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 &gt;= 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}