KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > asm > ByteVector


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000,2002,2003 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * Contact: Eric.Bruneton@rd.francetelecom.com
31  *
32  * Author: Eric Bruneton
33  */

34
35 package org.logicalcobwebs.asm;
36
37 /**
38  * A dynamically extensible vector of bytes. This class is roughly equivalent to
39  * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
40  */

41
42 final class ByteVector {
43
44   /**
45    * The content of this vector.
46    */

47
48   byte[] data;
49
50   /**
51    * Actual number of bytes in this vector.
52    */

53
54   int length;
55
56   /**
57    * Constructs a new {@link ByteVector ByteVector} with a default initial size.
58    */

59
60   public ByteVector () {
61     data = new byte[64];
62   }
63
64   /**
65    * Constructs a new {@link ByteVector ByteVector} with the given initial size.
66    *
67    * @param initialSize the initial size of the byte vector to be constructed.
68    */

69
70   public ByteVector (final int initialSize) {
71     data = new byte[initialSize];
72   }
73
74   /**
75    * Puts a byte into this byte vector. The byte vector is automatically
76    * enlarged if necessary.
77    *
78    * @param b a byte.
79    * @return this byte vector.
80    */

81
82   public ByteVector put1 (final int b) {
83     int length = this.length;
84     if (length + 1 > data.length) {
85       enlarge(1);
86     }
87     data[length++] = (byte)b;
88     this.length = length;
89     return this;
90   }
91
92   /**
93    * Puts two bytes into this byte vector. The byte vector is automatically
94    * enlarged if necessary.
95    *
96    * @param b1 a byte.
97    * @param b2 another byte.
98    * @return this byte vector.
99    */

100
101   public ByteVector put11 (final int b1, final int b2) {
102     int length = this.length;
103     if (length + 2 > data.length) {
104       enlarge(2);
105     }
106     byte[] data = this.data;
107     data[length++] = (byte)b1;
108     data[length++] = (byte)b2;
109     this.length = length;
110     return this;
111   }
112
113   /**
114    * Puts a short into this byte vector. The byte vector is automatically
115    * enlarged if necessary.
116    *
117    * @param s a short.
118    * @return this byte vector.
119    */

120
121   public ByteVector put2 (final int s) {
122     int length = this.length;
123     if (length + 2 > data.length) {
124       enlarge(2);
125     }
126     byte[] data = this.data;
127     data[length++] = (byte)(s >>> 8);
128     data[length++] = (byte)s;
129     this.length = length;
130     return this;
131   }
132
133   /**
134    * Puts a byte and a short into this byte vector. The byte vector is
135    * automatically enlarged if necessary.
136    *
137    * @param b a byte.
138    * @param s a short.
139    * @return this byte vector.
140    */

141
142   public ByteVector put12 (final int b, final int s) {
143     int length = this.length;
144     if (length + 3 > data.length) {
145       enlarge(3);
146     }
147     byte[] data = this.data;
148     data[length++] = (byte)b;
149     data[length++] = (byte)(s >>> 8);
150     data[length++] = (byte)s;
151     this.length = length;
152     return this;
153   }
154
155   /**
156    * Puts an int into this byte vector. The byte vector is automatically
157    * enlarged if necessary.
158    *
159    * @param i an int.
160    * @return this byte vector.
161    */

162
163   public ByteVector put4 (final int i) {
164     int length = this.length;
165     if (length + 4 > data.length) {
166       enlarge(4);
167     }
168     byte[] data = this.data;
169     data[length++] = (byte)(i >>> 24);
170     data[length++] = (byte)(i >>> 16);
171     data[length++] = (byte)(i >>> 8);
172     data[length++] = (byte)i;
173     this.length = length;
174     return this;
175   }
176
177   /**
178    * Puts a long into this byte vector. The byte vector is automatically
179    * enlarged if necessary.
180    *
181    * @param l a long.
182    * @return this byte vector.
183    */

184
185   public ByteVector put8 (final long l) {
186     int length = this.length;
187     if (length + 8 > data.length) {
188       enlarge(8);
189     }
190     byte[] data = this.data;
191     int i = (int)(l >>> 32);
192     data[length++] = (byte)(i >>> 24);
193     data[length++] = (byte)(i >>> 16);
194     data[length++] = (byte)(i >>> 8);
195     data[length++] = (byte)i;
196     i = (int)l;
197     data[length++] = (byte)(i >>> 24);
198     data[length++] = (byte)(i >>> 16);
199     data[length++] = (byte)(i >>> 8);
200     data[length++] = (byte)i;
201     this.length = length;
202     return this;
203   }
204
205   /**
206    * Puts a String in UTF format into this byte vector. The byte vector is
207    * automatically enlarged if necessary.
208    *
209    * @param s a String.
210    * @return this byte vector.
211    */

212
213   public ByteVector putUTF (final String JavaDoc s) {
214     int charLength = s.length();
215     int byteLength = 0;
216     for (int i = 0; i < charLength; ++i) {
217       char c = s.charAt(i);
218       if (c >= '\001' && c <= '\177') {
219         byteLength++;
220       } else if (c > '\u07FF') {
221         byteLength += 3;
222       } else {
223         byteLength += 2;
224       }
225     }
226     if (byteLength > 65535) {
227       throw new IllegalArgumentException JavaDoc();
228     }
229     int length = this.length;
230     if (length + 2 + byteLength > data.length) {
231       enlarge(2 + byteLength);
232     }
233     byte[] data = this.data;
234     data[length++] = (byte)(byteLength >>> 8);
235     data[length++] = (byte)(byteLength);
236     for (int i = 0; i < charLength; ++i) {
237       char c = s.charAt(i);
238       if (c >= '\001' && c <= '\177') {
239         data[length++] = (byte)c;
240       } else if (c > '\u07FF') {
241         data[length++] = (byte)(0xE0 | c >> 12 & 0xF);
242         data[length++] = (byte)(0x80 | c >> 6 & 0x3F);
243         data[length++] = (byte)(0x80 | c & 0x3F);
244       } else {
245         data[length++] = (byte)(0xC0 | c >> 6 & 0x1F);
246         data[length++] = (byte)(0x80 | c & 0x3F);
247       }
248     }
249     this.length = length;
250     return this;
251   }
252
253   /**
254    * Puts an array of bytes into this byte vector. The byte vector is
255    * automatically enlarged if necessary.
256    *
257    * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt> null
258    * bytes into this byte vector.
259    * @param off index of the fist byte of b that must be copied.
260    * @param len number of bytes of b that must be copied.
261    * @return this byte vector.
262    */

263
264   public ByteVector putByteArray (
265     final byte[] b,
266     final int off,
267     final int len)
268   {
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
286   private void enlarge (final int size) {
287     int length1 = 2 * data.length;
288     int length2 = length + size;
289     byte[] newData = new byte[length1 > length2 ? length1 : length2];
290     System.arraycopy(data, 0, newData, 0, length);
291     data = newData;
292   }
293 }
294
Popular Tags