1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.dx.io; 18 19import com.android.dx.util.ByteInput; 20import com.android.dx.util.Leb128Utils; 21 22/** 23 * SAX-style reader for encoded values. 24 * TODO: convert this to a pull-style reader 25 */ 26public class EncodedValueReader { 27 public static final int ENCODED_BYTE = 0x00; 28 public static final int ENCODED_SHORT = 0x02; 29 public static final int ENCODED_CHAR = 0x03; 30 public static final int ENCODED_INT = 0x04; 31 public static final int ENCODED_LONG = 0x06; 32 public static final int ENCODED_FLOAT = 0x10; 33 public static final int ENCODED_DOUBLE = 0x11; 34 public static final int ENCODED_STRING = 0x17; 35 public static final int ENCODED_TYPE = 0x18; 36 public static final int ENCODED_FIELD = 0x19; 37 public static final int ENCODED_ENUM = 0x1b; 38 public static final int ENCODED_METHOD = 0x1a; 39 public static final int ENCODED_ARRAY = 0x1c; 40 public static final int ENCODED_ANNOTATION = 0x1d; 41 public static final int ENCODED_NULL = 0x1e; 42 public static final int ENCODED_BOOLEAN = 0x1f; 43 44 protected final ByteInput in; 45 46 public EncodedValueReader(ByteInput in) { 47 this.in = in; 48 } 49 50 public EncodedValueReader(EncodedValue in) { 51 this(in.asByteInput()); 52 } 53 54 public final void readArray() { 55 int size = Leb128Utils.readUnsignedLeb128(in); 56 visitArray(size); 57 58 for (int i = 0; i < size; i++) { 59 readValue(); 60 } 61 } 62 63 public final void readAnnotation() { 64 int typeIndex = Leb128Utils.readUnsignedLeb128(in); 65 int size = Leb128Utils.readUnsignedLeb128(in); 66 visitAnnotation(typeIndex, size); 67 68 for (int i = 0; i < size; i++) { 69 visitAnnotationName(Leb128Utils.readUnsignedLeb128(in)); 70 readValue(); 71 } 72 } 73 74 public final void readValue() { 75 int argAndType = in.readByte() & 0xff; 76 int type = argAndType & 0x1f; 77 int arg = (argAndType & 0xe0) >> 5; 78 int size = arg + 1; 79 80 switch (type) { 81 case ENCODED_BYTE: 82 case ENCODED_SHORT: 83 case ENCODED_CHAR: 84 case ENCODED_INT: 85 case ENCODED_LONG: 86 case ENCODED_FLOAT: 87 case ENCODED_DOUBLE: 88 visitPrimitive(argAndType, type, arg, size); 89 break; 90 case ENCODED_STRING: 91 visitString(type, readIndex(in, size)); 92 break; 93 case ENCODED_TYPE: 94 visitType(type, readIndex(in, size)); 95 break; 96 case ENCODED_FIELD: 97 case ENCODED_ENUM: 98 visitField(type, readIndex(in, size)); 99 break; 100 case ENCODED_METHOD: 101 visitMethod(type, readIndex(in, size)); 102 break; 103 case ENCODED_ARRAY: 104 visitArrayValue(argAndType); 105 readArray(); 106 break; 107 case ENCODED_ANNOTATION: 108 visitAnnotationValue(argAndType); 109 readAnnotation(); 110 break; 111 case ENCODED_NULL: 112 visitEncodedNull(argAndType); 113 break; 114 case ENCODED_BOOLEAN: 115 visitEncodedBoolean(argAndType); 116 break; 117 } 118 } 119 120 protected void visitArray(int size) {} 121 protected void visitAnnotation(int typeIndex, int size) {} 122 protected void visitAnnotationName(int nameIndex) {} 123 protected void visitPrimitive(int argAndType, int type, int arg, int size) { 124 for (int i = 0; i < size; i++) { 125 in.readByte(); 126 } 127 } 128 protected void visitString(int type, int index) {} 129 protected void visitType(int type, int index) {} 130 protected void visitField(int type, int index) {} 131 protected void visitMethod(int type, int index) {} 132 protected void visitArrayValue(int argAndType) {} 133 protected void visitAnnotationValue(int argAndType) {} 134 protected void visitEncodedBoolean(int argAndType) {} 135 protected void visitEncodedNull(int argAndType) {} 136 137 private int readIndex(ByteInput in, int byteCount) { 138 int result = 0; 139 int shift = 0; 140 for (int i = 0; i < byteCount; i++) { 141 result += (in.readByte() & 0xff) << shift; 142 shift += 8; 143 } 144 return result; 145 } 146} 147