1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.io;
15
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.OutputStream;
19
20 import org.eclipse.jetty.util.TypeUtil;
21 import org.eclipse.jetty.util.log.Log;
22
23
24
25
26
27 public abstract class AbstractBuffer implements Buffer
28 {
29 protected final static String
30 __IMMUTABLE = "IMMUTABLE",
31 __READONLY = "READONLY",
32 __READWRITE = "READWRITE",
33 __VOLATILE = "VOLATILE";
34
35 protected int _access;
36 protected boolean _volatile;
37
38 protected int _get;
39 protected int _put;
40 protected int _hash;
41 protected int _hashGet;
42 protected int _hashPut;
43 protected int _mark;
44 protected String _string;
45 protected View _view;
46
47
48
49
50
51
52 public AbstractBuffer(int access, boolean isVolatile)
53 {
54 if (access == IMMUTABLE && isVolatile)
55 throw new IllegalArgumentException("IMMUTABLE && VOLATILE");
56 setMarkIndex(-1);
57 _access = access;
58 _volatile = isVolatile;
59 }
60
61
62
63
64 public byte[] asArray()
65 {
66 byte[] bytes = new byte[length()];
67 byte[] array = array();
68 if (array != null)
69 System.arraycopy(array, getIndex(), bytes, 0, bytes.length);
70 else
71 peek(getIndex(), bytes, 0, length());
72 return bytes;
73 }
74
75 public ByteArrayBuffer duplicate(int access)
76 {
77 Buffer b=this.buffer();
78 if (this instanceof Buffer.CaseInsensitve || b instanceof Buffer.CaseInsensitve)
79 return new ByteArrayBuffer.CaseInsensitive(asArray(), 0, length(),access);
80 else
81 return new ByteArrayBuffer(asArray(), 0, length(), access);
82 }
83
84
85
86
87 public Buffer asNonVolatileBuffer()
88 {
89 if (!isVolatile()) return this;
90 return duplicate(_access);
91 }
92
93 public Buffer asImmutableBuffer()
94 {
95 if (isImmutable()) return this;
96 return duplicate(IMMUTABLE);
97 }
98
99
100
101
102 public Buffer asReadOnlyBuffer()
103 {
104 if (isReadOnly()) return this;
105 return new View(this, markIndex(), getIndex(), putIndex(), READONLY);
106 }
107
108 public Buffer asMutableBuffer()
109 {
110 if (!isImmutable()) return this;
111
112 Buffer b=this.buffer();
113 if (b.isReadOnly())
114 {
115 return duplicate(READWRITE);
116 }
117 return new View(b, markIndex(), getIndex(), putIndex(), _access);
118 }
119
120 public Buffer buffer()
121 {
122 return this;
123 }
124
125 public void clear()
126 {
127 setMarkIndex(-1);
128 setGetIndex(0);
129 setPutIndex(0);
130 }
131
132 public void compact()
133 {
134 if (isReadOnly()) throw new IllegalStateException(__READONLY);
135 int s = markIndex() >= 0 ? markIndex() : getIndex();
136 if (s > 0)
137 {
138 byte array[] = array();
139 int length = putIndex() - s;
140 if (length > 0)
141 {
142 if (array != null)
143 System.arraycopy(array(), s, array(), 0, length);
144 else
145 poke(0, peek(s, length));
146 }
147 if (markIndex() > 0) setMarkIndex(markIndex() - s);
148 setGetIndex(getIndex() - s);
149 setPutIndex(putIndex() - s);
150 }
151 }
152
153 @Override
154 public boolean equals(Object obj)
155 {
156 if (obj==this)
157 return true;
158
159
160 if (obj == null || !(obj instanceof Buffer)) return false;
161 Buffer b = (Buffer) obj;
162
163 if (this instanceof Buffer.CaseInsensitve || b instanceof Buffer.CaseInsensitve)
164 return equalsIgnoreCase(b);
165
166
167 if (b.length() != length()) return false;
168
169
170 if (_hash != 0 && obj instanceof AbstractBuffer)
171 {
172 AbstractBuffer ab = (AbstractBuffer) obj;
173 if (ab._hash != 0 && _hash != ab._hash) return false;
174 }
175
176
177 int get=getIndex();
178 int bi=b.putIndex();
179 for (int i = putIndex(); i-->get;)
180 {
181 byte b1 = peek(i);
182 byte b2 = b.peek(--bi);
183 if (b1 != b2) return false;
184 }
185 return true;
186 }
187
188 public boolean equalsIgnoreCase(Buffer b)
189 {
190 if (b==this)
191 return true;
192
193
194 if (b.length() != length()) return false;
195
196
197 if (_hash != 0 && b instanceof AbstractBuffer)
198 {
199 AbstractBuffer ab = (AbstractBuffer) b;
200 if (ab._hash != 0 && _hash != ab._hash) return false;
201 }
202
203
204 int get=getIndex();
205 int bi=b.putIndex();
206
207 byte[] array = array();
208 byte[] barray= b.array();
209 if (array!=null && barray!=null)
210 {
211 for (int i = putIndex(); i-->get;)
212 {
213 byte b1 = array[i];
214 byte b2 = barray[--bi];
215 if (b1 != b2)
216 {
217 if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A');
218 if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A');
219 if (b1 != b2) return false;
220 }
221 }
222 }
223 else
224 {
225 for (int i = putIndex(); i-->get;)
226 {
227 byte b1 = peek(i);
228 byte b2 = b.peek(--bi);
229 if (b1 != b2)
230 {
231 if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A');
232 if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A');
233 if (b1 != b2) return false;
234 }
235 }
236 }
237 return true;
238 }
239
240 public byte get()
241 {
242 return peek(_get++);
243 }
244
245 public int get(byte[] b, int offset, int length)
246 {
247 int gi = getIndex();
248 int l=length();
249 if (l==0)
250 return -1;
251
252 if (length>l)
253 length=l;
254
255 length = peek(gi, b, offset, length);
256 if (length>0)
257 setGetIndex(gi + length);
258 return length;
259 }
260
261 public Buffer get(int length)
262 {
263 int gi = getIndex();
264 Buffer view = peek(gi, length);
265 setGetIndex(gi + length);
266 return view;
267 }
268
269 public final int getIndex()
270 {
271 return _get;
272 }
273
274 public boolean hasContent()
275 {
276 return _put > _get;
277 }
278
279 @Override
280 public int hashCode()
281 {
282 if (_hash == 0 || _hashGet!=_get || _hashPut!=_put)
283 {
284 int get=getIndex();
285 byte[] array = array();
286 if (array==null)
287 {
288 for (int i = putIndex(); i-- >get;)
289 {
290 byte b = peek(i);
291 if ('a' <= b && b <= 'z')
292 b = (byte) (b - 'a' + 'A');
293 _hash = 31 * _hash + b;
294 }
295 }
296 else
297 {
298 for (int i = putIndex(); i-- >get;)
299 {
300 byte b = array[i];
301 if ('a' <= b && b <= 'z')
302 b = (byte) (b - 'a' + 'A');
303 _hash = 31 * _hash + b;
304 }
305 }
306 if (_hash == 0)
307 _hash = -1;
308 _hashGet=_get;
309 _hashPut=_put;
310
311 }
312 return _hash;
313 }
314
315 public boolean isImmutable()
316 {
317 return _access <= IMMUTABLE;
318 }
319
320 public boolean isReadOnly()
321 {
322 return _access <= READONLY;
323 }
324
325 public boolean isVolatile()
326 {
327 return _volatile;
328 }
329
330 public int length()
331 {
332 return _put - _get;
333 }
334
335 public void mark()
336 {
337 setMarkIndex(_get - 1);
338 }
339
340 public void mark(int offset)
341 {
342 setMarkIndex(_get + offset);
343 }
344
345 public int markIndex()
346 {
347 return _mark;
348 }
349
350 public byte peek()
351 {
352 return peek(_get);
353 }
354
355 public Buffer peek(int index, int length)
356 {
357 if (_view == null)
358 {
359 _view = new View(this, -1, index, index + length, isReadOnly() ? READONLY : READWRITE);
360 }
361 else
362 {
363 _view.update(this.buffer());
364 _view.setMarkIndex(-1);
365 _view.setGetIndex(0);
366 _view.setPutIndex(index + length);
367 _view.setGetIndex(index);
368
369 }
370 return _view;
371 }
372
373 public int poke(int index, Buffer src)
374 {
375 _hash=0;
376
377
378
379
380
381
382
383 int length=src.length();
384 if (index + length > capacity())
385 {
386 length=capacity()-index;
387
388
389
390
391 }
392
393 byte[] src_array = src.array();
394 byte[] dst_array = array();
395 if (src_array != null && dst_array != null)
396 System.arraycopy(src_array, src.getIndex(), dst_array, index, length);
397 else if (src_array != null)
398 {
399 int s=src.getIndex();
400 for (int i=0;i<length;i++)
401 poke(index++,src_array[s++]);
402 }
403 else if (dst_array != null)
404 {
405 int s=src.getIndex();
406 for (int i=0;i<length;i++)
407 dst_array[index++]=src.peek(s++);
408 }
409 else
410 {
411 int s=src.getIndex();
412 for (int i=0;i<length;i++)
413 poke(index++,src.peek(s++));
414 }
415
416 return length;
417 }
418
419
420 public int poke(int index, byte[] b, int offset, int length)
421 {
422 _hash=0;
423
424
425
426
427
428
429 if (index + length > capacity())
430 {
431 length=capacity()-index;
432
433
434
435 }
436
437 byte[] dst_array = array();
438 if (dst_array != null)
439 System.arraycopy(b, offset, dst_array, index, length);
440 else
441 {
442 int s=offset;
443 for (int i=0;i<length;i++)
444 poke(index++,b[s++]);
445 }
446 return length;
447 }
448
449 public int put(Buffer src)
450 {
451 int pi = putIndex();
452 int l=poke(pi, src);
453 setPutIndex(pi + l);
454 return l;
455 }
456
457 public void put(byte b)
458 {
459 int pi = putIndex();
460 poke(pi, b);
461 setPutIndex(pi + 1);
462 }
463
464 public int put(byte[] b, int offset, int length)
465 {
466 int pi = putIndex();
467 int l = poke(pi, b, offset, length);
468 setPutIndex(pi + l);
469 return l;
470 }
471
472 public int put(byte[] b)
473 {
474 int pi = putIndex();
475 int l = poke(pi, b, 0, b.length);
476 setPutIndex(pi + l);
477 return l;
478 }
479
480 public final int putIndex()
481 {
482 return _put;
483 }
484
485 public void reset()
486 {
487 if (markIndex() >= 0) setGetIndex(markIndex());
488 }
489
490 public void rewind()
491 {
492 setGetIndex(0);
493 setMarkIndex(-1);
494 }
495
496 public void setGetIndex(int getIndex)
497 {
498
499
500
501
502
503
504
505
506 _get = getIndex;
507 _hash=0;
508 }
509
510 public void setMarkIndex(int index)
511 {
512
513
514
515
516 _mark = index;
517 }
518
519 public void setPutIndex(int putIndex)
520 {
521
522
523
524
525
526
527
528
529 _put = putIndex;
530 _hash=0;
531 }
532
533 public int skip(int n)
534 {
535 if (length() < n) n = length();
536 setGetIndex(getIndex() + n);
537 return n;
538 }
539
540 public Buffer slice()
541 {
542 return peek(getIndex(), length());
543 }
544
545 public Buffer sliceFromMark()
546 {
547 return sliceFromMark(getIndex() - markIndex() - 1);
548 }
549
550 public Buffer sliceFromMark(int length)
551 {
552 if (markIndex() < 0) return null;
553 Buffer view = peek(markIndex(), length);
554 setMarkIndex(-1);
555 return view;
556 }
557
558 public int space()
559 {
560 return capacity() - _put;
561 }
562
563 public String toDetailString()
564 {
565 StringBuilder buf = new StringBuilder();
566 buf.append("[");
567 buf.append(super.hashCode());
568 buf.append(",");
569 buf.append(this.buffer().hashCode());
570 buf.append(",m=");
571 buf.append(markIndex());
572 buf.append(",g=");
573 buf.append(getIndex());
574 buf.append(",p=");
575 buf.append(putIndex());
576 buf.append(",c=");
577 buf.append(capacity());
578 buf.append("]={");
579 if (markIndex() >= 0)
580 {
581 for (int i = markIndex(); i < getIndex(); i++)
582 {
583 byte b = peek(i);
584 TypeUtil.toHex(b,buf);
585 }
586 buf.append("}{");
587 }
588 int count = 0;
589 for (int i = getIndex(); i < putIndex(); i++)
590 {
591 byte b = peek(i);
592 TypeUtil.toHex(b,buf);
593 if (count++ == 50)
594 {
595 if (putIndex() - i > 20)
596 {
597 buf.append(" ... ");
598 i = putIndex() - 20;
599 }
600 }
601 }
602 buf.append('}');
603 return buf.toString();
604 }
605
606
607 @Override
608 public String toString()
609 {
610 if (isImmutable())
611 {
612 if (_string == null)
613 _string = new String(asArray(), 0, length());
614 return _string;
615 }
616 return new String(asArray(), 0, length());
617 }
618
619
620 public String toString(String charset)
621 {
622 try
623 {
624 byte[] bytes=array();
625 if (bytes!=null)
626 return new String(bytes,getIndex(),length(),charset);
627 return new String(asArray(), 0, length(),charset);
628
629 }
630 catch(Exception e)
631 {
632 Log.warn(e);
633 return new String(asArray(), 0, length());
634 }
635 }
636
637
638 public String toDebugString()
639 {
640 return getClass()+"@"+super.hashCode();
641 }
642
643
644 public void writeTo(OutputStream out)
645 throws IOException
646 {
647 byte[] array = array();
648
649 if (array!=null)
650 {
651 out.write(array,getIndex(),length());
652 }
653 else
654 {
655 int len = this.length();
656 byte[] buf=new byte[len>1024?1024:len];
657 int offset=_get;
658 while (len>0)
659 {
660 int l=peek(offset,buf,0,len>buf.length?buf.length:len);
661 out.write(buf,0,l);
662 offset+=l;
663 len-=l;
664 }
665 }
666 clear();
667 }
668
669
670 public int readFrom(InputStream in,int max) throws IOException
671 {
672 byte[] array = array();
673 int s=space();
674 if (s>max)
675 s=max;
676
677 if (array!=null)
678 {
679 int l=in.read(array,_put,s);
680 if (l>0)
681 _put+=l;
682 return l;
683 }
684 else
685 {
686 byte[] buf=new byte[s>1024?1024:s];
687 int total=0;
688 while (s>0)
689 {
690 int l=in.read(buf,0,buf.length);
691 if (l<0)
692 return total>0?total:-1;
693 int p=put(buf,0,l);
694 assert l==p;
695 s-=l;
696 }
697 return total;
698 }
699 }
700 }