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