1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.util; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.Writer; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implementation of {@link AnnotatedOutput} which stores the written data 2599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * into a {@code byte[]}. 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p><b>Note:</b> As per the {@link Output} interface, multi-byte 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * writes all use little-endian order.</p> 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class ByteArrayAnnotatedOutput 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project implements AnnotatedOutput { 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** default size for stretchy instances */ 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int DEFAULT_SIZE = 1000; 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * whether the instance is stretchy, that is, whether its array 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * may be resized to increase capacity 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final boolean stretchy; 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 4199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} the data itself */ 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private byte[] data; 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 4499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code >= 0;} current output cursor */ 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int cursor; 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** whether annotations are to be verbose */ 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private boolean verbose; 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 5199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code null-ok;} list of annotations, or {@code null} if this instance 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * isn't keeping them 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private ArrayList<Annotation> annotations; 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 5699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code >= 40 (if used);} the desired maximum annotation width */ 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int annotationWidth; 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 6099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code >= 8 (if used);} the number of bytes of hex output to use 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in annotations 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int hexCols; 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance with a fixed maximum size. Note that the 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * given array is the only one that will be used to store data. In 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * particular, no reallocation will occur in order to expand the 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * capacity of the resulting instance. Also, the constructed 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instance does not keep annotations by default. 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 7299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param data {@code non-null;} data array to use for output 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ByteArrayAnnotatedOutput(byte[] data) { 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this(data, false); 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs a "stretchy" instance. The underlying array may be 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reallocated. The constructed instance does not keep annotations 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by default. 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ByteArrayAnnotatedOutput() { 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this(new byte[DEFAULT_SIZE], true); 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Internal constructor. 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 9099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param data {@code non-null;} data array to use for output 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param stretchy whether the instance is to be stretchy 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private ByteArrayAnnotatedOutput(byte[] data, boolean stretchy) { 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (data == null) { 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("data == null"); 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.stretchy = stretchy; 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.data = data; 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.cursor = 0; 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.verbose = false; 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.annotations = null; 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.annotationWidth = 0; 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.hexCols = 0; 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 10899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Gets the underlying {@code byte[]} of this instance, which 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * may be larger than the number of bytes written 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see #toByteArray 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 11399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the {@code byte[]} 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public byte[] getArray() { 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return data; 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 12099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Constructs and returns a new {@code byte[]} that contains 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the written contents exactly (that is, with no extra unwritten 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bytes at the end). 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see #getArray 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 12699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} an appropriately-constructed array 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public byte[] toByteArray() { 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] result = new byte[cursor]; 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(data, 0, result, 0, cursor); 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getCursor() { 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return cursor; 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void assertCursor(int expectedCursor) { 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cursor != expectedCursor) { 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new ExceptionWithContext("expected cursor " + 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project expectedCursor + "; actual value: " + cursor); 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void writeByte(int value) { 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int writeAt = cursor; 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int end = writeAt + 1; 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stretchy) { 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ensureCapacity(end); 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (end > data.length) { 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwBounds(); 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt] = (byte) value; 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cursor = end; 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void writeShort(int value) { 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int writeAt = cursor; 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int end = writeAt + 2; 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stretchy) { 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ensureCapacity(end); 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (end > data.length) { 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwBounds(); 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt] = (byte) value; 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt + 1] = (byte) (value >> 8); 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cursor = end; 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void writeInt(int value) { 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int writeAt = cursor; 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int end = writeAt + 4; 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stretchy) { 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ensureCapacity(end); 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (end > data.length) { 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwBounds(); 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt] = (byte) value; 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt + 1] = (byte) (value >> 8); 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt + 2] = (byte) (value >> 16); 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt + 3] = (byte) (value >> 24); 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cursor = end; 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void writeLong(long value) { 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int writeAt = cursor; 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int end = writeAt + 8; 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stretchy) { 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ensureCapacity(end); 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (end > data.length) { 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwBounds(); 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int half = (int) value; 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt] = (byte) half; 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt + 1] = (byte) (half >> 8); 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt + 2] = (byte) (half >> 16); 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt + 3] = (byte) (half >> 24); 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project half = (int) (value >> 32); 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt + 4] = (byte) half; 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt + 5] = (byte) (half >> 8); 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt + 6] = (byte) (half >> 16); 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data[writeAt + 7] = (byte) (half >> 24); 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cursor = end; 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int writeUnsignedLeb128(int value) { 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int remaining = value >> 7; 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int count = 0; 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (remaining != 0) { 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project writeByte((value & 0x7f) | 0x80); 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project value = remaining; 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project remaining >>= 7; 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project count++; 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project writeByte(value & 0x7f); 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return count + 1; 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int writeSignedLeb128(int value) { 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int remaining = value >> 7; 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int count = 0; 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean hasMore = true; 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1; 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (hasMore) { 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hasMore = (remaining != end) 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project || ((remaining & 1) != ((value >> 6) & 1)); 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project writeByte((value & 0x7f) | (hasMore ? 0x80 : 0)); 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project value = remaining; 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project remaining >>= 7; 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project count++; 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return count; 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void write(ByteArray bytes) { 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int blen = bytes.size(); 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int writeAt = cursor; 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int end = writeAt + blen; 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stretchy) { 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ensureCapacity(end); 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (end > data.length) { 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwBounds(); 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytes.getBytes(data, writeAt); 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cursor = end; 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void write(byte[] bytes, int offset, int length) { 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int writeAt = cursor; 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int end = writeAt + length; 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int bytesEnd = offset + length; 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // twos-complement math trick: ((x < 0) || (y < 0)) <=> ((x|y) < 0) 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (((offset | length | end) < 0) || (bytesEnd > bytes.length)) { 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IndexOutOfBoundsException("bytes.length " + 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytes.length + "; " + 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project offset + "..!" + end); 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stretchy) { 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ensureCapacity(end); 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (end > data.length) { 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwBounds(); 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(bytes, offset, data, writeAt, length); 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cursor = end; 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void write(byte[] bytes) { 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project write(bytes, 0, bytes.length); 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void writeZeroes(int count) { 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (count < 0) { 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("count < 0"); 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int end = cursor + count; 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stretchy) { 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ensureCapacity(end); 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (end > data.length) { 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwBounds(); 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There is no need to actually write zeroes, since the array is 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * already preinitialized with zeroes. 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cursor = end; 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void alignTo(int alignment) { 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int mask = alignment - 1; 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((alignment < 0) || ((mask & alignment) != 0)) { 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("bogus alignment"); 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int end = (cursor + mask) & ~mask; 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stretchy) { 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ensureCapacity(end); 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (end > data.length) { 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwBounds(); 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There is no need to actually write zeroes, since the array is 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * already preinitialized with zeroes. 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cursor = end; 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean annotates() { 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (annotations != null); 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean isVerbose() { 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return verbose; 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void annotate(String msg) { 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (annotations == null) { 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endAnnotation(); 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project annotations.add(new Annotation(cursor, msg)); 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void annotate(int amt, String msg) { 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (annotations == null) { 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endAnnotation(); 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int asz = annotations.size(); 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int lastEnd = (asz == 0) ? 0 : annotations.get(asz - 1).getEnd(); 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int startAt; 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (lastEnd <= cursor) { 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project startAt = cursor; 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project startAt = lastEnd; 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project annotations.add(new Annotation(startAt, startAt + amt, msg)); 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void endAnnotation() { 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (annotations == null) { 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int sz = annotations.size(); 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (sz != 0) { 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project annotations.get(sz - 1).setEndIfUnset(cursor); 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getAnnotationWidth() { 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int leftWidth = 8 + (hexCols * 2) + (hexCols / 2); 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return annotationWidth - leftWidth; 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Indicates that this instance should keep annotations. This method may 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be called only once per instance, and only before any data has been 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * written to the it. 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 42299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param annotationWidth {@code >= 40;} the desired maximum annotation width 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param verbose whether or not to indicate verbose annotations 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void enableAnnotations(int annotationWidth, boolean verbose) { 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((annotations != null) || (cursor != 0)) { 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new RuntimeException("cannot enable annotations"); 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (annotationWidth < 40) { 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("annotationWidth < 40"); 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int hexCols = (((annotationWidth - 7) / 15) + 1) & ~1; 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (hexCols < 6) { 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hexCols = 6; 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (hexCols > 10) { 438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hexCols = 10; 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.annotations = new ArrayList<Annotation>(1000); 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.annotationWidth = annotationWidth; 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.hexCols = hexCols; 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.verbose = verbose; 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Finishes up annotation processing. This closes off any open 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * annotations and removes annotations that don't refer to written 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data. 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void finishAnnotating() { 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Close off the final annotation, if any. 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endAnnotation(); 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Remove annotations that refer to unwritten data. 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (annotations != null) { 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int asz = annotations.size(); 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (asz > 0) { 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Annotation last = annotations.get(asz - 1); 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (last.getStart() > cursor) { 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project annotations.remove(asz - 1); 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project asz--; 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (last.getEnd() > cursor) { 465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project last.setEnd(cursor); 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Writes the annotated content of this instance to the given writer. 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 47799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param out {@code non-null;} where to write to 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void writeAnnotationsTo(Writer out) throws IOException { 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int width2 = getAnnotationWidth(); 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int width1 = annotationWidth - width2 - 1; 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project TwoColumnOutput twoc = new TwoColumnOutput(out, width1, width2, "|"); 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Writer left = twoc.getLeft(); 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Writer right = twoc.getRight(); 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int leftAt = 0; // left-hand byte output cursor 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int rightAt = 0; // right-hand annotation index 488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int rightSz = annotations.size(); 489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while ((leftAt < cursor) && (rightAt < rightSz)) { 491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Annotation a = annotations.get(rightAt); 492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int start = a.getStart(); 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int end; 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String text; 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (leftAt < start) { 497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // This is an area with no annotation. 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project end = start; 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = leftAt; 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project text = ""; 501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // This is an area with an annotation. 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project end = a.getEnd(); 504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project text = a.getText(); 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project rightAt++; 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project left.write(Hex.dump(data, start, end - start, start, hexCols, 6)); 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project right.write(text); 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project twoc.flush(); 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project leftAt = end; 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (leftAt < cursor) { 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // There is unannotated output at the end. 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project left.write(Hex.dump(data, leftAt, cursor - leftAt, leftAt, 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hexCols, 6)); 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (rightAt < rightSz) { 521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // There are zero-byte annotations at the end. 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project right.write(annotations.get(rightAt).getText()); 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project rightAt++; 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project twoc.flush(); 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Throws the excpetion for when an attempt is made to write past the 531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * end of the instance. 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static void throwBounds() { 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IndexOutOfBoundsException("attempt to write past the end"); 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reallocates the underlying array if necessary. Calls to this method 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should be guarded by a test of {@link #stretchy}. 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 54199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param desiredSize {@code >= 0;} the desired minimum total size of the array 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void ensureCapacity(int desiredSize) { 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (data.length < desiredSize) { 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] newData = new byte[desiredSize * 2 + 1000]; 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(data, 0, newData, 0, cursor); 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project data = newData; 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Annotation on output. 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static class Annotation { 55599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code >= 0;} start of annotated range (inclusive) */ 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final int start; 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 55999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code >= 0;} end of annotated range (exclusive); 56099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code Integer.MAX_VALUE} if unclosed 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int end; 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 56499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} annotation text */ 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final String text; 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 57099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param start {@code >= 0;} start of annotated range 57199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param end {@code >= start;} end of annotated range (exclusive) or 57299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code Integer.MAX_VALUE} if unclosed 57399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param text {@code non-null;} annotation text 574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Annotation(int start, int end, String text) { 576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.start = start; 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.end = end; 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.text = text; 579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. It is initally unclosed. 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 58499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param start {@code >= 0;} start of annotated range 58599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param text {@code non-null;} annotation text 586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Annotation(int start, String text) { 588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this(start, Integer.MAX_VALUE, text); 589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets the end as given, but only if the instance is unclosed; 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * otherwise, do nothing. 594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 59599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param end {@code >= start;} the end 596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void setEndIfUnset(int end) { 598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (this.end == Integer.MAX_VALUE) { 599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.end = end; 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets the end as given. 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 60699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param end {@code >= start;} the end 607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void setEnd(int end) { 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.end = end; 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the start. 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the start 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getStart() { 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return start; 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the end. 623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the end 625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getEnd() { 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return end; 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the text. 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 63399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the text 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String getText() { 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return text; 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 640