Mercurial > lasercutter
comparison 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 |
comparison
equal
deleted
inserted
replaced
9:35cf337adfcf | 10:ef7dbbd6452c |
---|---|
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; | |
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 { | |
79 enlarge(1); | |
80 } | |
81 data[length++] = (byte) b; | |
82 this.length = length; | |
83 return this; | |
84 } | |
85 | |
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 } | |
106 | |
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 } | |
126 | |
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 } | |
148 | |
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 } | |
170 | |
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 } | |
198 | |
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 } | |
281 | |
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 } | |
304 | |
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 } |