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