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