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