summaryrefslogtreecommitdiffstats
path: root/dx/src/com/android/dx/dex/file/ValueEncoder.java
diff options
context:
space:
mode:
Diffstat (limited to 'dx/src/com/android/dx/dex/file/ValueEncoder.java')
-rw-r--r--dx/src/com/android/dx/dex/file/ValueEncoder.java532
1 files changed, 0 insertions, 532 deletions
diff --git a/dx/src/com/android/dx/dex/file/ValueEncoder.java b/dx/src/com/android/dx/dex/file/ValueEncoder.java
deleted file mode 100644
index 02a34194f..000000000
--- a/dx/src/com/android/dx/dex/file/ValueEncoder.java
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * 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.android.dx.dex.file;
-
-import com.android.dx.rop.annotation.Annotation;
-import com.android.dx.rop.annotation.NameValuePair;
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.CstAnnotation;
-import com.android.dx.rop.cst.CstArray;
-import com.android.dx.rop.cst.CstBoolean;
-import com.android.dx.rop.cst.CstByte;
-import com.android.dx.rop.cst.CstChar;
-import com.android.dx.rop.cst.CstDouble;
-import com.android.dx.rop.cst.CstEnumRef;
-import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstFloat;
-import com.android.dx.rop.cst.CstInteger;
-import com.android.dx.rop.cst.CstKnownNull;
-import com.android.dx.rop.cst.CstLiteralBits;
-import com.android.dx.rop.cst.CstLong;
-import com.android.dx.rop.cst.CstMethodRef;
-import com.android.dx.rop.cst.CstShort;
-import com.android.dx.rop.cst.CstString;
-import com.android.dx.rop.cst.CstType;
-import com.android.dx.rop.cst.CstUtf8;
-import com.android.dx.util.AnnotatedOutput;
-import com.android.dx.util.Hex;
-
-import java.util.Collection;
-
-/**
- * Handler for writing out <code>encoded_values</code> and parts
- * thereof.
- */
-public final class ValueEncoder {
- /** annotation value type constant: <code>byte</code> */
- private static final int VALUE_BYTE = 0x00;
-
- /** annotation value type constant: <code>short</code> */
- private static final int VALUE_SHORT = 0x02;
-
- /** annotation value type constant: <code>char</code> */
- private static final int VALUE_CHAR = 0x03;
-
- /** annotation value type constant: <code>int</code> */
- private static final int VALUE_INT = 0x04;
-
- /** annotation value type constant: <code>long</code> */
- private static final int VALUE_LONG = 0x06;
-
- /** annotation value type constant: <code>float</code> */
- private static final int VALUE_FLOAT = 0x10;
-
- /** annotation value type constant: <code>double</code> */
- private static final int VALUE_DOUBLE = 0x11;
-
- /** annotation value type constant: <code>string</code> */
- private static final int VALUE_STRING = 0x17;
-
- /** annotation value type constant: <code>type</code> */
- private static final int VALUE_TYPE = 0x18;
-
- /** annotation value type constant: <code>field</code> */
- private static final int VALUE_FIELD = 0x19;
-
- /** annotation value type constant: <code>method</code> */
- private static final int VALUE_METHOD = 0x1a;
-
- /** annotation value type constant: <code>enum</code> */
- private static final int VALUE_ENUM = 0x1b;
-
- /** annotation value type constant: <code>array</code> */
- private static final int VALUE_ARRAY = 0x1c;
-
- /** annotation value type constant: <code>annotation</code> */
- private static final int VALUE_ANNOTATION = 0x1d;
-
- /** annotation value type constant: <code>null</code> */
- private static final int VALUE_NULL = 0x1e;
-
- /** annotation value type constant: <code>boolean</code> */
- private static final int VALUE_BOOLEAN = 0x1f;
-
- /** non-null; file being written */
- private final DexFile file;
-
- /** non-null; output stream to write to */
- private final AnnotatedOutput out;
-
- /**
- * Construct an instance.
- *
- * @param file non-null; file being written
- * @param out non-null; output stream to write to
- */
- public ValueEncoder(DexFile file, AnnotatedOutput out) {
- if (file == null) {
- throw new NullPointerException("file == null");
- }
-
- if (out == null) {
- throw new NullPointerException("out == null");
- }
-
- this.file = file;
- this.out = out;
- }
-
- /**
- * Writes out the encoded form of the given constant.
- *
- * @param cst non-null; the constant to write
- */
- public void writeConstant(Constant cst) {
- int type = constantToValueType(cst);
- int arg;
-
- switch (type) {
- case VALUE_BYTE:
- case VALUE_SHORT:
- case VALUE_INT:
- case VALUE_LONG: {
- long value = ((CstLiteralBits) cst).getLongBits();
- writeSignedIntegralValue(type, value);
- break;
- }
- case VALUE_CHAR: {
- long value = ((CstLiteralBits) cst).getLongBits();
- writeUnsignedIntegralValue(type, value);
- break;
- }
- case VALUE_FLOAT: {
- // Shift value left 32 so that right-zero-extension works.
- long value = ((CstFloat) cst).getLongBits() << 32;
- writeRightZeroExtendedValue(type, value);
- break;
- }
- case VALUE_DOUBLE: {
- long value = ((CstDouble) cst).getLongBits();
- writeRightZeroExtendedValue(type, value);
- break;
- }
- case VALUE_STRING: {
- int index = file.getStringIds().indexOf((CstString) cst);
- writeUnsignedIntegralValue(type, (long) index);
- break;
- }
- case VALUE_TYPE: {
- int index = file.getTypeIds().indexOf((CstType) cst);
- writeUnsignedIntegralValue(type, (long) index);
- break;
- }
- case VALUE_FIELD: {
- int index = file.getFieldIds().indexOf((CstFieldRef) cst);
- writeUnsignedIntegralValue(type, (long) index);
- break;
- }
- case VALUE_METHOD: {
- int index = file.getMethodIds().indexOf((CstMethodRef) cst);
- writeUnsignedIntegralValue(type, (long) index);
- break;
- }
- case VALUE_ENUM: {
- CstFieldRef fieldRef = ((CstEnumRef) cst).getFieldRef();
- int index = file.getFieldIds().indexOf(fieldRef);
- writeUnsignedIntegralValue(type, (long) index);
- break;
- }
- case VALUE_ARRAY: {
- out.writeByte(type);
- writeArray((CstArray) cst, false);
- break;
- }
- case VALUE_ANNOTATION: {
- out.writeByte(type);
- writeAnnotation(((CstAnnotation) cst).getAnnotation(),
- false);
- break;
- }
- case VALUE_NULL: {
- out.writeByte(type);
- break;
- }
- case VALUE_BOOLEAN: {
- int value = ((CstBoolean) cst).getIntBits();
- out.writeByte(type | (value << 5));
- break;
- }
- default: {
- throw new RuntimeException("Shouldn't happen");
- }
- }
- }
-
- /**
- * Gets the value type for the given constant.
- *
- * @param cst non-null; the constant
- * @return the value type; one of the <code>VALUE_*</code> constants
- * defined by this class
- */
- private static int constantToValueType(Constant cst) {
- /*
- * TODO: Constant should probable have an associated enum, so this
- * can be a switch().
- */
- if (cst instanceof CstByte) {
- return VALUE_BYTE;
- } else if (cst instanceof CstShort) {
- return VALUE_SHORT;
- } else if (cst instanceof CstChar) {
- return VALUE_CHAR;
- } else if (cst instanceof CstInteger) {
- return VALUE_INT;
- } else if (cst instanceof CstLong) {
- return VALUE_LONG;
- } else if (cst instanceof CstFloat) {
- return VALUE_FLOAT;
- } else if (cst instanceof CstDouble) {
- return VALUE_DOUBLE;
- } else if (cst instanceof CstString) {
- return VALUE_STRING;
- } else if (cst instanceof CstType) {
- return VALUE_TYPE;
- } else if (cst instanceof CstFieldRef) {
- return VALUE_FIELD;
- } else if (cst instanceof CstMethodRef) {
- return VALUE_METHOD;
- } else if (cst instanceof CstEnumRef) {
- return VALUE_ENUM;
- } else if (cst instanceof CstArray) {
- return VALUE_ARRAY;
- } else if (cst instanceof CstAnnotation) {
- return VALUE_ANNOTATION;
- } else if (cst instanceof CstKnownNull) {
- return VALUE_NULL;
- } else if (cst instanceof CstBoolean) {
- return VALUE_BOOLEAN;
- } else {
- throw new RuntimeException("Shouldn't happen");
- }
- }
-
- /**
- * Writes out the encoded form of the given array, that is, as
- * an <code>encoded_array</code> and not including a
- * <code>value_type</code> prefix. If the output stream keeps
- * (debugging) annotations and <code>topLevel</code> is
- * <code>true</code>, then this method will write (debugging)
- * annotations.
- *
- * @param array non-null; array instance to write
- * @param topLevel <code>true</code> iff the given annotation is the
- * top-level annotation or <code>false</code> if it is a sub-annotation
- * of some other annotation
- */
- public void writeArray(CstArray array, boolean topLevel) {
- boolean annotates = topLevel && out.annotates();
- CstArray.List list = ((CstArray) array).getList();
- int size = list.size();
-
- if (annotates) {
- out.annotate(" size: " + Hex.u4(size));
- }
-
- out.writeUnsignedLeb128(size);
-
- for (int i = 0; i < size; i++) {
- Constant cst = list.get(i);
- if (annotates) {
- out.annotate(" [" + Integer.toHexString(i) + "] " +
- constantToHuman(cst));
- }
- writeConstant(cst);
- }
-
- if (annotates) {
- out.endAnnotation();
- }
- }
-
- /**
- * Writes out the encoded form of the given annotation, that is,
- * as an <code>encoded_annotation</code> and not including a
- * <code>value_type</code> prefix. If the output stream keeps
- * (debugging) annotations and <code>topLevel</code> is
- * <code>true</code>, then this method will write (debugging)
- * annotations.
- *
- * @param annotation non-null; annotation instance to write
- * @param topLevel <code>true</code> iff the given annotation is the
- * top-level annotation or <code>false</code> if it is a sub-annotation
- * of some other annotation
- */
- public void writeAnnotation(Annotation annotation, boolean topLevel) {
- boolean annotates = topLevel && out.annotates();
- StringIdsSection stringIds = file.getStringIds();
- TypeIdsSection typeIds = file.getTypeIds();
-
- CstType type = annotation.getType();
- int typeIdx = typeIds.indexOf(type);
-
- if (annotates) {
- out.annotate(" type_idx: " + Hex.u4(typeIdx) + " // " +
- type.toHuman());
- }
-
- out.writeUnsignedLeb128(typeIds.indexOf(annotation.getType()));
-
- Collection<NameValuePair> pairs = annotation.getNameValuePairs();
- int size = pairs.size();
-
- if (annotates) {
- out.annotate(" size: " + Hex.u4(size));
- }
-
- out.writeUnsignedLeb128(size);
-
- int at = 0;
- for (NameValuePair pair : pairs) {
- CstUtf8 name = pair.getName();
- int nameIdx = stringIds.indexOf(name);
- Constant value = pair.getValue();
-
- if (annotates) {
- out.annotate(0, " elements[" + at + "]:");
- at++;
- out.annotate(" name_idx: " + Hex.u4(nameIdx) + " // " +
- name.toHuman());
- }
-
- out.writeUnsignedLeb128(nameIdx);
-
- if (annotates) {
- out.annotate(" value: " + constantToHuman(value));
- }
-
- writeConstant(value);
- }
-
- if (annotates) {
- out.endAnnotation();
- }
- }
-
- /**
- * Gets the colloquial type name and human form of the type of the
- * given constant, when used as an encoded value.
- *
- * @param cst non-null; the constant
- * @return non-null; its type name and human form
- */
- public static String constantToHuman(Constant cst) {
- int type = constantToValueType(cst);
-
- if (type == VALUE_NULL) {
- return "null";
- }
-
- StringBuilder sb = new StringBuilder();
-
- sb.append(cst.typeName());
- sb.append(' ');
- sb.append(cst.toHuman());
-
- return sb.toString();
- }
-
- /**
- * Helper for {@link #writeConstant}, which writes out the value
- * for any signed integral type.
- *
- * @param type the type constant
- * @param value <code>long</code> bits of the value
- */
- private void writeSignedIntegralValue(int type, long value) {
- /*
- * Figure out how many bits are needed to represent the value,
- * including a sign bit: The bit count is subtracted from 65
- * and not 64 to account for the sign bit. The xor operation
- * has the effect of leaving non-negative values alone and
- * unary complementing negative values (so that a leading zero
- * count always returns a useful number for our present
- * purpose).
- */
- int requiredBits =
- 65 - Long.numberOfLeadingZeros(value ^ (value >> 63));
-
- // Round up the requiredBits to a number of bytes.
- int requiredBytes = (requiredBits + 0x07) >> 3;
-
- /*
- * Write the header byte, which includes the type and
- * requiredBytes - 1.
- */
- out.writeByte(type | ((requiredBytes - 1) << 5));
-
- // Write the value, per se.
- while (requiredBytes > 0) {
- out.writeByte((byte) value);
- value >>= 8;
- requiredBytes--;
- }
- }
-
- /**
- * Helper for {@link #writeConstant}, which writes out the value
- * for any unsigned integral type.
- *
- * @param type the type constant
- * @param value <code>long</code> bits of the value
- */
- private void writeUnsignedIntegralValue(int type, long value) {
- // Figure out how many bits are needed to represent the value.
- int requiredBits = 64 - Long.numberOfLeadingZeros(value);
- if (requiredBits == 0) {
- requiredBits = 1;
- }
-
- // Round up the requiredBits to a number of bytes.
- int requiredBytes = (requiredBits + 0x07) >> 3;
-
- /*
- * Write the header byte, which includes the type and
- * requiredBytes - 1.
- */
- out.writeByte(type | ((requiredBytes - 1) << 5));
-
- // Write the value, per se.
- while (requiredBytes > 0) {
- out.writeByte((byte) value);
- value >>= 8;
- requiredBytes--;
- }
- }
-
- /**
- * Helper for {@link #writeConstant}, which writes out a
- * right-zero-extended value.
- *
- * @param type the type constant
- * @param value <code>long</code> bits of the value
- */
- private void writeRightZeroExtendedValue(int type, long value) {
- // Figure out how many bits are needed to represent the value.
- int requiredBits = 64 - Long.numberOfTrailingZeros(value);
- if (requiredBits == 0) {
- requiredBits = 1;
- }
-
- // Round up the requiredBits to a number of bytes.
- int requiredBytes = (requiredBits + 0x07) >> 3;
-
- // Scootch the first bits to be written down to the low-order bits.
- value >>= 64 - (requiredBytes * 8);
-
- /*
- * Write the header byte, which includes the type and
- * requiredBytes - 1.
- */
- out.writeByte(type | ((requiredBytes - 1) << 5));
-
- // Write the value, per se.
- while (requiredBytes > 0) {
- out.writeByte((byte) value);
- value >>= 8;
- requiredBytes--;
- }
- }
-
-
- /**
- * Helper for <code>addContents()</code> methods, which adds
- * contents for a particular {@link Annotation}, calling itself
- * recursively should it encounter a nested annotation.
- *
- * @param file non-null; the file to add to
- * @param annotation non-null; the annotation to add contents for
- */
- public static void addContents(DexFile file, Annotation annotation) {
- TypeIdsSection typeIds = file.getTypeIds();
- StringIdsSection stringIds = file.getStringIds();
-
- typeIds.intern(annotation.getType());
-
- for (NameValuePair pair : annotation.getNameValuePairs()) {
- stringIds.intern(pair.getName());
- addContents(file, pair.getValue());
- }
- }
-
- /**
- * Helper for <code>addContents()</code> methods, which adds
- * contents for a particular constant, calling itself recursively
- * should it encounter a {@link CstArray} and calling {@link
- * #addContents(DexFile,Annotation)} recursively should it
- * encounter a {@link CstAnnotation}.
- *
- * @param file non-null; the file to add to
- * @param cst non-null; the constant to add contents for
- */
- public static void addContents(DexFile file, Constant cst) {
- TypeIdsSection typeIds = file.getTypeIds();
- StringIdsSection stringIds = file.getStringIds();
-
- if (cst instanceof CstAnnotation) {
- addContents(file, ((CstAnnotation) cst).getAnnotation());
- } else if (cst instanceof CstArray) {
- CstArray.List list = ((CstArray) cst).getList();
- int size = list.size();
- for (int i = 0; i < size; i++) {
- addContents(file, list.get(i));
- }
- } else {
- file.internIfAppropriate(cst);
- }
- }
-}