001// ASM: a very small and fast Java bytecode manipulation framework 002// Copyright (c) 2000-2011 INRIA, France Telecom 003// All rights reserved. 004// 005// Redistribution and use in source and binary forms, with or without 006// modification, are permitted provided that the following conditions 007// are met: 008// 1. Redistributions of source code must retain the above copyright 009// notice, this list of conditions and the following disclaimer. 010// 2. Redistributions in binary form must reproduce the above copyright 011// notice, this list of conditions and the following disclaimer in the 012// documentation and/or other materials provided with the distribution. 013// 3. Neither the name of the copyright holders nor the names of its 014// contributors may be used to endorse or promote products derived from 015// this software without specific prior written permission. 016// 017// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 018// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 019// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 020// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 021// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 022// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 023// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 024// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 025// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 026// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 027// THE POSSIBILITY OF SUCH DAMAGE. 028package org.springframework.asm; 029 030/** 031 * A dynamically extensible vector of bytes. This class is roughly equivalent to a DataOutputStream 032 * on top of a ByteArrayOutputStream, but is more efficient. 033 * 034 * @author Eric Bruneton 035 */ 036public class ByteVector { 037 038 /** The content of this vector. Only the first {@link #length} bytes contain real data. */ 039 byte[] data; 040 041 /** The actual number of bytes in this vector. */ 042 int length; 043 044 /** Constructs a new {@link ByteVector} with a default initial capacity. */ 045 public ByteVector() { 046 data = new byte[64]; 047 } 048 049 /** 050 * Constructs a new {@link ByteVector} with the given initial capacity. 051 * 052 * @param initialCapacity the initial capacity of the byte vector to be constructed. 053 */ 054 public ByteVector(final int initialCapacity) { 055 data = new byte[initialCapacity]; 056 } 057 058 /** 059 * Constructs a new {@link ByteVector} from the given initial data. 060 * 061 * @param data the initial data of the new byte vector. 062 */ 063 ByteVector(final byte[] data) { 064 this.data = data; 065 this.length = data.length; 066 } 067 068 /** 069 * Puts a byte into this byte vector. The byte vector is automatically enlarged if necessary. 070 * 071 * @param byteValue a byte. 072 * @return this byte vector. 073 */ 074 public ByteVector putByte(final int byteValue) { 075 int currentLength = length; 076 if (currentLength + 1 > data.length) { 077 enlarge(1); 078 } 079 data[currentLength++] = (byte) byteValue; 080 length = currentLength; 081 return this; 082 } 083 084 /** 085 * Puts two bytes into this byte vector. The byte vector is automatically enlarged if necessary. 086 * 087 * @param byteValue1 a byte. 088 * @param byteValue2 another byte. 089 * @return this byte vector. 090 */ 091 final ByteVector put11(final int byteValue1, final int byteValue2) { 092 int currentLength = length; 093 if (currentLength + 2 > data.length) { 094 enlarge(2); 095 } 096 byte[] currentData = data; 097 currentData[currentLength++] = (byte) byteValue1; 098 currentData[currentLength++] = (byte) byteValue2; 099 length = currentLength; 100 return this; 101 } 102 103 /** 104 * Puts a short into this byte vector. The byte vector is automatically enlarged if necessary. 105 * 106 * @param shortValue a short. 107 * @return this byte vector. 108 */ 109 public ByteVector putShort(final int shortValue) { 110 int currentLength = length; 111 if (currentLength + 2 > data.length) { 112 enlarge(2); 113 } 114 byte[] currentData = data; 115 currentData[currentLength++] = (byte) (shortValue >>> 8); 116 currentData[currentLength++] = (byte) shortValue; 117 length = currentLength; 118 return this; 119 } 120 121 /** 122 * Puts a byte and a short into this byte vector. The byte vector is automatically enlarged if 123 * necessary. 124 * 125 * @param byteValue a byte. 126 * @param shortValue a short. 127 * @return this byte vector. 128 */ 129 final ByteVector put12(final int byteValue, final int shortValue) { 130 int currentLength = length; 131 if (currentLength + 3 > data.length) { 132 enlarge(3); 133 } 134 byte[] currentData = data; 135 currentData[currentLength++] = (byte) byteValue; 136 currentData[currentLength++] = (byte) (shortValue >>> 8); 137 currentData[currentLength++] = (byte) shortValue; 138 length = currentLength; 139 return this; 140 } 141 142 /** 143 * Puts two bytes and a short into this byte vector. The byte vector is automatically enlarged if 144 * necessary. 145 * 146 * @param byteValue1 a byte. 147 * @param byteValue2 another byte. 148 * @param shortValue a short. 149 * @return this byte vector. 150 */ 151 final ByteVector put112(final int byteValue1, final int byteValue2, final int shortValue) { 152 int currentLength = length; 153 if (currentLength + 4 > data.length) { 154 enlarge(4); 155 } 156 byte[] currentData = data; 157 currentData[currentLength++] = (byte) byteValue1; 158 currentData[currentLength++] = (byte) byteValue2; 159 currentData[currentLength++] = (byte) (shortValue >>> 8); 160 currentData[currentLength++] = (byte) shortValue; 161 length = currentLength; 162 return this; 163 } 164 165 /** 166 * Puts an int into this byte vector. The byte vector is automatically enlarged if necessary. 167 * 168 * @param intValue an int. 169 * @return this byte vector. 170 */ 171 public ByteVector putInt(final int intValue) { 172 int currentLength = length; 173 if (currentLength + 4 > data.length) { 174 enlarge(4); 175 } 176 byte[] currentData = data; 177 currentData[currentLength++] = (byte) (intValue >>> 24); 178 currentData[currentLength++] = (byte) (intValue >>> 16); 179 currentData[currentLength++] = (byte) (intValue >>> 8); 180 currentData[currentLength++] = (byte) intValue; 181 length = currentLength; 182 return this; 183 } 184 185 /** 186 * Puts one byte and two shorts into this byte vector. The byte vector is automatically enlarged 187 * if necessary. 188 * 189 * @param byteValue a byte. 190 * @param shortValue1 a short. 191 * @param shortValue2 another short. 192 * @return this byte vector. 193 */ 194 final ByteVector put122(final int byteValue, final int shortValue1, final int shortValue2) { 195 int currentLength = length; 196 if (currentLength + 5 > data.length) { 197 enlarge(5); 198 } 199 byte[] currentData = data; 200 currentData[currentLength++] = (byte) byteValue; 201 currentData[currentLength++] = (byte) (shortValue1 >>> 8); 202 currentData[currentLength++] = (byte) shortValue1; 203 currentData[currentLength++] = (byte) (shortValue2 >>> 8); 204 currentData[currentLength++] = (byte) shortValue2; 205 length = currentLength; 206 return this; 207 } 208 209 /** 210 * Puts a long into this byte vector. The byte vector is automatically enlarged if necessary. 211 * 212 * @param longValue a long. 213 * @return this byte vector. 214 */ 215 public ByteVector putLong(final long longValue) { 216 int currentLength = length; 217 if (currentLength + 8 > data.length) { 218 enlarge(8); 219 } 220 byte[] currentData = data; 221 int intValue = (int) (longValue >>> 32); 222 currentData[currentLength++] = (byte) (intValue >>> 24); 223 currentData[currentLength++] = (byte) (intValue >>> 16); 224 currentData[currentLength++] = (byte) (intValue >>> 8); 225 currentData[currentLength++] = (byte) intValue; 226 intValue = (int) longValue; 227 currentData[currentLength++] = (byte) (intValue >>> 24); 228 currentData[currentLength++] = (byte) (intValue >>> 16); 229 currentData[currentLength++] = (byte) (intValue >>> 8); 230 currentData[currentLength++] = (byte) intValue; 231 length = currentLength; 232 return this; 233 } 234 235 /** 236 * Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if 237 * necessary. 238 * 239 * @param stringValue a String whose UTF8 encoded length must be less than 65536. 240 * @return this byte vector. 241 */ 242 // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility). 243 public ByteVector putUTF8(final String stringValue) { 244 int charLength = stringValue.length(); 245 if (charLength > 65535) { 246 throw new IllegalArgumentException("UTF8 string too large"); 247 } 248 int currentLength = length; 249 if (currentLength + 2 + charLength > data.length) { 250 enlarge(2 + charLength); 251 } 252 byte[] currentData = data; 253 // Optimistic algorithm: instead of computing the byte length and then serializing the string 254 // (which requires two loops), we assume the byte length is equal to char length (which is the 255 // most frequent case), and we start serializing the string right away. During the 256 // serialization, if we find that this assumption is wrong, we continue with the general method. 257 currentData[currentLength++] = (byte) (charLength >>> 8); 258 currentData[currentLength++] = (byte) charLength; 259 for (int i = 0; i < charLength; ++i) { 260 char charValue = stringValue.charAt(i); 261 if (charValue >= '\u0001' && charValue <= '\u007F') { 262 currentData[currentLength++] = (byte) charValue; 263 } else { 264 length = currentLength; 265 return encodeUtf8(stringValue, i, 65535); 266 } 267 } 268 length = currentLength; 269 return this; 270 } 271 272 /** 273 * Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if 274 * necessary. The string length is encoded in two bytes before the encoded characters, if there is 275 * space for that (i.e. if this.length - offset - 2 >= 0). 276 * 277 * @param stringValue the String to encode. 278 * @param offset the index of the first character to encode. The previous characters are supposed 279 * to have already been encoded, using only one byte per character. 280 * @param maxByteLength the maximum byte length of the encoded string, including the already 281 * encoded characters. 282 * @return this byte vector. 283 */ 284 final ByteVector encodeUtf8(final String stringValue, final int offset, final int maxByteLength) { 285 int charLength = stringValue.length(); 286 int byteLength = offset; 287 for (int i = offset; i < charLength; ++i) { 288 char charValue = stringValue.charAt(i); 289 if (charValue >= 0x0001 && charValue <= 0x007F) { 290 byteLength++; 291 } else if (charValue <= 0x07FF) { 292 byteLength += 2; 293 } else { 294 byteLength += 3; 295 } 296 } 297 if (byteLength > maxByteLength) { 298 throw new IllegalArgumentException("UTF8 string too large"); 299 } 300 // Compute where 'byteLength' must be stored in 'data', and store it at this location. 301 int byteLengthOffset = length - offset - 2; 302 if (byteLengthOffset >= 0) { 303 data[byteLengthOffset] = (byte) (byteLength >>> 8); 304 data[byteLengthOffset + 1] = (byte) byteLength; 305 } 306 if (length + byteLength - offset > data.length) { 307 enlarge(byteLength - offset); 308 } 309 int currentLength = length; 310 for (int i = offset; i < charLength; ++i) { 311 char charValue = stringValue.charAt(i); 312 if (charValue >= 0x0001 && charValue <= 0x007F) { 313 data[currentLength++] = (byte) charValue; 314 } else if (charValue <= 0x07FF) { 315 data[currentLength++] = (byte) (0xC0 | charValue >> 6 & 0x1F); 316 data[currentLength++] = (byte) (0x80 | charValue & 0x3F); 317 } else { 318 data[currentLength++] = (byte) (0xE0 | charValue >> 12 & 0xF); 319 data[currentLength++] = (byte) (0x80 | charValue >> 6 & 0x3F); 320 data[currentLength++] = (byte) (0x80 | charValue & 0x3F); 321 } 322 } 323 length = currentLength; 324 return this; 325 } 326 327 /** 328 * Puts an array of bytes into this byte vector. The byte vector is automatically enlarged if 329 * necessary. 330 * 331 * @param byteArrayValue an array of bytes. May be {@literal null} to put {@code byteLength} null 332 * bytes into this byte vector. 333 * @param byteOffset index of the first byte of byteArrayValue that must be copied. 334 * @param byteLength number of bytes of byteArrayValue that must be copied. 335 * @return this byte vector. 336 */ 337 public ByteVector putByteArray( 338 final byte[] byteArrayValue, final int byteOffset, final int byteLength) { 339 if (length + byteLength > data.length) { 340 enlarge(byteLength); 341 } 342 if (byteArrayValue != null) { 343 System.arraycopy(byteArrayValue, byteOffset, data, length, byteLength); 344 } 345 length += byteLength; 346 return this; 347 } 348 349 /** 350 * Enlarges this byte vector so that it can receive 'size' more bytes. 351 * 352 * @param size number of additional bytes that this byte vector should be able to receive. 353 */ 354 private void enlarge(final int size) { 355 int doubleCapacity = 2 * data.length; 356 int minimalCapacity = length + size; 357 byte[] newData = new byte[doubleCapacity > minimalCapacity ? doubleCapacity : minimalCapacity]; 358 System.arraycopy(data, 0, newData, 0, length); 359 data = newData; 360 } 361}