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