71 */ 72 byte[] data; 73 74 /** 75 * Actual number of bytes in this vector. 76 */ 77 int length; 78 79 /** 80 * Constructs a new {@link ByteVector ByteVector} with a default initial 81 * size. 82 */ 83 public ByteVector() { 84 data = new byte[64]; 85 } 86 87 /** 88 * Constructs a new {@link ByteVector ByteVector} with the given initial 89 * size. 90 * 91 * @param initialSize the initial size of the byte vector to be constructed. 92 */ 93 public ByteVector(final int initialSize) { 94 data = new byte[initialSize]; 95 } 96 97 /** 98 * Puts a byte into this byte vector. The byte vector is automatically 99 * enlarged if necessary. 100 * 101 * @param b a byte. 102 * @return this byte vector. 103 */ 104 public ByteVector putByte(final int b) { 105 int length = this.length; 106 if (length + 1 > data.length) { 107 enlarge(1); 108 } 109 data[length++] = (byte) b; 110 this.length = length; 111 return this; 112 } 113 114 /** 115 * Puts two bytes into this byte vector. The byte vector is automatically 116 * enlarged if necessary. 117 * 118 * @param b1 a byte. 119 * @param b2 another byte. 120 * @return this byte vector. 121 */ 122 ByteVector put11(final int b1, final int b2) { 123 int length = this.length; 124 if (length + 2 > data.length) { 125 enlarge(2); 126 } 127 byte[] data = this.data; 128 data[length++] = (byte) b1; 129 data[length++] = (byte) b2; 130 this.length = length; 131 return this; 132 } 133 134 /** 135 * Puts a short into this byte vector. The byte vector is automatically 136 * enlarged if necessary. 137 * 138 * @param s a short. 139 * @return this byte vector. 140 */ 141 public ByteVector putShort(final int s) { 142 int length = this.length; 143 if (length + 2 > data.length) { 144 enlarge(2); 145 } 146 byte[] data = this.data; 147 data[length++] = (byte) (s >>> 8); 148 data[length++] = (byte) s; 149 this.length = length; 150 return this; 151 } 152 153 /** 154 * Puts a byte and a short into this byte vector. The byte vector is 155 * automatically enlarged if necessary. 156 * 157 * @param b a byte. 158 * @param s a short. 159 * @return this byte vector. 160 */ 161 ByteVector put12(final int b, final int s) { 162 int length = this.length; 163 if (length + 3 > data.length) { 164 enlarge(3); 165 } 166 byte[] data = this.data; 167 data[length++] = (byte) b; 168 data[length++] = (byte) (s >>> 8); 169 data[length++] = (byte) s; 170 this.length = length; 171 return this; 172 } 173 174 /** 175 * Puts an int into this byte vector. The byte vector is automatically 176 * enlarged if necessary. 177 * 178 * @param i an int. 179 * @return this byte vector. 180 */ 181 public ByteVector putInt(final int i) { 182 int length = this.length; 183 if (length + 4 > data.length) { 184 enlarge(4); 185 } 186 byte[] data = this.data; 187 data[length++] = (byte) (i >>> 24); 188 data[length++] = (byte) (i >>> 16); 189 data[length++] = (byte) (i >>> 8); 190 data[length++] = (byte) i; 191 this.length = length; 192 return this; 193 } 194 195 /** 196 * Puts a long into this byte vector. The byte vector is automatically 197 * enlarged if necessary. 198 * 199 * @param l a long. 200 * @return this byte vector. 201 */ 202 public ByteVector putLong(final long l) { 203 int length = this.length; 204 if (length + 8 > data.length) { 205 enlarge(8); 206 } 207 byte[] data = this.data; 208 int i = (int) (l >>> 32); 209 data[length++] = (byte) (i >>> 24); 210 data[length++] = (byte) (i >>> 16); 211 data[length++] = (byte) (i >>> 8); 212 data[length++] = (byte) i; 213 i = (int) l; 214 data[length++] = (byte) (i >>> 24); 215 data[length++] = (byte) (i >>> 16); 216 data[length++] = (byte) (i >>> 8); 217 data[length++] = (byte) i; 218 this.length = length; 219 return this; 220 } 221 222 /** 223 * Puts an UTF8 string into this byte vector. The byte vector is 224 * automatically enlarged if necessary. 225 * 226 * @param s a String. 227 * @return this byte vector. 228 */ 229 public ByteVector putUTF8(final String s) { 230 int charLength = s.length(); 231 int len = length; 232 if (len + 2 + charLength > data.length) { 233 enlarge(2 + charLength); 234 } 235 byte[] data = this.data; 236 // optimistic algorithm: instead of computing the byte length and then 237 // serializing the string (which requires two loops), we assume the byte 238 // length is equal to char length (which is the most frequent case), and 239 // we start serializing the string right away. During the serialization, 240 // if we find that this assumption is wrong, we continue with the 241 // general method. 242 data[len++] = (byte) (charLength >>> 8); 243 data[len++] = (byte) charLength; 244 for (int i = 0; i < charLength; ++i) { 245 char c = s.charAt(i); 246 if (c >= '\001' && c <= '\177') { 271 } else if (c > '\u07FF') { 272 data[len++] = (byte) (0xE0 | c >> 12 & 0xF); 273 data[len++] = (byte) (0x80 | c >> 6 & 0x3F); 274 data[len++] = (byte) (0x80 | c & 0x3F); 275 } else { 276 data[len++] = (byte) (0xC0 | c >> 6 & 0x1F); 277 data[len++] = (byte) (0x80 | c & 0x3F); 278 } 279 } 280 break; 281 } 282 } 283 length = len; 284 return this; 285 } 286 287 /** 288 * Puts an array of bytes into this byte vector. The byte vector is 289 * automatically enlarged if necessary. 290 * 291 * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt> 292 * null bytes into this byte vector. 293 * @param off index of the fist byte of b that must be copied. 294 * @param len number of bytes of b that must be copied. 295 * @return this byte vector. 296 */ 297 public ByteVector putByteArray(final byte[] b, final int off, final int len) 298 { 299 if (length + len > data.length) { 300 enlarge(len); 301 } 302 if (b != null) { 303 System.arraycopy(b, off, data, length, len); 304 } 305 length += len; 306 return this; 307 } 308 309 /** 310 * Enlarge this byte vector so that it can receive n more bytes. 311 * 312 * @param size number of additional bytes that this byte vector should be 313 * able to receive. 314 */ 315 private void enlarge(final int size) { 316 int length1 = 2 * data.length; 317 int length2 = length + size; 318 byte[] newData = new byte[length1 > length2 ? length1 : length2]; 319 System.arraycopy(data, 0, newData, 0, length); 320 data = newData; 321 } 322 } | 71 */ 72 byte[] data; 73 74 /** 75 * Actual number of bytes in this vector. 76 */ 77 int length; 78 79 /** 80 * Constructs a new {@link ByteVector ByteVector} with a default initial 81 * size. 82 */ 83 public ByteVector() { 84 data = new byte[64]; 85 } 86 87 /** 88 * Constructs a new {@link ByteVector ByteVector} with the given initial 89 * size. 90 * 91 * @param initialSize 92 * the initial size of the byte vector to be constructed. 93 */ 94 public ByteVector(final int initialSize) { 95 data = new byte[initialSize]; 96 } 97 98 /** 99 * Puts a byte into this byte vector. The byte vector is automatically 100 * enlarged if necessary. 101 * 102 * @param b 103 * a byte. 104 * @return this byte vector. 105 */ 106 public ByteVector putByte(final int b) { 107 int length = this.length; 108 if (length + 1 > data.length) { 109 enlarge(1); 110 } 111 data[length++] = (byte) b; 112 this.length = length; 113 return this; 114 } 115 116 /** 117 * Puts two bytes into this byte vector. The byte vector is automatically 118 * enlarged if necessary. 119 * 120 * @param b1 121 * a byte. 122 * @param b2 123 * another byte. 124 * @return this byte vector. 125 */ 126 ByteVector put11(final int b1, final int b2) { 127 int length = this.length; 128 if (length + 2 > data.length) { 129 enlarge(2); 130 } 131 byte[] data = this.data; 132 data[length++] = (byte) b1; 133 data[length++] = (byte) b2; 134 this.length = length; 135 return this; 136 } 137 138 /** 139 * Puts a short into this byte vector. The byte vector is automatically 140 * enlarged if necessary. 141 * 142 * @param s 143 * a short. 144 * @return this byte vector. 145 */ 146 public ByteVector putShort(final int s) { 147 int length = this.length; 148 if (length + 2 > data.length) { 149 enlarge(2); 150 } 151 byte[] data = this.data; 152 data[length++] = (byte) (s >>> 8); 153 data[length++] = (byte) s; 154 this.length = length; 155 return this; 156 } 157 158 /** 159 * Puts a byte and a short into this byte vector. The byte vector is 160 * automatically enlarged if necessary. 161 * 162 * @param b 163 * a byte. 164 * @param s 165 * a short. 166 * @return this byte vector. 167 */ 168 ByteVector put12(final int b, final int s) { 169 int length = this.length; 170 if (length + 3 > data.length) { 171 enlarge(3); 172 } 173 byte[] data = this.data; 174 data[length++] = (byte) b; 175 data[length++] = (byte) (s >>> 8); 176 data[length++] = (byte) s; 177 this.length = length; 178 return this; 179 } 180 181 /** 182 * Puts an int into this byte vector. The byte vector is automatically 183 * enlarged if necessary. 184 * 185 * @param i 186 * an int. 187 * @return this byte vector. 188 */ 189 public ByteVector putInt(final int i) { 190 int length = this.length; 191 if (length + 4 > data.length) { 192 enlarge(4); 193 } 194 byte[] data = this.data; 195 data[length++] = (byte) (i >>> 24); 196 data[length++] = (byte) (i >>> 16); 197 data[length++] = (byte) (i >>> 8); 198 data[length++] = (byte) i; 199 this.length = length; 200 return this; 201 } 202 203 /** 204 * Puts a long into this byte vector. The byte vector is automatically 205 * enlarged if necessary. 206 * 207 * @param l 208 * a long. 209 * @return this byte vector. 210 */ 211 public ByteVector putLong(final long l) { 212 int length = this.length; 213 if (length + 8 > data.length) { 214 enlarge(8); 215 } 216 byte[] data = this.data; 217 int i = (int) (l >>> 32); 218 data[length++] = (byte) (i >>> 24); 219 data[length++] = (byte) (i >>> 16); 220 data[length++] = (byte) (i >>> 8); 221 data[length++] = (byte) i; 222 i = (int) l; 223 data[length++] = (byte) (i >>> 24); 224 data[length++] = (byte) (i >>> 16); 225 data[length++] = (byte) (i >>> 8); 226 data[length++] = (byte) i; 227 this.length = length; 228 return this; 229 } 230 231 /** 232 * Puts an UTF8 string into this byte vector. The byte vector is 233 * automatically enlarged if necessary. 234 * 235 * @param s 236 * a String. 237 * @return this byte vector. 238 */ 239 public ByteVector putUTF8(final String s) { 240 int charLength = s.length(); 241 int len = length; 242 if (len + 2 + charLength > data.length) { 243 enlarge(2 + charLength); 244 } 245 byte[] data = this.data; 246 // optimistic algorithm: instead of computing the byte length and then 247 // serializing the string (which requires two loops), we assume the byte 248 // length is equal to char length (which is the most frequent case), and 249 // we start serializing the string right away. During the serialization, 250 // if we find that this assumption is wrong, we continue with the 251 // general method. 252 data[len++] = (byte) (charLength >>> 8); 253 data[len++] = (byte) charLength; 254 for (int i = 0; i < charLength; ++i) { 255 char c = s.charAt(i); 256 if (c >= '\001' && c <= '\177') { 281 } else if (c > '\u07FF') { 282 data[len++] = (byte) (0xE0 | c >> 12 & 0xF); 283 data[len++] = (byte) (0x80 | c >> 6 & 0x3F); 284 data[len++] = (byte) (0x80 | c & 0x3F); 285 } else { 286 data[len++] = (byte) (0xC0 | c >> 6 & 0x1F); 287 data[len++] = (byte) (0x80 | c & 0x3F); 288 } 289 } 290 break; 291 } 292 } 293 length = len; 294 return this; 295 } 296 297 /** 298 * Puts an array of bytes into this byte vector. The byte vector is 299 * automatically enlarged if necessary. 300 * 301 * @param b 302 * an array of bytes. May be <tt>null</tt> to put <tt>len</tt> 303 * null bytes into this byte vector. 304 * @param off 305 * index of the fist byte of b that must be copied. 306 * @param len 307 * number of bytes of b that must be copied. 308 * @return this byte vector. 309 */ 310 public ByteVector putByteArray(final byte[] b, final int off, final int len) { 311 if (length + len > data.length) { 312 enlarge(len); 313 } 314 if (b != null) { 315 System.arraycopy(b, off, data, length, len); 316 } 317 length += len; 318 return this; 319 } 320 321 /** 322 * Enlarge this byte vector so that it can receive n more bytes. 323 * 324 * @param size 325 * number of additional bytes that this byte vector should be 326 * able to receive. 327 */ 328 private void enlarge(final int size) { 329 int length1 = 2 * data.length; 330 int length2 = length + size; 331 byte[] newData = new byte[length1 > length2 ? length1 : length2]; 332 System.arraycopy(data, 0, newData, 0, length); 333 data = newData; 334 } 335 } |