/* * Copyright (C) 2011 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.io; import com.android.dx.util.ByteInput; import com.android.dx.util.Leb128Utils; /** * SAX-style reader for encoded values. * TODO: convert this to a pull-style reader */ public class EncodedValueReader { public static final int ENCODED_BYTE = 0x00; public static final int ENCODED_SHORT = 0x02; public static final int ENCODED_CHAR = 0x03; public static final int ENCODED_INT = 0x04; public static final int ENCODED_LONG = 0x06; public static final int ENCODED_FLOAT = 0x10; public static final int ENCODED_DOUBLE = 0x11; public static final int ENCODED_STRING = 0x17; public static final int ENCODED_TYPE = 0x18; public static final int ENCODED_FIELD = 0x19; public static final int ENCODED_ENUM = 0x1b; public static final int ENCODED_METHOD = 0x1a; public static final int ENCODED_ARRAY = 0x1c; public static final int ENCODED_ANNOTATION = 0x1d; public static final int ENCODED_NULL = 0x1e; public static final int ENCODED_BOOLEAN = 0x1f; protected final ByteInput in; public EncodedValueReader(ByteInput in) { this.in = in; } public EncodedValueReader(EncodedValue in) { this(in.asByteInput()); } public final void readArray() { int size = Leb128Utils.readUnsignedLeb128(in); visitArray(size); for (int i = 0; i < size; i++) { readValue(); } } public final void readAnnotation() { int typeIndex = Leb128Utils.readUnsignedLeb128(in); int size = Leb128Utils.readUnsignedLeb128(in); visitAnnotation(typeIndex, size); for (int i = 0; i < size; i++) { visitAnnotationName(Leb128Utils.readUnsignedLeb128(in)); readValue(); } } public final void readValue() { int argAndType = in.readByte() & 0xff; int type = argAndType & 0x1f; int arg = (argAndType & 0xe0) >> 5; int size = arg + 1; switch (type) { case ENCODED_BYTE: case ENCODED_SHORT: case ENCODED_CHAR: case ENCODED_INT: case ENCODED_LONG: case ENCODED_FLOAT: case ENCODED_DOUBLE: visitPrimitive(argAndType, type, arg, size); break; case ENCODED_STRING: visitString(type, readIndex(in, size)); break; case ENCODED_TYPE: visitType(type, readIndex(in, size)); break; case ENCODED_FIELD: case ENCODED_ENUM: visitField(type, readIndex(in, size)); break; case ENCODED_METHOD: visitMethod(type, readIndex(in, size)); break; case ENCODED_ARRAY: visitArrayValue(argAndType); readArray(); break; case ENCODED_ANNOTATION: visitAnnotationValue(argAndType); readAnnotation(); break; case ENCODED_NULL: visitEncodedNull(argAndType); break; case ENCODED_BOOLEAN: visitEncodedBoolean(argAndType); break; } } protected void visitArray(int size) {} protected void visitAnnotation(int typeIndex, int size) {} protected void visitAnnotationName(int nameIndex) {} protected void visitPrimitive(int argAndType, int type, int arg, int size) { for (int i = 0; i < size; i++) { in.readByte(); } } protected void visitString(int type, int index) {} protected void visitType(int type, int index) {} protected void visitField(int type, int index) {} protected void visitMethod(int type, int index) {} protected void visitArrayValue(int argAndType) {} protected void visitAnnotationValue(int argAndType) {} protected void visitEncodedBoolean(int argAndType) {} protected void visitEncodedNull(int argAndType) {} private int readIndex(ByteInput in, int byteCount) { int result = 0; int shift = 0; for (int i = 0; i < byteCount; i++) { result += (in.readByte() & 0xff) << shift; shift += 8; } return result; } }