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