comparison src/org/eclipse/jetty/io/ByteArrayBuffer.java @ 1010:2712133d5bce

simplify Buffer code
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 23 Oct 2016 22:23:50 -0600
parents 3428c60d7cfc
children 4dc1e1a18661
comparison
equal deleted inserted replaced
1009:c3a04bded909 1010:2712133d5bce
29 /** 29 /**
30 * 30 *
31 */ 31 */
32 public class ByteArrayBuffer extends AbstractBuffer 32 public class ByteArrayBuffer extends AbstractBuffer
33 { 33 {
34 // Set a maximum size to a write for the writeTo method, to ensure that very large content is not 34 // Set a maximum size to a write for the writeTo method, to ensure that very large content is not
35 // written as a single write (which may fall foul to write timeouts if consumed slowly). 35 // written as a single write (which may fall foul to write timeouts if consumed slowly).
36 final static int MAX_WRITE=Integer.getInteger("org.eclipse.jetty.io.ByteArrayBuffer.MAX_WRITE",128*1024); 36 final static int MAX_WRITE=Integer.getInteger("org.eclipse.jetty.io.ByteArrayBuffer.MAX_WRITE",128*1024);
37 final protected byte[] _bytes; 37 final protected byte[] _bytes;
38 38
39 protected ByteArrayBuffer(int size, int access, boolean isVolatile) 39 protected ByteArrayBuffer(int size, int access, boolean isVolatile)
40 { 40 {
41 this(new byte[size],0,0,access, isVolatile); 41 this(new byte[size],0,0,access, isVolatile);
42 } 42 }
43 43
44 public ByteArrayBuffer(byte[] bytes) 44 public ByteArrayBuffer(byte[] bytes)
45 { 45 {
46 this(bytes, 0, bytes.length, READWRITE); 46 this(bytes, 0, bytes.length, READWRITE);
47 } 47 }
48 48
49 public ByteArrayBuffer(byte[] bytes, int index, int length) 49 public ByteArrayBuffer(byte[] bytes, int index, int length)
50 { 50 {
51 this(bytes, index, length, READWRITE); 51 this(bytes, index, length, READWRITE);
52 } 52 }
53 53
54 public ByteArrayBuffer(byte[] bytes, int index, int length, int access) 54 public ByteArrayBuffer(byte[] bytes, int index, int length, int access)
55 { 55 {
56 super(READWRITE, NON_VOLATILE); 56 super(READWRITE, NON_VOLATILE);
57 _bytes = bytes; 57 _bytes = bytes;
58 setPutIndex(index + length); 58 setPutIndex(index + length);
59 setGetIndex(index); 59 setGetIndex(index);
60 _access = access; 60 _access = access;
61 } 61 }
62 62
63 public ByteArrayBuffer(byte[] bytes, int index, int length, int access, boolean isVolatile) 63 public ByteArrayBuffer(byte[] bytes, int index, int length, int access, boolean isVolatile)
64 { 64 {
65 super(READWRITE, isVolatile); 65 super(READWRITE, isVolatile);
66 _bytes = bytes; 66 _bytes = bytes;
67 setPutIndex(index + length); 67 setPutIndex(index + length);
68 setGetIndex(index); 68 setGetIndex(index);
69 _access = access; 69 _access = access;
70 } 70 }
71 71
72 public ByteArrayBuffer(int size) 72 public ByteArrayBuffer(int size)
73 { 73 {
74 this(new byte[size], 0, 0, READWRITE); 74 this(new byte[size], 0, 0, READWRITE);
75 setPutIndex(0); 75 setPutIndex(0);
76 } 76 }
77 77
78 public ByteArrayBuffer(String value) 78 public ByteArrayBuffer(String value)
79 { 79 {
80 super(READWRITE,NON_VOLATILE); 80 super(READWRITE,NON_VOLATILE);
81 _bytes = StringUtil.getBytes(value); 81 _bytes = StringUtil.getBytes(value);
82 setGetIndex(0); 82 setGetIndex(0);
83 setPutIndex(_bytes.length); 83 setPutIndex(_bytes.length);
84 _access=IMMUTABLE; 84 _access=IMMUTABLE;
85 _string = value; 85 _string = value;
86 } 86 }
87 87
88 public ByteArrayBuffer(String value,boolean immutable) 88 public ByteArrayBuffer(String value,boolean immutable)
89 { 89 {
90 super(READWRITE,NON_VOLATILE); 90 super(READWRITE,NON_VOLATILE);
91 _bytes = StringUtil.getBytes(value); 91 _bytes = StringUtil.getBytes(value);
92 setGetIndex(0); 92 setGetIndex(0);
93 setPutIndex(_bytes.length); 93 setPutIndex(_bytes.length);
94 if (immutable) 94 if (immutable)
95 { 95 {
96 _access=IMMUTABLE; 96 _access=IMMUTABLE;
97 _string = value; 97 _string = value;
98 } 98 }
99 } 99 }
100 100
101 public ByteArrayBuffer(String value,String encoding) throws UnsupportedEncodingException 101 public ByteArrayBuffer(String value,String encoding) throws UnsupportedEncodingException
102 { 102 {
103 super(READWRITE,NON_VOLATILE); 103 super(READWRITE,NON_VOLATILE);
104 _bytes = value.getBytes(encoding); 104 _bytes = value.getBytes(encoding);
105 setGetIndex(0); 105 setGetIndex(0);
106 setPutIndex(_bytes.length); 106 setPutIndex(_bytes.length);
107 _access=IMMUTABLE; 107 _access=IMMUTABLE;
108 _string = value; 108 _string = value;
109 } 109 }
110 110
111 public byte[] array() 111 public byte[] array()
112 { 112 {
113 return _bytes; 113 return _bytes;
114 } 114 }
115 115
116 public int capacity() 116 public int capacity()
117 { 117 {
118 return _bytes.length; 118 return _bytes.length;
119 } 119 }
120 120
121 @Override 121 @Override
122 public void compact() 122 public void compact()
123 { 123 {
124 if (isReadOnly()) 124 if (isReadOnly())
125 throw new IllegalStateException(__READONLY); 125 throw new IllegalStateException(__READONLY);
126 int s = markIndex() >= 0 ? markIndex() : getIndex(); 126 int s = markIndex() >= 0 ? markIndex() : getIndex();
127 if (s > 0) 127 if (s > 0)
128 { 128 {
129 int length = putIndex() - s; 129 int length = putIndex() - s;
130 if (length > 0) 130 if (length > 0)
131 { 131 {
132 System.arraycopy(_bytes, s,_bytes, 0, length); 132 System.arraycopy(_bytes, s,_bytes, 0, length);
133 } 133 }
134 if (markIndex() > 0) setMarkIndex(markIndex() - s); 134 if (markIndex() > 0) setMarkIndex(markIndex() - s);
135 setGetIndex(getIndex() - s); 135 setGetIndex(getIndex() - s);
136 setPutIndex(putIndex() - s); 136 setPutIndex(putIndex() - s);
137 } 137 }
138 } 138 }
139 139
140 140
141 @Override 141 @Override
142 public boolean equals(Object obj) 142 public boolean equals(Object obj)
143 { 143 {
144 if (obj==this) 144 if (obj==this)
145 return true; 145 return true;
146 146
147 if (obj == null || !(obj instanceof Buffer)) 147 if (obj == null || !(obj instanceof Buffer))
148 return false; 148 return false;
149 149
150 if (obj instanceof Buffer.CaseInsensitve) 150 if (obj instanceof Buffer.CaseInsensitve)
151 return equalsIgnoreCase((Buffer)obj); 151 return equalsIgnoreCase((Buffer)obj);
152 152
153 153
154 Buffer b = (Buffer) obj; 154 Buffer b = (Buffer) obj;
155 155
156 // reject different lengths 156 // reject different lengths
157 if (b.length() != length()) 157 if (b.length() != length())
158 return false; 158 return false;
159 159
160 // reject AbstractBuffer with different hash value 160 // reject AbstractBuffer with different hash value
161 if (_hash != 0 && obj instanceof AbstractBuffer) 161 if (_hash != 0 && obj instanceof AbstractBuffer)
162 { 162 {
163 AbstractBuffer ab = (AbstractBuffer) obj; 163 AbstractBuffer ab = (AbstractBuffer) obj;
164 if (ab._hash != 0 && _hash != ab._hash) 164 if (ab._hash != 0 && _hash != ab._hash)
165 return false; 165 return false;
166 } 166 }
167 167
168 // Nothing for it but to do the hard grind. 168 // Nothing for it but to do the hard grind.
169 int get=getIndex(); 169 int get=getIndex();
170 int bi=b.putIndex(); 170 int bi=b.putIndex();
171 for (int i = putIndex(); i-->get;) 171 for (int i = putIndex(); i-->get;)
172 { 172 {
173 byte b1 = _bytes[i]; 173 byte b1 = _bytes[i];
174 byte b2 = b.peek(--bi); 174 byte b2 = b.peek(--bi);
175 if (b1 != b2) return false; 175 if (b1 != b2) return false;
176 } 176 }
177 return true; 177 return true;
178 } 178 }
179 179
180 180
181 @Override 181 @Override
182 public boolean equalsIgnoreCase(Buffer b) 182 public boolean equalsIgnoreCase(Buffer b)
183 { 183 {
184 if (b==this) 184 if (b==this)
185 return true; 185 return true;
186 186
187 // reject different lengths 187 // reject different lengths
188 if (b==null || b.length() != length()) 188 if (b==null || b.length() != length())
189 return false; 189 return false;
190 190
191 // reject AbstractBuffer with different hash value 191 // reject AbstractBuffer with different hash value
192 if (_hash != 0 && b instanceof AbstractBuffer) 192 if (_hash != 0 && b instanceof AbstractBuffer)
193 { 193 {
194 AbstractBuffer ab = (AbstractBuffer) b; 194 AbstractBuffer ab = (AbstractBuffer) b;
195 if (ab._hash != 0 && _hash != ab._hash) return false; 195 if (ab._hash != 0 && _hash != ab._hash) return false;
196 } 196 }
197 197
198 // Nothing for it but to do the hard grind. 198 // Nothing for it but to do the hard grind.
199 int get=getIndex(); 199 int get=getIndex();
200 int bi=b.putIndex(); 200 int bi=b.putIndex();
201 byte[] barray=b.array(); 201 byte[] barray=b.array();
202 if (barray==null) 202 if (barray==null)
203 { 203 {
204 for (int i = putIndex(); i-->get;) 204 for (int i = putIndex(); i-->get;)
205 { 205 {
206 byte b1 = _bytes[i]; 206 byte b1 = _bytes[i];
207 byte b2 = b.peek(--bi); 207 byte b2 = b.peek(--bi);
208 if (b1 != b2) 208 if (b1 != b2)
209 { 209 {
210 if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A'); 210 if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A');
211 if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A'); 211 if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A');
212 if (b1 != b2) return false; 212 if (b1 != b2) return false;
213 } 213 }
214 } 214 }
215 } 215 }
216 else 216 else
217 { 217 {
218 for (int i = putIndex(); i-->get;) 218 for (int i = putIndex(); i-->get;)
219 { 219 {
220 byte b1 = _bytes[i]; 220 byte b1 = _bytes[i];
221 byte b2 = barray[--bi]; 221 byte b2 = barray[--bi];
222 if (b1 != b2) 222 if (b1 != b2)
223 { 223 {
224 if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A'); 224 if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A');
225 if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A'); 225 if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A');
226 if (b1 != b2) return false; 226 if (b1 != b2) return false;
227 } 227 }
228 } 228 }
229 } 229 }
230 return true; 230 return true;
231 } 231 }
232 232
233 @Override 233 @Override
234 public byte get() 234 public byte get()
235 { 235 {
236 return _bytes[_get++]; 236 return _bytes[_get++];
237 } 237 }
238 238
239 @Override 239 @Override
240 public int hashCode() 240 public int hashCode()
241 { 241 {
242 if (_hash == 0 || _hashGet!=_get || _hashPut!=_put) 242 if (_hash == 0 || _hashGet!=_get || _hashPut!=_put)
243 { 243 {
244 int get=getIndex(); 244 int get=getIndex();
245 for (int i = putIndex(); i-- >get;) 245 for (int i = putIndex(); i-- >get;)
246 { 246 {
247 byte b = _bytes[i]; 247 byte b = _bytes[i];
248 if ('a' <= b && b <= 'z') 248 if ('a' <= b && b <= 'z')
249 b = (byte) (b - 'a' + 'A'); 249 b = (byte) (b - 'a' + 'A');
250 _hash = 31 * _hash + b; 250 _hash = 31 * _hash + b;
251 } 251 }
252 if (_hash == 0) 252 if (_hash == 0)
253 _hash = -1; 253 _hash = -1;
254 _hashGet=_get; 254 _hashGet=_get;
255 _hashPut=_put; 255 _hashPut=_put;
256 } 256 }
257 return _hash; 257 return _hash;
258 } 258 }
259 259
260 260
261 public byte peek(int index) 261 public byte peek(int index)
262 { 262 {
263 return _bytes[index]; 263 return _bytes[index];
264 } 264 }
265 265
266 public int peek(int index, byte[] b, int offset, int length) 266 public int peek(int index, byte[] b, int offset, int length)
267 { 267 {
268 int l = length; 268 int l = length;
269 if (index + l > capacity()) 269 if (index + l > capacity())
270 { 270 {
271 l = capacity() - index; 271 l = capacity() - index;
272 if (l==0) 272 if (l==0)
273 return -1; 273 return -1;
274 } 274 }
275 275
276 if (l < 0) 276 if (l < 0)
277 return -1; 277 return -1;
278 278
279 System.arraycopy(_bytes, index, b, offset, l); 279 System.arraycopy(_bytes, index, b, offset, l);
280 return l; 280 return l;
281 } 281 }
282 282
283 public void poke(int index, byte b) 283 public void poke(int index, byte b)
284 { 284 {
285 /* 285 /*
286 if (isReadOnly()) 286 if (isReadOnly())
287 throw new IllegalStateException(__READONLY); 287 throw new IllegalStateException(__READONLY);
288 288
289 if (index < 0) 289 if (index < 0)
290 throw new IllegalArgumentException("index<0: " + index + "<0"); 290 throw new IllegalArgumentException("index<0: " + index + "<0");
291 if (index > capacity()) 291 if (index > capacity())
292 throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity()); 292 throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
293 */ 293 */
294 _bytes[index] = b; 294 _bytes[index] = b;
295 } 295 }
296 296
297 @Override 297 @Override
298 public int poke(int index, Buffer src) 298 public int poke(int index, Buffer src)
299 { 299 {
300 _hash=0; 300 _hash=0;
301 301
302 /* 302 /*
303 if (isReadOnly()) 303 if (isReadOnly())
304 throw new IllegalStateException(__READONLY); 304 throw new IllegalStateException(__READONLY);
305 if (index < 0) 305 if (index < 0)
306 throw new IllegalArgumentException("index<0: " + index + "<0"); 306 throw new IllegalArgumentException("index<0: " + index + "<0");
307 */ 307 */
308 308
309 int length=src.length(); 309 int length=src.length();
310 if (index + length > capacity()) 310 if (index + length > capacity())
311 { 311 {
312 length=capacity()-index; 312 length=capacity()-index;
313 /* 313 /*
314 if (length<0) 314 if (length<0)
315 throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity()); 315 throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
316 */ 316 */
317 } 317 }
318 318
319 byte[] src_array = src.array(); 319 byte[] src_array = src.array();
320 if (src_array != null) 320 if (src_array != null)
321 System.arraycopy(src_array, src.getIndex(), _bytes, index, length); 321 System.arraycopy(src_array, src.getIndex(), _bytes, index, length);
322 else 322 else
323 { 323 {
324 int s=src.getIndex(); 324 int s=src.getIndex();
325 for (int i=0;i<length;i++) 325 for (int i=0;i<length;i++)
326 _bytes[index++]=src.peek(s++); 326 _bytes[index++]=src.peek(s++);
327 } 327 }
328 328
329 return length; 329 return length;
330 } 330 }
331 331
332 332
333 @Override 333 @Override
334 public int poke(int index, byte[] b, int offset, int length) 334 public int poke(int index, byte[] b, int offset, int length)
335 { 335 {
336 _hash=0; 336 _hash=0;
337 /* 337 /*
338 if (isReadOnly()) 338 if (isReadOnly())
339 throw new IllegalStateException(__READONLY); 339 throw new IllegalStateException(__READONLY);
340 if (index < 0) 340 if (index < 0)
341 throw new IllegalArgumentException("index<0: " + index + "<0"); 341 throw new IllegalArgumentException("index<0: " + index + "<0");
342 */ 342 */
343 343
344 if (index + length > capacity()) 344 if (index + length > capacity())
345 { 345 {
346 length=capacity()-index; 346 length=capacity()-index;
347 /* if (length<0) 347 /* if (length<0)
348 throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity()); 348 throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
349 */ 349 */
350 } 350 }
351 351
352 System.arraycopy(b, offset, _bytes, index, length); 352 System.arraycopy(b, offset, _bytes, index, length);
353 353
354 return length; 354 return length;
355 } 355 }
356 356
357 /* ------------------------------------------------------------ */ 357 @Override
358 @Override 358 public int readFrom(InputStream in,int max) throws IOException
359 public void writeTo(OutputStream out) 359 {
360 throws IOException 360 if (max<0||max>space())
361 { 361 max=space();
362 int len=length(); 362 int p = putIndex();
363 if (MAX_WRITE>0 && len>MAX_WRITE) 363
364 { 364 int len=0, total=0, available=max;
365 int off=getIndex(); 365 while (total<max)
366 while(len>0) 366 {
367 { 367 len=in.read(_bytes,p,available);
368 int c=len>MAX_WRITE?MAX_WRITE:len; 368 if (len<0)
369 out.write(_bytes,off,c); 369 break;
370 off+=c; 370 else if (len>0)
371 len-=c; 371 {
372 } 372 p += len;
373 } 373 total += len;
374 else 374 available -= len;
375 out.write(_bytes,getIndex(),len); 375 setPutIndex(p);
376 if (!isImmutable()) 376 }
377 clear(); 377 if (in.available()<=0)
378 } 378 break;
379 379 }
380 /* ------------------------------------------------------------ */ 380 if (len<0 && total==0)
381 @Override 381 return -1;
382 public int readFrom(InputStream in,int max) throws IOException 382 return total;
383 { 383 }
384 if (max<0||max>space()) 384
385 max=space(); 385 /* ------------------------------------------------------------ */
386 int p = putIndex(); 386 @Override
387 387 public int space()
388 int len=0, total=0, available=max; 388 {
389 while (total<max) 389 return _bytes.length - _put;
390 { 390 }
391 len=in.read(_bytes,p,available); 391
392 if (len<0) 392
393 break; 393 /* ------------------------------------------------------------ */
394 else if (len>0) 394 /* ------------------------------------------------------------ */
395 { 395 /* ------------------------------------------------------------ */
396 p += len; 396 public static class CaseInsensitive extends ByteArrayBuffer implements Buffer.CaseInsensitve
397 total += len; 397 {
398 available -= len; 398 public CaseInsensitive(String s)
399 setPutIndex(p); 399 {
400 } 400 super(s);
401 if (in.available()<=0) 401 }
402 break; 402
403 } 403 public CaseInsensitive(byte[] b, int o, int l, int rw)
404 if (len<0 && total==0) 404 {
405 return -1; 405 super(b,o,l,rw);
406 return total; 406 }
407 } 407
408 408 @Override
409 /* ------------------------------------------------------------ */ 409 public boolean equals(Object obj)
410 @Override 410 {
411 public int space() 411 return obj instanceof Buffer && equalsIgnoreCase((Buffer)obj);
412 { 412 }
413 return _bytes.length - _put; 413
414 } 414 }
415
416
417 /* ------------------------------------------------------------ */
418 /* ------------------------------------------------------------ */
419 /* ------------------------------------------------------------ */
420 public static class CaseInsensitive extends ByteArrayBuffer implements Buffer.CaseInsensitve
421 {
422 public CaseInsensitive(String s)
423 {
424 super(s);
425 }
426
427 public CaseInsensitive(byte[] b, int o, int l, int rw)
428 {
429 super(b,o,l,rw);
430 }
431
432 @Override
433 public boolean equals(Object obj)
434 {
435 return obj instanceof Buffer && equalsIgnoreCase((Buffer)obj);
436 }
437
438 }
439 } 415 }