1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.io;
16
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.OutputStream;
20
21 import org.mortbay.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 (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 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 public int hashCode()
279 {
280 if (_hash == 0 || _hashGet!=_get || _hashPut!=_put)
281 {
282 int get=getIndex();
283 byte[] array = array();
284 if (array==null)
285 {
286 for (int i = putIndex(); i-- >get;)
287 {
288 byte b = peek(i);
289 if ('a' <= b && b <= 'z')
290 b = (byte) (b - 'a' + 'A');
291 _hash = 31 * _hash + b;
292 }
293 }
294 else
295 {
296 for (int i = putIndex(); i-- >get;)
297 {
298 byte b = array[i];
299 if ('a' <= b && b <= 'z')
300 b = (byte) (b - 'a' + 'A');
301 _hash = 31 * _hash + b;
302 }
303 }
304 if (_hash == 0)
305 _hash = -1;
306 _hashGet=_get;
307 _hashPut=_put;
308
309 }
310 return _hash;
311 }
312
313 public boolean isImmutable()
314 {
315 return _access <= IMMUTABLE;
316 }
317
318 public boolean isReadOnly()
319 {
320 return _access <= READONLY;
321 }
322
323 public boolean isVolatile()
324 {
325 return _volatile;
326 }
327
328 public int length()
329 {
330 return _put - _get;
331 }
332
333 public void mark()
334 {
335 setMarkIndex(_get - 1);
336 }
337
338 public void mark(int offset)
339 {
340 setMarkIndex(_get + offset);
341 }
342
343 public int markIndex()
344 {
345 return _mark;
346 }
347
348 public byte peek()
349 {
350 return peek(_get);
351 }
352
353 public Buffer peek(int index, int length)
354 {
355 if (_view == null)
356 {
357 _view = new View(this, -1, index, index + length, isReadOnly() ? READONLY : READWRITE);
358 }
359 else
360 {
361 _view.update(this.buffer());
362 _view.setMarkIndex(-1);
363 _view.setGetIndex(0);
364 _view.setPutIndex(index + length);
365 _view.setGetIndex(index);
366
367 }
368 return _view;
369 }
370
371 public int poke(int index, Buffer src)
372 {
373 _hash=0;
374
375
376
377
378
379
380
381 int length=src.length();
382 if (index + length > capacity())
383 {
384 length=capacity()-index;
385
386
387
388
389 }
390
391 byte[] src_array = src.array();
392 byte[] dst_array = array();
393 if (src_array != null && dst_array != null)
394 System.arraycopy(src_array, src.getIndex(), dst_array, index, length);
395 else if (src_array != null)
396 {
397 int s=src.getIndex();
398 for (int i=0;i<length;i++)
399 poke(index++,src_array[s++]);
400 }
401 else if (dst_array != null)
402 {
403 int s=src.getIndex();
404 for (int i=0;i<length;i++)
405 dst_array[index++]=src.peek(s++);
406 }
407 else
408 {
409 int s=src.getIndex();
410 for (int i=0;i<length;i++)
411 poke(index++,src.peek(s++));
412 }
413
414 return length;
415 }
416
417
418 public int poke(int index, byte[] b, int offset, int length)
419 {
420 _hash=0;
421
422
423
424
425
426
427 if (index + length > capacity())
428 {
429 length=capacity()-index;
430
431
432
433 }
434
435 byte[] dst_array = array();
436 if (dst_array != null)
437 System.arraycopy(b, offset, dst_array, index, length);
438 else
439 {
440 int s=offset;
441 for (int i=0;i<length;i++)
442 poke(index++,b[s++]);
443 }
444 return length;
445 }
446
447 public int put(Buffer src)
448 {
449 int pi = putIndex();
450 int l=poke(pi, src);
451 setPutIndex(pi + l);
452 return l;
453 }
454
455 public void put(byte b)
456 {
457 int pi = putIndex();
458 poke(pi, b);
459 setPutIndex(pi + 1);
460 }
461
462 public int put(byte[] b, int offset, int length)
463 {
464 int pi = putIndex();
465 int l = poke(pi, b, offset, length);
466 setPutIndex(pi + l);
467 return l;
468 }
469
470 public int put(byte[] b)
471 {
472 int pi = putIndex();
473 int l = poke(pi, b, 0, b.length);
474 setPutIndex(pi + l);
475 return l;
476 }
477
478 public final int putIndex()
479 {
480 return _put;
481 }
482
483 public void reset()
484 {
485 if (markIndex() >= 0) setGetIndex(markIndex());
486 }
487
488 public void rewind()
489 {
490 setGetIndex(0);
491 setMarkIndex(-1);
492 }
493
494 public void setGetIndex(int getIndex)
495 {
496
497
498
499
500
501
502
503
504 _get = getIndex;
505 _hash=0;
506 }
507
508 public void setMarkIndex(int index)
509 {
510
511
512
513
514 _mark = index;
515 }
516
517 public void setPutIndex(int putIndex)
518 {
519
520
521
522
523
524
525
526
527 _put = putIndex;
528 _hash=0;
529 }
530
531 public int skip(int n)
532 {
533 if (length() < n) n = length();
534 setGetIndex(getIndex() + n);
535 return n;
536 }
537
538 public Buffer slice()
539 {
540 return peek(getIndex(), length());
541 }
542
543 public Buffer sliceFromMark()
544 {
545 return sliceFromMark(getIndex() - markIndex() - 1);
546 }
547
548 public Buffer sliceFromMark(int length)
549 {
550 if (markIndex() < 0) return null;
551 Buffer view = peek(markIndex(), length);
552 setMarkIndex(-1);
553 return view;
554 }
555
556 public int space()
557 {
558 return capacity() - _put;
559 }
560
561 public String toDetailString()
562 {
563 StringBuilder buf = new StringBuilder();
564 buf.append("[");
565 buf.append(super.hashCode());
566 buf.append(",");
567 buf.append(this.array().hashCode());
568 buf.append(",m=");
569 buf.append(markIndex());
570 buf.append(",g=");
571 buf.append(getIndex());
572 buf.append(",p=");
573 buf.append(putIndex());
574 buf.append(",c=");
575 buf.append(capacity());
576 buf.append("]={");
577 if (markIndex() >= 0)
578 {
579 for (int i = markIndex(); i < getIndex(); i++)
580 {
581 char c = (char) peek(i);
582 if (Character.isISOControl(c))
583 {
584 buf.append(c < 16 ? "\\0" : "\\");
585 buf.append(Integer.toString(c, 16));
586 }
587 else
588 buf.append(c);
589 }
590 buf.append("}{");
591 }
592 int count = 0;
593 for (int i = getIndex(); i < putIndex(); i++)
594 {
595 char c = (char) peek(i);
596 if (Character.isISOControl(c))
597 {
598 buf.append(c < 16 ? "\\0" : "\\");
599 buf.append(Integer.toString(c, 16));
600 }
601 else
602 buf.append(c);
603 if (count++ == 50)
604 {
605 if (putIndex() - i > 20)
606 {
607 buf.append(" ... ");
608 i = putIndex() - 20;
609 }
610 }
611 }
612 buf.append('}');
613 return buf.toString();
614 }
615
616
617 public String toString()
618 {
619 if (isImmutable())
620 {
621 if (_string == null)
622 _string = new String(asArray(), 0, length());
623 return _string;
624 }
625 return new String(asArray(), 0, length());
626 }
627
628
629 public String toString(String charset)
630 {
631 try
632 {
633 byte[] bytes=array();
634 if (bytes!=null)
635 return new String(bytes,getIndex(),length(),charset);
636 return new String(asArray(), 0, length(),charset);
637 }
638 catch(Exception e)
639 {
640 Log.warn(e);
641 return new String(asArray(), 0, length());
642 }
643 }
644
645
646 public String toDebugString()
647 {
648 return getClass()+"@"+super.hashCode();
649 }
650
651
652 public void writeTo(OutputStream out)
653 throws IOException
654 {
655 byte[] array = array();
656
657 if (array!=null)
658 {
659 out.write(array,getIndex(),length());
660 }
661 else
662 {
663 int len = this.length();
664 byte[] buf=new byte[len>1024?1024:len];
665 int offset=_get;
666 while (len>0)
667 {
668 int l=peek(offset,buf,0,len>buf.length?buf.length:len);
669 out.write(buf,0,l);
670 offset+=l;
671 len-=l;
672 }
673 }
674 clear();
675 }
676
677
678 public int readFrom(InputStream in,int max) throws IOException
679 {
680 byte[] array = array();
681 int s=space();
682 if (s>max)
683 s=max;
684
685 if (array!=null)
686 {
687 int l=in.read(array,_put,s);
688 if (l>0)
689 _put+=l;
690 return l;
691 }
692 else
693 {
694 byte[] buf=new byte[s>1024?1024:s];
695 int total=0;
696 while (s>0)
697 {
698 int l=in.read(buf,0,buf.length);
699 if (l<0)
700 return total>0?total:-1;
701 int p=put(buf,0,l);
702 assert l==p;
703 s-=l;
704 }
705 return total;
706 }
707 }
708 }