1 // ASM: a very small and fast Java bytecode manipulation framework 2 // Copyright (c) 2000-2011 INRIA, France Telecom 3 // All rights reserved. 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions 7 // are met: 8 // 1. Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // 3. Neither the name of the copyright holders nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 // THE POSSIBILITY OF SUCH DAMAGE. 28 package org.objectweb.asm; 29 30 /** 31 * A dynamically extensible vector of bytes. This class is roughly equivalent to a DataOutputStream 32 * on top of a ByteArrayOutputStream, but is more efficient. 33 * 34 * @author Eric Bruneton 35 */ 36 public class ByteVector { 37 38 /** The content of this vector. Only the first {@link #length} bytes contain real data. */ 39 byte[] data; 40 41 /** The actual number of bytes in this vector. */ 42 int length; 43 44 /** Constructs a new {@link ByteVector} with a default initial capacity. */ ByteVector()45 public ByteVector() { 46 data = new byte[64]; 47 } 48 49 /** 50 * Constructs a new {@link ByteVector} with the given initial capacity. 51 * 52 * @param initialCapacity the initial capacity of the byte vector to be constructed. 53 */ ByteVector(final int initialCapacity)54 public ByteVector(final int initialCapacity) { 55 data = new byte[initialCapacity]; 56 } 57 58 /** 59 * Constructs a new {@link ByteVector} from the given initial data. 60 * 61 * @param data the initial data of the new byte vector. 62 */ ByteVector(final byte[] data)63 ByteVector(final byte[] data) { 64 this.data = data; 65 this.length = data.length; 66 } 67 68 /** 69 * Returns the actual number of bytes in this vector. 70 * 71 * @return the actual number of bytes in this vector. 72 */ size()73 public int size() { 74 return length; 75 } 76 77 /** 78 * Puts a byte into this byte vector. The byte vector is automatically enlarged if necessary. 79 * 80 * @param byteValue a byte. 81 * @return this byte vector. 82 */ putByte(final int byteValue)83 public ByteVector putByte(final int byteValue) { 84 int currentLength = length; 85 if (currentLength + 1 > data.length) { 86 enlarge(1); 87 } 88 data[currentLength++] = (byte) byteValue; 89 length = currentLength; 90 return this; 91 } 92 93 /** 94 * Puts two bytes into this byte vector. The byte vector is automatically enlarged if necessary. 95 * 96 * @param byteValue1 a byte. 97 * @param byteValue2 another byte. 98 * @return this byte vector. 99 */ put11(final int byteValue1, final int byteValue2)100 final ByteVector put11(final int byteValue1, final int byteValue2) { 101 int currentLength = length; 102 if (currentLength + 2 > data.length) { 103 enlarge(2); 104 } 105 byte[] currentData = data; 106 currentData[currentLength++] = (byte) byteValue1; 107 currentData[currentLength++] = (byte) byteValue2; 108 length = currentLength; 109 return this; 110 } 111 112 /** 113 * Puts a short into this byte vector. The byte vector is automatically enlarged if necessary. 114 * 115 * @param shortValue a short. 116 * @return this byte vector. 117 */ putShort(final int shortValue)118 public ByteVector putShort(final int shortValue) { 119 int currentLength = length; 120 if (currentLength + 2 > data.length) { 121 enlarge(2); 122 } 123 byte[] currentData = data; 124 currentData[currentLength++] = (byte) (shortValue >>> 8); 125 currentData[currentLength++] = (byte) shortValue; 126 length = currentLength; 127 return this; 128 } 129 130 /** 131 * Puts a byte and a short into this byte vector. The byte vector is automatically enlarged if 132 * necessary. 133 * 134 * @param byteValue a byte. 135 * @param shortValue a short. 136 * @return this byte vector. 137 */ put12(final int byteValue, final int shortValue)138 final ByteVector put12(final int byteValue, final int shortValue) { 139 int currentLength = length; 140 if (currentLength + 3 > data.length) { 141 enlarge(3); 142 } 143 byte[] currentData = data; 144 currentData[currentLength++] = (byte) byteValue; 145 currentData[currentLength++] = (byte) (shortValue >>> 8); 146 currentData[currentLength++] = (byte) shortValue; 147 length = currentLength; 148 return this; 149 } 150 151 /** 152 * Puts two bytes and a short into this byte vector. The byte vector is automatically enlarged if 153 * necessary. 154 * 155 * @param byteValue1 a byte. 156 * @param byteValue2 another byte. 157 * @param shortValue a short. 158 * @return this byte vector. 159 */ put112(final int byteValue1, final int byteValue2, final int shortValue)160 final ByteVector put112(final int byteValue1, final int byteValue2, final int shortValue) { 161 int currentLength = length; 162 if (currentLength + 4 > data.length) { 163 enlarge(4); 164 } 165 byte[] currentData = data; 166 currentData[currentLength++] = (byte) byteValue1; 167 currentData[currentLength++] = (byte) byteValue2; 168 currentData[currentLength++] = (byte) (shortValue >>> 8); 169 currentData[currentLength++] = (byte) shortValue; 170 length = currentLength; 171 return this; 172 } 173 174 /** 175 * Puts an int into this byte vector. The byte vector is automatically enlarged if necessary. 176 * 177 * @param intValue an int. 178 * @return this byte vector. 179 */ putInt(final int intValue)180 public ByteVector putInt(final int intValue) { 181 int currentLength = length; 182 if (currentLength + 4 > data.length) { 183 enlarge(4); 184 } 185 byte[] currentData = data; 186 currentData[currentLength++] = (byte) (intValue >>> 24); 187 currentData[currentLength++] = (byte) (intValue >>> 16); 188 currentData[currentLength++] = (byte) (intValue >>> 8); 189 currentData[currentLength++] = (byte) intValue; 190 length = currentLength; 191 return this; 192 } 193 194 /** 195 * Puts one byte and two shorts into this byte vector. The byte vector is automatically enlarged 196 * if necessary. 197 * 198 * @param byteValue a byte. 199 * @param shortValue1 a short. 200 * @param shortValue2 another short. 201 * @return this byte vector. 202 */ put122(final int byteValue, final int shortValue1, final int shortValue2)203 final ByteVector put122(final int byteValue, final int shortValue1, final int shortValue2) { 204 int currentLength = length; 205 if (currentLength + 5 > data.length) { 206 enlarge(5); 207 } 208 byte[] currentData = data; 209 currentData[currentLength++] = (byte) byteValue; 210 currentData[currentLength++] = (byte) (shortValue1 >>> 8); 211 currentData[currentLength++] = (byte) shortValue1; 212 currentData[currentLength++] = (byte) (shortValue2 >>> 8); 213 currentData[currentLength++] = (byte) shortValue2; 214 length = currentLength; 215 return this; 216 } 217 218 /** 219 * Puts a long into this byte vector. The byte vector is automatically enlarged if necessary. 220 * 221 * @param longValue a long. 222 * @return this byte vector. 223 */ putLong(final long longValue)224 public ByteVector putLong(final long longValue) { 225 int currentLength = length; 226 if (currentLength + 8 > data.length) { 227 enlarge(8); 228 } 229 byte[] currentData = data; 230 int intValue = (int) (longValue >>> 32); 231 currentData[currentLength++] = (byte) (intValue >>> 24); 232 currentData[currentLength++] = (byte) (intValue >>> 16); 233 currentData[currentLength++] = (byte) (intValue >>> 8); 234 currentData[currentLength++] = (byte) intValue; 235 intValue = (int) longValue; 236 currentData[currentLength++] = (byte) (intValue >>> 24); 237 currentData[currentLength++] = (byte) (intValue >>> 16); 238 currentData[currentLength++] = (byte) (intValue >>> 8); 239 currentData[currentLength++] = (byte) intValue; 240 length = currentLength; 241 return this; 242 } 243 244 /** 245 * Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if 246 * necessary. 247 * 248 * @param stringValue a String whose UTF8 encoded length must be less than 65536. 249 * @return this byte vector. 250 */ 251 // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility). putUTF8(final String stringValue)252 public ByteVector putUTF8(final String stringValue) { 253 int charLength = stringValue.length(); 254 if (charLength > 65535) { 255 throw new IllegalArgumentException("UTF8 string too large"); 256 } 257 int currentLength = length; 258 if (currentLength + 2 + charLength > data.length) { 259 enlarge(2 + charLength); 260 } 261 byte[] currentData = data; 262 // Optimistic algorithm: instead of computing the byte length and then serializing the string 263 // (which requires two loops), we assume the byte length is equal to char length (which is the 264 // most frequent case), and we start serializing the string right away. During the 265 // serialization, if we find that this assumption is wrong, we continue with the general method. 266 currentData[currentLength++] = (byte) (charLength >>> 8); 267 currentData[currentLength++] = (byte) charLength; 268 for (int i = 0; i < charLength; ++i) { 269 char charValue = stringValue.charAt(i); 270 if (charValue >= '\u0001' && charValue <= '\u007F') { 271 currentData[currentLength++] = (byte) charValue; 272 } else { 273 length = currentLength; 274 return encodeUtf8(stringValue, i, 65535); 275 } 276 } 277 length = currentLength; 278 return this; 279 } 280 281 /** 282 * Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if 283 * necessary. The string length is encoded in two bytes before the encoded characters, if there is 284 * space for that (i.e. if this.length - offset - 2 >= 0). 285 * 286 * @param stringValue the String to encode. 287 * @param offset the index of the first character to encode. The previous characters are supposed 288 * to have already been encoded, using only one byte per character. 289 * @param maxByteLength the maximum byte length of the encoded string, including the already 290 * encoded characters. 291 * @return this byte vector. 292 */ encodeUtf8(final String stringValue, final int offset, final int maxByteLength)293 final ByteVector encodeUtf8(final String stringValue, final int offset, final int maxByteLength) { 294 int charLength = stringValue.length(); 295 int byteLength = offset; 296 for (int i = offset; i < charLength; ++i) { 297 char charValue = stringValue.charAt(i); 298 if (charValue >= 0x0001 && charValue <= 0x007F) { 299 byteLength++; 300 } else if (charValue <= 0x07FF) { 301 byteLength += 2; 302 } else { 303 byteLength += 3; 304 } 305 } 306 if (byteLength > maxByteLength) { 307 throw new IllegalArgumentException("UTF8 string too large"); 308 } 309 // Compute where 'byteLength' must be stored in 'data', and store it at this location. 310 int byteLengthOffset = length - offset - 2; 311 if (byteLengthOffset >= 0) { 312 data[byteLengthOffset] = (byte) (byteLength >>> 8); 313 data[byteLengthOffset + 1] = (byte) byteLength; 314 } 315 if (length + byteLength - offset > data.length) { 316 enlarge(byteLength - offset); 317 } 318 int currentLength = length; 319 for (int i = offset; i < charLength; ++i) { 320 char charValue = stringValue.charAt(i); 321 if (charValue >= 0x0001 && charValue <= 0x007F) { 322 data[currentLength++] = (byte) charValue; 323 } else if (charValue <= 0x07FF) { 324 data[currentLength++] = (byte) (0xC0 | charValue >> 6 & 0x1F); 325 data[currentLength++] = (byte) (0x80 | charValue & 0x3F); 326 } else { 327 data[currentLength++] = (byte) (0xE0 | charValue >> 12 & 0xF); 328 data[currentLength++] = (byte) (0x80 | charValue >> 6 & 0x3F); 329 data[currentLength++] = (byte) (0x80 | charValue & 0x3F); 330 } 331 } 332 length = currentLength; 333 return this; 334 } 335 336 /** 337 * Puts an array of bytes into this byte vector. The byte vector is automatically enlarged if 338 * necessary. 339 * 340 * @param byteArrayValue an array of bytes. May be {@literal null} to put {@code byteLength} null 341 * bytes into this byte vector. 342 * @param byteOffset index of the first byte of byteArrayValue that must be copied. 343 * @param byteLength number of bytes of byteArrayValue that must be copied. 344 * @return this byte vector. 345 */ putByteArray( final byte[] byteArrayValue, final int byteOffset, final int byteLength)346 public ByteVector putByteArray( 347 final byte[] byteArrayValue, final int byteOffset, final int byteLength) { 348 if (length + byteLength > data.length) { 349 enlarge(byteLength); 350 } 351 if (byteArrayValue != null) { 352 System.arraycopy(byteArrayValue, byteOffset, data, length, byteLength); 353 } 354 length += byteLength; 355 return this; 356 } 357 358 /** 359 * Enlarges this byte vector so that it can receive 'size' more bytes. 360 * 361 * @param size number of additional bytes that this byte vector should be able to receive. 362 */ enlarge(final int size)363 private void enlarge(final int size) { 364 if (length > data.length) { 365 throw new AssertionError("Internal error"); 366 } 367 int doubleCapacity = 2 * data.length; 368 int minimalCapacity = length + size; 369 byte[] newData = new byte[doubleCapacity > minimalCapacity ? doubleCapacity : minimalCapacity]; 370 System.arraycopy(data, 0, newData, 0, length); 371 data = newData; 372 } 373 } 374