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