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