KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > retrotranslator > runtime > asm > ByteVector


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 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 package net.sf.retrotranslator.runtime.asm;
31
32 /**
33  * A dynamically extensible vector of bytes. This class is roughly equivalent to
34  * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
35  *
36  * @author Eric Bruneton
37  */

38 public class ByteVector {
39
40     /**
41      * The content of this vector.
42      */

43     byte[] data;
44
45     /**
46      * Actual number of bytes in this vector.
47      */

48     int length;
49
50     /**
51      * Constructs a new {@link ByteVector ByteVector} with a default initial
52      * size.
53      */

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

64     public ByteVector(final int initialSize) {
65         data = new byte[initialSize];
66     }
67
68     /**
69      * Puts a byte into this byte vector. The byte vector is automatically
70      * enlarged if necessary.
71      *
72      * @param b a byte.
73      * @return this byte vector.
74      */

75     public ByteVector putByte(final int b) {
76         int length = this.length;
77         if (length + 1 > data.length) {
78             enlarge(1);
79         }
80         data[length++] = (byte) b;
81         this.length = length;
82         return this;
83     }
84
85     /**
86      * Puts two bytes into this byte vector. The byte vector is automatically
87      * enlarged if necessary.
88      *
89      * @param b1 a byte.
90      * @param b2 another byte.
91      * @return this byte vector.
92      */

93     ByteVector put11(final int b1, final int b2) {
94         int length = this.length;
95         if (length + 2 > data.length) {
96             enlarge(2);
97         }
98         byte[] data = this.data;
99         data[length++] = (byte) b1;
100         data[length++] = (byte) b2;
101         this.length = length;
102         return this;
103     }
104
105     /**
106      * Puts a short into this byte vector. The byte vector is automatically
107      * enlarged if necessary.
108      *
109      * @param s a short.
110      * @return this byte vector.
111      */

112     public ByteVector putShort(final int s) {
113         int length = this.length;
114         if (length + 2 > data.length) {
115             enlarge(2);
116         }
117         byte[] data = this.data;
118         data[length++] = (byte) (s >>> 8);
119         data[length++] = (byte) s;
120         this.length = length;
121         return this;
122     }
123
124     /**
125      * Puts a byte and a short into this byte vector. The byte vector is
126      * automatically enlarged if necessary.
127      *
128      * @param b a byte.
129      * @param s a short.
130      * @return this byte vector.
131      */

132     ByteVector put12(final int b, final int s) {
133         int length = this.length;
134         if (length + 3 > data.length) {
135             enlarge(3);
136         }
137         byte[] data = this.data;
138         data[length++] = (byte) b;
139         data[length++] = (byte) (s >>> 8);
140         data[length++] = (byte) s;
141         this.length = length;
142         return this;
143     }
144
145     /**
146      * Puts an int into this byte vector. The byte vector is automatically
147      * enlarged if necessary.
148      *
149      * @param i an int.
150      * @return this byte vector.
151      */

152     public ByteVector putInt(final int i) {
153         int length = this.length;
154         if (length + 4 > data.length) {
155             enlarge(4);
156         }
157         byte[] data = this.data;
158         data[length++] = (byte) (i >>> 24);
159         data[length++] = (byte) (i >>> 16);
160         data[length++] = (byte) (i >>> 8);
161         data[length++] = (byte) i;
162         this.length = length;
163         return this;
164     }
165
166     /**
167      * Puts a long into this byte vector. The byte vector is automatically
168      * enlarged if necessary.
169      *
170      * @param l a long.
171      * @return this byte vector.
172      */

173     public ByteVector putLong(final long l) {
174         int length = this.length;
175         if (length + 8 > data.length) {
176             enlarge(8);
177         }
178         byte[] data = this.data;
179         int i = (int) (l >>> 32);
180         data[length++] = (byte) (i >>> 24);
181         data[length++] = (byte) (i >>> 16);
182         data[length++] = (byte) (i >>> 8);
183         data[length++] = (byte) i;
184         i = (int) l;
185         data[length++] = (byte) (i >>> 24);
186         data[length++] = (byte) (i >>> 16);
187         data[length++] = (byte) (i >>> 8);
188         data[length++] = (byte) i;
189         this.length = length;
190         return this;
191     }
192
193     /**
194      * Puts an UTF8 string into this byte vector. The byte vector is
195      * automatically enlarged if necessary.
196      *
197      * @param s a String.
198      * @return this byte vector.
199      */

200     public ByteVector putUTF8(final String JavaDoc s) {
201         int charLength = s.length();
202         if (length + 2 + charLength > data.length) {
203             enlarge(2 + charLength);
204         }
205         int len = length;
206         byte[] data = this.data;
207         // optimistic algorithm: instead of computing the byte length and then
208
// serializing the string (which requires two loops), we assume the byte
209
// length is equal to char length (which is the most frequent case), and
210
// we start serializing the string right away. During the serialization,
211
// if we find that this assumption is wrong, we continue with the
212
// general method.
213
data[len++] = (byte) (charLength >>> 8);
214         data[len++] = (byte) (charLength);
215         for (int i = 0; i < charLength; ++i) {
216             char c = s.charAt(i);
217             if (c >= '\001' && c <= '\177') {
218                 data[len++] = (byte) c;
219             } else {
220                 int byteLength = i;
221                 for (int j = i; j < charLength; ++j) {
222                     c = s.charAt(j);
223                     if (c >= '\001' && c <= '\177') {
224                         byteLength++;
225                     } else if (c > '\u07FF') {
226                         byteLength += 3;
227                     } else {
228                         byteLength += 2;
229                     }
230                 }
231                 data[length] = (byte) (byteLength >>> 8);
232                 data[length + 1] = (byte) (byteLength);
233                 if (length + 2 + byteLength > data.length) {
234                     length = len;
235                     enlarge(2 + byteLength);
236                     data = this.data;
237                 }
238                 for (int j = i; j < charLength; ++j) {
239                     c = s.charAt(j);
240                     if (c >= '\001' && c <= '\177') {
241                         data[len++] = (byte) c;
242                     } else if (c > '\u07FF') {
243                         data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
244                         data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
245                         data[len++] = (byte) (0x80 | c & 0x3F);
246                     } else {
247                         data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
248                         data[len++] = (byte) (0x80 | c & 0x3F);
249                     }
250                 }
251                 break;
252             }
253         }
254         length = len;
255         return this;
256     }
257
258     /**
259      * Puts an array of bytes into this byte vector. The byte vector is
260      * automatically enlarged if necessary.
261      *
262      * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
263      * null bytes into this byte vector.
264      * @param off index of the fist byte of b that must be copied.
265      * @param len number of bytes of b that must be copied.
266      * @return this byte vector.
267      */

268     public ByteVector putByteArray(final byte[] b, final int off, final int len)
269     {
270         if (length + len > data.length) {
271             enlarge(len);
272         }
273         if (b != null) {
274             System.arraycopy(b, off, data, length, len);
275         }
276         length += len;
277         return this;
278     }
279
280     /**
281      * Enlarge this byte vector so that it can receive n more bytes.
282      *
283      * @param size number of additional bytes that this byte vector should be
284      * able to receive.
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