001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2005 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: */package org.ejb3unit.asm;
030:
031: /**
032: * A dynamically extensible vector of bytes. This class is roughly equivalent to
033: * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
034: *
035: * @author Eric Bruneton
036: */
037: public class ByteVector {
038:
039: /**
040: * The content of this vector.
041: */
042: byte[] data;
043:
044: /**
045: * Actual number of bytes in this vector.
046: */
047: int length;
048:
049: /**
050: * Constructs a new {@link ByteVector ByteVector} with a default initial
051: * size.
052: */
053: public ByteVector() {
054: data = new byte[64];
055: }
056:
057: /**
058: * Constructs a new {@link ByteVector ByteVector} with the given initial
059: * size.
060: *
061: * @param initialSize
062: * the initial size of the byte vector to be constructed.
063: */
064: public ByteVector(final int initialSize) {
065: data = new byte[initialSize];
066: }
067:
068: /**
069: * Puts a byte into this byte vector. The byte vector is automatically
070: * enlarged if necessary.
071: *
072: * @param b
073: * a byte.
074: * @return this byte vector.
075: */
076: public ByteVector putByte(final int b) {
077: int length = this .length;
078: if (length + 1 > data.length) {
079: enlarge(1);
080: }
081: data[length++] = (byte) b;
082: this .length = length;
083: return this ;
084: }
085:
086: /**
087: * Puts two bytes into this byte vector. The byte vector is automatically
088: * enlarged if necessary.
089: *
090: * @param b1
091: * a byte.
092: * @param b2
093: * another byte.
094: * @return this byte vector.
095: */
096: ByteVector put11(final int b1, final int b2) {
097: int length = this .length;
098: if (length + 2 > data.length) {
099: enlarge(2);
100: }
101: byte[] data = this .data;
102: data[length++] = (byte) b1;
103: data[length++] = (byte) b2;
104: this .length = length;
105: return this ;
106: }
107:
108: /**
109: * Puts a short into this byte vector. The byte vector is automatically
110: * enlarged if necessary.
111: *
112: * @param s
113: * a short.
114: * @return this byte vector.
115: */
116: public ByteVector putShort(final int s) {
117: int length = this .length;
118: if (length + 2 > data.length) {
119: enlarge(2);
120: }
121: byte[] data = this .data;
122: data[length++] = (byte) (s >>> 8);
123: data[length++] = (byte) s;
124: this .length = length;
125: return this ;
126: }
127:
128: /**
129: * Puts a byte and a short into this byte vector. The byte vector is
130: * automatically enlarged if necessary.
131: *
132: * @param b
133: * a byte.
134: * @param s
135: * a short.
136: * @return this byte vector.
137: */
138: ByteVector put12(final int b, final int s) {
139: int length = this .length;
140: if (length + 3 > data.length) {
141: enlarge(3);
142: }
143: byte[] data = this .data;
144: data[length++] = (byte) b;
145: data[length++] = (byte) (s >>> 8);
146: data[length++] = (byte) s;
147: this .length = length;
148: return this ;
149: }
150:
151: /**
152: * Puts an int into this byte vector. The byte vector is automatically
153: * enlarged if necessary.
154: *
155: * @param i
156: * an int.
157: * @return this byte vector.
158: */
159: public ByteVector putInt(final int i) {
160: int length = this .length;
161: if (length + 4 > data.length) {
162: enlarge(4);
163: }
164: byte[] data = this .data;
165: data[length++] = (byte) (i >>> 24);
166: data[length++] = (byte) (i >>> 16);
167: data[length++] = (byte) (i >>> 8);
168: data[length++] = (byte) i;
169: this .length = length;
170: return this ;
171: }
172:
173: /**
174: * Puts a long into this byte vector. The byte vector is automatically
175: * enlarged if necessary.
176: *
177: * @param l
178: * a long.
179: * @return this byte vector.
180: */
181: public ByteVector putLong(final long l) {
182: int length = this .length;
183: if (length + 8 > data.length) {
184: enlarge(8);
185: }
186: byte[] data = this .data;
187: int i = (int) (l >>> 32);
188: data[length++] = (byte) (i >>> 24);
189: data[length++] = (byte) (i >>> 16);
190: data[length++] = (byte) (i >>> 8);
191: data[length++] = (byte) i;
192: i = (int) l;
193: data[length++] = (byte) (i >>> 24);
194: data[length++] = (byte) (i >>> 16);
195: data[length++] = (byte) (i >>> 8);
196: data[length++] = (byte) i;
197: this .length = length;
198: return this ;
199: }
200:
201: /**
202: * Puts an UTF8 string into this byte vector. The byte vector is
203: * automatically enlarged if necessary.
204: *
205: * @param s
206: * a String.
207: * @return this byte vector.
208: */
209: public ByteVector putUTF8(final String s) {
210: int charLength = s.length();
211: if (length + 2 + charLength > data.length) {
212: enlarge(2 + charLength);
213: }
214: int len = length;
215: byte[] data = this .data;
216: // optimistic algorithm: instead of computing the byte length and then
217: // serializing the string (which requires two loops), we assume the byte
218: // length is equal to char length (which is the most frequent case), and
219: // we start serializing the string right away. During the serialization,
220: // if we find that this assumption is wrong, we continue with the
221: // general method.
222: data[len++] = (byte) (charLength >>> 8);
223: data[len++] = (byte) charLength;
224: for (int i = 0; i < charLength; ++i) {
225: char c = s.charAt(i);
226: if (c >= '\001' && c <= '\177') {
227: data[len++] = (byte) c;
228: } else {
229: int byteLength = i;
230: for (int j = i; j < charLength; ++j) {
231: c = s.charAt(j);
232: if (c >= '\001' && c <= '\177') {
233: byteLength++;
234: } else if (c > '\u07FF') {
235: byteLength += 3;
236: } else {
237: byteLength += 2;
238: }
239: }
240: data[length] = (byte) (byteLength >>> 8);
241: data[length + 1] = (byte) byteLength;
242: if (length + 2 + byteLength > data.length) {
243: length = len;
244: enlarge(2 + byteLength);
245: data = this .data;
246: }
247: for (int j = i; j < charLength; ++j) {
248: c = s.charAt(j);
249: if (c >= '\001' && c <= '\177') {
250: data[len++] = (byte) c;
251: } else if (c > '\u07FF') {
252: data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
253: data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
254: data[len++] = (byte) (0x80 | c & 0x3F);
255: } else {
256: data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
257: data[len++] = (byte) (0x80 | c & 0x3F);
258: }
259: }
260: break;
261: }
262: }
263: length = len;
264: return this ;
265: }
266:
267: /**
268: * Puts an array of bytes into this byte vector. The byte vector is
269: * automatically enlarged if necessary.
270: *
271: * @param b
272: * an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
273: * null bytes into this byte vector.
274: * @param off
275: * index of the fist byte of b that must be copied.
276: * @param len
277: * number of bytes of b that must be copied.
278: * @return this byte vector.
279: */
280: public ByteVector putByteArray(final byte[] b, final int off,
281: final int len) {
282: if (length + len > data.length) {
283: enlarge(len);
284: }
285: if (b != null) {
286: System.arraycopy(b, off, data, length, len);
287: }
288: length += len;
289: return this ;
290: }
291:
292: /**
293: * Enlarge this byte vector so that it can receive n more bytes.
294: *
295: * @param size
296: * number of additional bytes that this byte vector should be
297: * able to receive.
298: */
299: private void enlarge(final int size) {
300: int length1 = 2 * data.length;
301: int length2 = length + size;
302: byte[] newData = new byte[length1 > length2 ? length1 : length2];
303: System.arraycopy(data, 0, newData, 0, length);
304: data = newData;
305: }
306: }
|