view src/clojure/asm/ByteVector.java @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
line wrap: on
line source
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 clojure.asm;
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{
40 /**
41 * The content of this vector.
42 */
43 byte[] data;
45 /**
46 * Actual number of bytes in this vector.
47 */
48 int length;
50 /**
51 * Constructs a new {@link ByteVector ByteVector} with a default initial
52 * size.
53 */
54 public ByteVector(){
55 data = new byte[64];
56 }
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 }
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 {
79 enlarge(1);
80 }
81 data[length++] = (byte) b;
82 this.length = length;
83 return this;
84 }
86 /**
87 * Puts two bytes into this byte vector. The byte vector is automatically
88 * enlarged if necessary.
89 *
90 * @param b1 a byte.
91 * @param b2 another byte.
92 * @return this byte vector.
93 */
94 ByteVector put11(final int b1, final int b2){
95 int length = this.length;
96 if(length + 2 > data.length)
97 {
98 enlarge(2);
99 }
100 byte[] data = this.data;
101 data[length++] = (byte) b1;
102 data[length++] = (byte) b2;
103 this.length = length;
104 return this;
105 }
107 /**
108 * Puts a short into this byte vector. The byte vector is automatically
109 * enlarged if necessary.
110 *
111 * @param s a short.
112 * @return this byte vector.
113 */
114 public ByteVector putShort(final int s){
115 int length = this.length;
116 if(length + 2 > data.length)
117 {
118 enlarge(2);
119 }
120 byte[] data = this.data;
121 data[length++] = (byte) (s >>> 8);
122 data[length++] = (byte) s;
123 this.length = length;
124 return this;
125 }
127 /**
128 * Puts a byte and a short into this byte vector. The byte vector is
129 * automatically enlarged if necessary.
130 *
131 * @param b a byte.
132 * @param s a short.
133 * @return this byte vector.
134 */
135 ByteVector put12(final int b, final int s){
136 int length = this.length;
137 if(length + 3 > data.length)
138 {
139 enlarge(3);
140 }
141 byte[] data = this.data;
142 data[length++] = (byte) b;
143 data[length++] = (byte) (s >>> 8);
144 data[length++] = (byte) s;
145 this.length = length;
146 return this;
147 }
149 /**
150 * Puts an int into this byte vector. The byte vector is automatically
151 * enlarged if necessary.
152 *
153 * @param i an int.
154 * @return this byte vector.
155 */
156 public ByteVector putInt(final int i){
157 int length = this.length;
158 if(length + 4 > data.length)
159 {
160 enlarge(4);
161 }
162 byte[] data = this.data;
163 data[length++] = (byte) (i >>> 24);
164 data[length++] = (byte) (i >>> 16);
165 data[length++] = (byte) (i >>> 8);
166 data[length++] = (byte) i;
167 this.length = length;
168 return this;
169 }
171 /**
172 * Puts a long into this byte vector. The byte vector is automatically
173 * enlarged if necessary.
174 *
175 * @param l a long.
176 * @return this byte vector.
177 */
178 public ByteVector putLong(final long l){
179 int length = this.length;
180 if(length + 8 > data.length)
181 {
182 enlarge(8);
183 }
184 byte[] data = this.data;
185 int i = (int) (l >>> 32);
186 data[length++] = (byte) (i >>> 24);
187 data[length++] = (byte) (i >>> 16);
188 data[length++] = (byte) (i >>> 8);
189 data[length++] = (byte) i;
190 i = (int) l;
191 data[length++] = (byte) (i >>> 24);
192 data[length++] = (byte) (i >>> 16);
193 data[length++] = (byte) (i >>> 8);
194 data[length++] = (byte) i;
195 this.length = length;
196 return this;
197 }
199 /**
200 * Puts an UTF8 string into this byte vector. The byte vector is
201 * automatically enlarged if necessary.
202 *
203 * @param s a String.
204 * @return this byte vector.
205 */
206 public ByteVector putUTF8(final String s){
207 int charLength = s.length();
208 if(length + 2 + charLength > data.length)
209 {
210 enlarge(2 + charLength);
211 }
212 int len = length;
213 byte[] data = this.data;
214 // optimistic algorithm: instead of computing the byte length and then
215 // serializing the string (which requires two loops), we assume the byte
216 // length is equal to char length (which is the most frequent case), and
217 // we start serializing the string right away. During the serialization,
218 // if we find that this assumption is wrong, we continue with the
219 // general method.
220 data[len++] = (byte) (charLength >>> 8);
221 data[len++] = (byte) charLength;
222 for(int i = 0; i < charLength; ++i)
223 {
224 char c = s.charAt(i);
225 if(c >= '\001' && c <= '\177')
226 {
227 data[len++] = (byte) c;
228 }
229 else
230 {
231 int byteLength = i;
232 for(int j = i; j < charLength; ++j)
233 {
234 c = s.charAt(j);
235 if(c >= '\001' && c <= '\177')
236 {
237 byteLength++;
238 }
239 else if(c > '\u07FF')
240 {
241 byteLength += 3;
242 }
243 else
244 {
245 byteLength += 2;
246 }
247 }
248 data[length] = (byte) (byteLength >>> 8);
249 data[length + 1] = (byte) byteLength;
250 if(length + 2 + byteLength > data.length)
251 {
252 length = len;
253 enlarge(2 + byteLength);
254 data = this.data;
255 }
256 for(int j = i; j < charLength; ++j)
257 {
258 c = s.charAt(j);
259 if(c >= '\001' && c <= '\177')
260 {
261 data[len++] = (byte) c;
262 }
263 else if(c > '\u07FF')
264 {
265 data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
266 data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
267 data[len++] = (byte) (0x80 | c & 0x3F);
268 }
269 else
270 {
271 data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
272 data[len++] = (byte) (0x80 | c & 0x3F);
273 }
274 }
275 break;
276 }
277 }
278 length = len;
279 return this;
280 }
282 /**
283 * Puts an array of bytes into this byte vector. The byte vector is
284 * automatically enlarged if necessary.
285 *
286 * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
287 * null bytes into this byte vector.
288 * @param off index of the fist byte of b that must be copied.
289 * @param len number of bytes of b that must be copied.
290 * @return this byte vector.
291 */
292 public ByteVector putByteArray(final byte[] b, final int off, final int len){
293 if(length + len > data.length)
294 {
295 enlarge(len);
296 }
297 if(b != null)
298 {
299 System.arraycopy(b, off, data, length, len);
300 }
301 length += len;
302 return this;
303 }
305 /**
306 * Enlarge this byte vector so that it can receive n more bytes.
307 *
308 * @param size number of additional bytes that this byte vector should be
309 * able to receive.
310 */
311 private void enlarge(final int size){
312 int length1 = 2 * data.length;
313 int length2 = length + size;
314 byte[] newData = new byte[length1 > length2 ? length1 : length2];
315 System.arraycopy(data, 0, newData, 0, length);
316 data = newData;
317 }
318 }