/*
* dex2jar - Tools to work with android .dex and java .class files
* Copyright (c) 2009-2013 Panxiaobo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.d2j.dex.writer.item;
import com.googlecode.d2j.dex.writer.ann.Idx;
import com.googlecode.d2j.dex.writer.ann.Off;
import com.googlecode.d2j.dex.writer.ev.EncodedValue;
import com.googlecode.d2j.dex.writer.io.DataOut;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ClassDataItem extends BaseItem {
public final List<EncodedField> staticFields = new ArrayList<>(5);
public final List<EncodedField> instanceFields = new ArrayList<>(5);
public final List<EncodedMethod> directMethods = new ArrayList<>(5);
public final List<EncodedMethod> virtualMethods = new ArrayList<>(5);
@Override
public int place(int offset) {
offset += lengthOfUleb128(staticFields.size());
offset += lengthOfUleb128(instanceFields.size());
offset += lengthOfUleb128(directMethods.size());
offset += lengthOfUleb128(virtualMethods.size());
offset = placeField(offset, staticFields);
offset = placeField(offset, instanceFields);
offset = placeMethod(offset, directMethods);
offset = placeMethod(offset, virtualMethods);
return offset;
}
private int placeMethod(int offset, List<EncodedMethod> methods) {
if (methods.size() == 0) {
return offset;
}
int lastIdx = 0;
for (EncodedMethod f : methods) {
offset += lengthOfUleb128(f.method.index - lastIdx);
offset += lengthOfUleb128(f.accessFlags);
offset += lengthOfUleb128(f.code == null ? 0 : f.code.offset);
lastIdx = f.method.index;
}
return offset;
}
private int placeField(int offset, List<EncodedField> fields) {
if (fields.size() == 0) {
return offset;
}
int lastIdx = 0;
for (EncodedField f : fields) {
offset += lengthOfUleb128(f.field.index - lastIdx);
offset += lengthOfUleb128(f.accessFlags);
lastIdx = f.field.index;
}
return offset;
}
@Override
public void write(DataOut out) {
out.uleb128("static_fields_size", staticFields.size());
out.uleb128("instance_fields_size", instanceFields.size());
out.uleb128("ditect_methods_size", directMethods.size());
out.uleb128("virtual_methods_size", virtualMethods.size());
writeField(out, staticFields);
writeField(out, instanceFields);
writeMethod(out, directMethods);
writeMethod(out, virtualMethods);
}
private void writeMethod(DataOut out, List<EncodedMethod> methods) {
if (methods == null || methods.size() == 0) {
return;
}
int lastIdx = 0;
for (EncodedMethod f : methods) {
out.uleb128("method_idx_diff", f.method.index - lastIdx);
out.uleb128("access_flags", f.accessFlags);
out.uleb128("code_off", f.code == null ? 0 : f.code.offset);
lastIdx = f.method.index;
}
}
private void writeField(DataOut out, List<EncodedField> fields) {
if (fields == null || fields.size() == 0) {
return;
}
int lastIdx = 0;
for (EncodedField f : fields) {
out.uleb128("field_idx_diff", f.field.index - lastIdx);
out.uleb128("access_flags", f.accessFlags);
lastIdx = f.field.index;
}
}
public int getMemberSize() {
return instanceFields.size() + staticFields.size() + directMethods.size() + virtualMethods.size();
}
public void prepare(ConstPool cp) {
Comparator<EncodedField> fc = new Comparator<EncodedField>() {
@Override
public int compare(EncodedField arg0, EncodedField arg1) {
return arg0.field.compareTo(arg1.field);
}
};
Comparator<EncodedMethod> mc = new
Comparator<EncodedMethod>() {
@Override
public int compare(EncodedMethod arg0, EncodedMethod arg1) {
return arg0.method.compareTo(arg1.method);
}
};
Collections.sort(instanceFields, fc);
Collections.sort(staticFields, fc);
Collections.sort(directMethods, mc);
Collections.sort(virtualMethods, mc);
}
public static class EncodedField {
public int accessFlags;
@Idx
public FieldIdItem field;
public EncodedValue staticValue;
public AnnotationSetItem annotationSetItem;
}
public static class EncodedMethod {
public int accessFlags;
@Idx
public MethodIdItem method;
@Off
public CodeItem code;
//
public AnnotationSetItem annotationSetItem;
public AnnotationSetRefListItem parameterAnnotation;
}
}