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