annotate 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
rev   line source
rlm@10 1 /***
rlm@10 2 * ASM: a very small and fast Java bytecode manipulation framework
rlm@10 3 * Copyright (c) 2000-2005 INRIA, France Telecom
rlm@10 4 * All rights reserved.
rlm@10 5 *
rlm@10 6 * Redistribution and use in source and binary forms, with or without
rlm@10 7 * modification, are permitted provided that the following conditions
rlm@10 8 * are met:
rlm@10 9 * 1. Redistributions of source code must retain the above copyright
rlm@10 10 * notice, this list of conditions and the following disclaimer.
rlm@10 11 * 2. Redistributions in binary form must reproduce the above copyright
rlm@10 12 * notice, this list of conditions and the following disclaimer in the
rlm@10 13 * documentation and/or other materials provided with the distribution.
rlm@10 14 * 3. Neither the name of the copyright holders nor the names of its
rlm@10 15 * contributors may be used to endorse or promote products derived from
rlm@10 16 * this software without specific prior written permission.
rlm@10 17 *
rlm@10 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
rlm@10 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
rlm@10 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
rlm@10 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
rlm@10 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
rlm@10 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
rlm@10 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
rlm@10 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
rlm@10 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
rlm@10 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
rlm@10 28 * THE POSSIBILITY OF SUCH DAMAGE.
rlm@10 29 */
rlm@10 30 package clojure.asm;
rlm@10 31
rlm@10 32 /**
rlm@10 33 * A dynamically extensible vector of bytes. This class is roughly equivalent to
rlm@10 34 * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
rlm@10 35 *
rlm@10 36 * @author Eric Bruneton
rlm@10 37 */
rlm@10 38 public class ByteVector{
rlm@10 39
rlm@10 40 /**
rlm@10 41 * The content of this vector.
rlm@10 42 */
rlm@10 43 byte[] data;
rlm@10 44
rlm@10 45 /**
rlm@10 46 * Actual number of bytes in this vector.
rlm@10 47 */
rlm@10 48 int length;
rlm@10 49
rlm@10 50 /**
rlm@10 51 * Constructs a new {@link ByteVector ByteVector} with a default initial
rlm@10 52 * size.
rlm@10 53 */
rlm@10 54 public ByteVector(){
rlm@10 55 data = new byte[64];
rlm@10 56 }
rlm@10 57
rlm@10 58 /**
rlm@10 59 * Constructs a new {@link ByteVector ByteVector} with the given initial
rlm@10 60 * size.
rlm@10 61 *
rlm@10 62 * @param initialSize the initial size of the byte vector to be constructed.
rlm@10 63 */
rlm@10 64 public ByteVector(final int initialSize){
rlm@10 65 data = new byte[initialSize];
rlm@10 66 }
rlm@10 67
rlm@10 68 /**
rlm@10 69 * Puts a byte into this byte vector. The byte vector is automatically
rlm@10 70 * enlarged if necessary.
rlm@10 71 *
rlm@10 72 * @param b a byte.
rlm@10 73 * @return this byte vector.
rlm@10 74 */
rlm@10 75 public ByteVector putByte(final int b){
rlm@10 76 int length = this.length;
rlm@10 77 if(length + 1 > data.length)
rlm@10 78 {
rlm@10 79 enlarge(1);
rlm@10 80 }
rlm@10 81 data[length++] = (byte) b;
rlm@10 82 this.length = length;
rlm@10 83 return this;
rlm@10 84 }
rlm@10 85
rlm@10 86 /**
rlm@10 87 * Puts two bytes into this byte vector. The byte vector is automatically
rlm@10 88 * enlarged if necessary.
rlm@10 89 *
rlm@10 90 * @param b1 a byte.
rlm@10 91 * @param b2 another byte.
rlm@10 92 * @return this byte vector.
rlm@10 93 */
rlm@10 94 ByteVector put11(final int b1, final int b2){
rlm@10 95 int length = this.length;
rlm@10 96 if(length + 2 > data.length)
rlm@10 97 {
rlm@10 98 enlarge(2);
rlm@10 99 }
rlm@10 100 byte[] data = this.data;
rlm@10 101 data[length++] = (byte) b1;
rlm@10 102 data[length++] = (byte) b2;
rlm@10 103 this.length = length;
rlm@10 104 return this;
rlm@10 105 }
rlm@10 106
rlm@10 107 /**
rlm@10 108 * Puts a short into this byte vector. The byte vector is automatically
rlm@10 109 * enlarged if necessary.
rlm@10 110 *
rlm@10 111 * @param s a short.
rlm@10 112 * @return this byte vector.
rlm@10 113 */
rlm@10 114 public ByteVector putShort(final int s){
rlm@10 115 int length = this.length;
rlm@10 116 if(length + 2 > data.length)
rlm@10 117 {
rlm@10 118 enlarge(2);
rlm@10 119 }
rlm@10 120 byte[] data = this.data;
rlm@10 121 data[length++] = (byte) (s >>> 8);
rlm@10 122 data[length++] = (byte) s;
rlm@10 123 this.length = length;
rlm@10 124 return this;
rlm@10 125 }
rlm@10 126
rlm@10 127 /**
rlm@10 128 * Puts a byte and a short into this byte vector. The byte vector is
rlm@10 129 * automatically enlarged if necessary.
rlm@10 130 *
rlm@10 131 * @param b a byte.
rlm@10 132 * @param s a short.
rlm@10 133 * @return this byte vector.
rlm@10 134 */
rlm@10 135 ByteVector put12(final int b, final int s){
rlm@10 136 int length = this.length;
rlm@10 137 if(length + 3 > data.length)
rlm@10 138 {
rlm@10 139 enlarge(3);
rlm@10 140 }
rlm@10 141 byte[] data = this.data;
rlm@10 142 data[length++] = (byte) b;
rlm@10 143 data[length++] = (byte) (s >>> 8);
rlm@10 144 data[length++] = (byte) s;
rlm@10 145 this.length = length;
rlm@10 146 return this;
rlm@10 147 }
rlm@10 148
rlm@10 149 /**
rlm@10 150 * Puts an int into this byte vector. The byte vector is automatically
rlm@10 151 * enlarged if necessary.
rlm@10 152 *
rlm@10 153 * @param i an int.
rlm@10 154 * @return this byte vector.
rlm@10 155 */
rlm@10 156 public ByteVector putInt(final int i){
rlm@10 157 int length = this.length;
rlm@10 158 if(length + 4 > data.length)
rlm@10 159 {
rlm@10 160 enlarge(4);
rlm@10 161 }
rlm@10 162 byte[] data = this.data;
rlm@10 163 data[length++] = (byte) (i >>> 24);
rlm@10 164 data[length++] = (byte) (i >>> 16);
rlm@10 165 data[length++] = (byte) (i >>> 8);
rlm@10 166 data[length++] = (byte) i;
rlm@10 167 this.length = length;
rlm@10 168 return this;
rlm@10 169 }
rlm@10 170
rlm@10 171 /**
rlm@10 172 * Puts a long into this byte vector. The byte vector is automatically
rlm@10 173 * enlarged if necessary.
rlm@10 174 *
rlm@10 175 * @param l a long.
rlm@10 176 * @return this byte vector.
rlm@10 177 */
rlm@10 178 public ByteVector putLong(final long l){
rlm@10 179 int length = this.length;
rlm@10 180 if(length + 8 > data.length)
rlm@10 181 {
rlm@10 182 enlarge(8);
rlm@10 183 }
rlm@10 184 byte[] data = this.data;
rlm@10 185 int i = (int) (l >>> 32);
rlm@10 186 data[length++] = (byte) (i >>> 24);
rlm@10 187 data[length++] = (byte) (i >>> 16);
rlm@10 188 data[length++] = (byte) (i >>> 8);
rlm@10 189 data[length++] = (byte) i;
rlm@10 190 i = (int) l;
rlm@10 191 data[length++] = (byte) (i >>> 24);
rlm@10 192 data[length++] = (byte) (i >>> 16);
rlm@10 193 data[length++] = (byte) (i >>> 8);
rlm@10 194 data[length++] = (byte) i;
rlm@10 195 this.length = length;
rlm@10 196 return this;
rlm@10 197 }
rlm@10 198
rlm@10 199 /**
rlm@10 200 * Puts an UTF8 string into this byte vector. The byte vector is
rlm@10 201 * automatically enlarged if necessary.
rlm@10 202 *
rlm@10 203 * @param s a String.
rlm@10 204 * @return this byte vector.
rlm@10 205 */
rlm@10 206 public ByteVector putUTF8(final String s){
rlm@10 207 int charLength = s.length();
rlm@10 208 if(length + 2 + charLength > data.length)
rlm@10 209 {
rlm@10 210 enlarge(2 + charLength);
rlm@10 211 }
rlm@10 212 int len = length;
rlm@10 213 byte[] data = this.data;
rlm@10 214 // optimistic algorithm: instead of computing the byte length and then
rlm@10 215 // serializing the string (which requires two loops), we assume the byte
rlm@10 216 // length is equal to char length (which is the most frequent case), and
rlm@10 217 // we start serializing the string right away. During the serialization,
rlm@10 218 // if we find that this assumption is wrong, we continue with the
rlm@10 219 // general method.
rlm@10 220 data[len++] = (byte) (charLength >>> 8);
rlm@10 221 data[len++] = (byte) charLength;
rlm@10 222 for(int i = 0; i < charLength; ++i)
rlm@10 223 {
rlm@10 224 char c = s.charAt(i);
rlm@10 225 if(c >= '\001' && c <= '\177')
rlm@10 226 {
rlm@10 227 data[len++] = (byte) c;
rlm@10 228 }
rlm@10 229 else
rlm@10 230 {
rlm@10 231 int byteLength = i;
rlm@10 232 for(int j = i; j < charLength; ++j)
rlm@10 233 {
rlm@10 234 c = s.charAt(j);
rlm@10 235 if(c >= '\001' && c <= '\177')
rlm@10 236 {
rlm@10 237 byteLength++;
rlm@10 238 }
rlm@10 239 else if(c > '\u07FF')
rlm@10 240 {
rlm@10 241 byteLength += 3;
rlm@10 242 }
rlm@10 243 else
rlm@10 244 {
rlm@10 245 byteLength += 2;
rlm@10 246 }
rlm@10 247 }
rlm@10 248 data[length] = (byte) (byteLength >>> 8);
rlm@10 249 data[length + 1] = (byte) byteLength;
rlm@10 250 if(length + 2 + byteLength > data.length)
rlm@10 251 {
rlm@10 252 length = len;
rlm@10 253 enlarge(2 + byteLength);
rlm@10 254 data = this.data;
rlm@10 255 }
rlm@10 256 for(int j = i; j < charLength; ++j)
rlm@10 257 {
rlm@10 258 c = s.charAt(j);
rlm@10 259 if(c >= '\001' && c <= '\177')
rlm@10 260 {
rlm@10 261 data[len++] = (byte) c;
rlm@10 262 }
rlm@10 263 else if(c > '\u07FF')
rlm@10 264 {
rlm@10 265 data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
rlm@10 266 data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
rlm@10 267 data[len++] = (byte) (0x80 | c & 0x3F);
rlm@10 268 }
rlm@10 269 else
rlm@10 270 {
rlm@10 271 data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
rlm@10 272 data[len++] = (byte) (0x80 | c & 0x3F);
rlm@10 273 }
rlm@10 274 }
rlm@10 275 break;
rlm@10 276 }
rlm@10 277 }
rlm@10 278 length = len;
rlm@10 279 return this;
rlm@10 280 }
rlm@10 281
rlm@10 282 /**
rlm@10 283 * Puts an array of bytes into this byte vector. The byte vector is
rlm@10 284 * automatically enlarged if necessary.
rlm@10 285 *
rlm@10 286 * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
rlm@10 287 * null bytes into this byte vector.
rlm@10 288 * @param off index of the fist byte of b that must be copied.
rlm@10 289 * @param len number of bytes of b that must be copied.
rlm@10 290 * @return this byte vector.
rlm@10 291 */
rlm@10 292 public ByteVector putByteArray(final byte[] b, final int off, final int len){
rlm@10 293 if(length + len > data.length)
rlm@10 294 {
rlm@10 295 enlarge(len);
rlm@10 296 }
rlm@10 297 if(b != null)
rlm@10 298 {
rlm@10 299 System.arraycopy(b, off, data, length, len);
rlm@10 300 }
rlm@10 301 length += len;
rlm@10 302 return this;
rlm@10 303 }
rlm@10 304
rlm@10 305 /**
rlm@10 306 * Enlarge this byte vector so that it can receive n more bytes.
rlm@10 307 *
rlm@10 308 * @param size number of additional bytes that this byte vector should be
rlm@10 309 * able to receive.
rlm@10 310 */
rlm@10 311 private void enlarge(final int size){
rlm@10 312 int length1 = 2 * data.length;
rlm@10 313 int length2 = length + size;
rlm@10 314 byte[] newData = new byte[length1 > length2 ? length1 : length2];
rlm@10 315 System.arraycopy(data, 0, newData, 0, length);
rlm@10 316 data = newData;
rlm@10 317 }
rlm@10 318 }