1 17 18 package org.apache.tomcat.util.buf; 19 20 import java.io.IOException ; 21 import java.io.Serializable ; 22 23 36 37 40 64 public final class ByteChunk implements Cloneable , Serializable { 65 66 70 public static interface ByteInputChannel { 71 76 public int realReadBytes(byte cbuf[], int off, int len) 77 throws IOException ; 78 } 79 80 82 public static interface ByteOutputChannel { 83 87 public void realWriteBytes(byte cbuf[], int off, int len) 88 throws IOException ; 89 } 90 91 93 97 public static final String DEFAULT_CHARACTER_ENCODING="ISO-8859-1"; 98 99 private byte[] buff; 101 102 private int start=0; 103 private int end; 104 105 private String enc; 106 107 private boolean isSet=false; 109 private int limit=-1; 111 112 private ByteInputChannel in = null; 113 private ByteOutputChannel out = null; 114 115 private boolean isOutput=false; 116 private boolean optimizedWrite=true; 117 118 121 public ByteChunk() { 122 } 123 124 public ByteChunk( int initial ) { 125 allocate( initial, -1 ); 126 } 127 128 public ByteChunk getClone() { 130 try { 131 return (ByteChunk)this.clone(); 132 } catch( Exception ex) { 133 return null; 134 } 135 } 136 137 public boolean isNull() { 138 return ! isSet; } 140 141 144 public void recycle() { 145 enc=null; 147 start=0; 148 end=0; 149 isSet=false; 150 } 151 152 public void reset() { 153 buff=null; 154 } 155 156 158 public void allocate( int initial, int limit ) { 159 isOutput=true; 160 if( buff==null || buff.length < initial ) { 161 buff=new byte[initial]; 162 } 163 this.limit=limit; 164 start=0; 165 end=0; 166 isSet=true; 167 } 168 169 176 public void setBytes(byte[] b, int off, int len) { 177 buff = b; 178 start = off; 179 end = start+ len; 180 isSet=true; 181 } 182 183 public void setOptimizedWrite(boolean optimizedWrite) { 184 this.optimizedWrite = optimizedWrite; 185 } 186 187 public void setEncoding( String enc ) { 188 this.enc=enc; 189 } 190 public String getEncoding() { 191 if (enc == null) 192 enc=DEFAULT_CHARACTER_ENCODING; 193 return enc; 194 } 195 196 199 public byte[] getBytes() { 200 return getBuffer(); 201 } 202 203 206 public byte[] getBuffer() { 207 return buff; 208 } 209 210 214 public int getStart() { 215 return start; 216 } 217 218 public int getOffset() { 219 return start; 220 } 221 222 public void setOffset(int off) { 223 if (end < off ) end=off; 224 start=off; 225 } 226 227 231 public int getLength() { 232 return end-start; 233 } 234 235 242 public void setLimit(int limit) { 243 this.limit=limit; 244 } 245 246 public int getLimit() { 247 return limit; 248 } 249 250 253 public void setByteInputChannel(ByteInputChannel in) { 254 this.in = in; 255 } 256 257 262 public void setByteOutputChannel(ByteOutputChannel out) { 263 this.out=out; 264 } 265 266 public int getEnd() { 267 return end; 268 } 269 270 public void setEnd( int i ) { 271 end=i; 272 } 273 274 280 public void append( char c ) 281 throws IOException 282 { 283 append( (byte)c); 284 } 285 286 public void append( byte b ) 287 throws IOException 288 { 289 makeSpace( 1 ); 290 291 if( limit >0 && end >= limit ) { 293 flushBuffer(); 294 } 295 buff[end++]=b; 296 } 297 298 public void append( ByteChunk src ) 299 throws IOException 300 { 301 append( src.getBytes(), src.getStart(), src.getLength()); 302 } 303 304 306 public void append( byte src[], int off, int len ) 307 throws IOException 308 { 309 makeSpace( len ); 311 312 if( limit < 0 ) { 314 System.arraycopy( src, off, buff, end, len ); 316 end+=len; 317 return; 318 } 319 320 if ( optimizedWrite && len == limit && end == start && out != null ) { 325 out.realWriteBytes( src, off, len ); 326 return; 327 } 328 if( len <= limit - end ) { 330 System.arraycopy( src, off, buff, end, len ); 333 end+=len; 334 return; 335 } 336 337 340 342 345 int avail=limit-end; 346 System.arraycopy(src, off, buff, end, avail); 347 end += avail; 348 349 flushBuffer(); 350 351 int remain = len - avail; 352 353 while (remain > (limit - end)) { 354 out.realWriteBytes( src, (off + len) - remain, limit - end ); 355 remain = remain - (limit - end); 356 } 357 358 System.arraycopy(src, (off + len) - remain, buff, end, remain); 359 end += remain; 360 361 } 362 363 364 366 public int substract() 367 throws IOException { 368 369 if ((end - start) == 0) { 370 if (in == null) 371 return -1; 372 int n = in.realReadBytes( buff, 0, buff.length ); 373 if (n < 0) 374 return -1; 375 } 376 377 return (buff[start++] & 0xFF); 378 379 } 380 381 public int substract(ByteChunk src) 382 throws IOException { 383 384 if ((end - start) == 0) { 385 if (in == null) 386 return -1; 387 int n = in.realReadBytes( buff, 0, buff.length ); 388 if (n < 0) 389 return -1; 390 } 391 392 int len = getLength(); 393 src.append(buff, start, len); 394 start = end; 395 return len; 396 397 } 398 399 public int substract( byte src[], int off, int len ) 400 throws IOException { 401 402 if ((end - start) == 0) { 403 if (in == null) 404 return -1; 405 int n = in.realReadBytes( buff, 0, buff.length ); 406 if (n < 0) 407 return -1; 408 } 409 410 int n = len; 411 if (len > getLength()) { 412 n = getLength(); 413 } 414 System.arraycopy(buff, start, src, off, n); 415 start += n; 416 return n; 417 418 } 419 420 421 426 public void flushBuffer() 427 throws IOException 428 { 429 if( out==null ) { 431 throw new IOException ( "Buffer overflow, no sink " + limit + " " + 432 buff.length ); 433 } 434 out.realWriteBytes( buff, start, end-start ); 435 end=start; 436 } 437 438 441 private void makeSpace(int count) 442 { 443 byte[] tmp = null; 444 445 int newSize; 446 int desiredSize=end + count; 447 448 if( limit > 0 && 450 desiredSize > limit) { 451 desiredSize=limit; 452 } 453 454 if( buff==null ) { 455 if( desiredSize < 256 ) desiredSize=256; buff=new byte[desiredSize]; 457 } 458 459 if( desiredSize <= buff.length ) { 462 return; 463 } 464 if( desiredSize < 2 * buff.length ) { 466 newSize= buff.length * 2; 467 if( limit >0 && 468 newSize > limit ) newSize=limit; 469 tmp=new byte[newSize]; 470 } else { 471 newSize= buff.length * 2 + count ; 472 if( limit > 0 && 473 newSize > limit ) newSize=limit; 474 tmp=new byte[newSize]; 475 } 476 477 System.arraycopy(buff, start, tmp, 0, end-start); 478 buff = tmp; 479 tmp = null; 480 end=end-start; 481 start=0; 482 } 483 484 486 public String toString() { 487 if (null == buff) { 488 return null; 489 } else if (end-start == 0) { 490 return ""; 491 } 492 return StringCache.toString(this); 493 } 494 495 public String toStringInternal() { 496 String strValue=null; 497 try { 498 if( enc==null ) enc=DEFAULT_CHARACTER_ENCODING; 499 strValue = new String ( buff, start, end-start, enc ); 500 512 } catch (java.io.UnsupportedEncodingException e) { 513 strValue = new String (buff, start, end-start); 516 } 517 return strValue; 518 } 519 520 public int getInt() 521 { 522 return Ascii.parseInt(buff, start,end-start); 523 } 524 525 public long getLong() { 526 return Ascii.parseLong(buff, start,end-start); 527 } 528 529 530 532 537 public boolean equals(String s) { 538 541 byte[] b = buff; 542 int blen = end-start; 543 if (b == null || blen != s.length()) { 544 return false; 545 } 546 int boff = start; 547 for (int i = 0; i < blen; i++) { 548 if (b[boff++] != s.charAt(i)) { 549 return false; 550 } 551 } 552 return true; 553 } 554 555 560 public boolean equalsIgnoreCase(String s) { 561 byte[] b = buff; 562 int blen = end-start; 563 if (b == null || blen != s.length()) { 564 return false; 565 } 566 int boff = start; 567 for (int i = 0; i < blen; i++) { 568 if (Ascii.toLower(b[boff++]) != Ascii.toLower(s.charAt(i))) { 569 return false; 570 } 571 } 572 return true; 573 } 574 575 public boolean equals( ByteChunk bb ) { 576 return equals( bb.getBytes(), bb.getStart(), bb.getLength()); 577 } 578 579 public boolean equals( byte b2[], int off2, int len2) { 580 byte b1[]=buff; 581 if( b1==null && b2==null ) return true; 582 583 int len=end-start; 584 if ( len2 != len || b1==null || b2==null ) 585 return false; 586 587 int off1 = start; 588 589 while ( len-- > 0) { 590 if (b1[off1++] != b2[off2++]) { 591 return false; 592 } 593 } 594 return true; 595 } 596 597 public boolean equals( CharChunk cc ) { 598 return equals( cc.getChars(), cc.getStart(), cc.getLength()); 599 } 600 601 public boolean equals( char c2[], int off2, int len2) { 602 byte b1[]=buff; 604 if( c2==null && b1==null ) return true; 605 606 if (b1== null || c2==null || end-start != len2 ) { 607 return false; 608 } 609 int off1 = start; 610 int len=end-start; 611 612 while ( len-- > 0) { 613 if ( (char)b1[off1++] != c2[off2++]) { 614 return false; 615 } 616 } 617 return true; 618 } 619 620 624 public boolean startsWith(String s) { 625 byte[] b = buff; 627 int blen = s.length(); 628 if (b == null || blen > end-start) { 629 return false; 630 } 631 int boff = start; 632 for (int i = 0; i < blen; i++) { 633 if (b[boff++] != s.charAt(i)) { 634 return false; 635 } 636 } 637 return true; 638 } 639 640 641 public boolean startsWith(byte[] b2) { 642 byte[] b1 = buff; 643 if (b1 == null && b2 == null) { 644 return true; 645 } 646 647 int len = end - start; 648 if (b1 == null || b2 == null || b2.length > len) { 649 return false; 650 } 651 for (int i = start, j = 0; i < end && j < b2.length; ) { 652 if (b1[i++] != b2[j++]) 653 return false; 654 } 655 return true; 656 } 657 658 663 public boolean startsWithIgnoreCase(String s, int pos) { 664 byte[] b = buff; 665 int len = s.length(); 666 if (b == null || len+pos > end-start) { 667 return false; 668 } 669 int off = start+pos; 670 for (int i = 0; i < len; i++) { 671 if (Ascii.toLower( b[off++] ) != Ascii.toLower( s.charAt(i))) { 672 return false; 673 } 674 } 675 return true; 676 } 677 678 public int indexOf( String src, int srcOff, int srcLen, int myOff ) { 679 char first=src.charAt( srcOff ); 680 681 int srcEnd = srcOff + srcLen; 683 684 for( int i=myOff+start; i <= (end - srcLen); i++ ) { 685 if( buff[i] != first ) continue; 686 int myPos=i+1; 688 for( int srcPos=srcOff + 1; srcPos< srcEnd; ) { 689 if( buff[myPos++] != src.charAt( srcPos++ )) 690 break; 691 if( srcPos==srcEnd ) return i-start; } 693 } 694 return -1; 695 } 696 697 699 public int hash() { 701 return hashBytes( buff, start, end-start); 702 } 703 704 public int hashIgnoreCase() { 706 return hashBytesIC( buff, start, end-start ); 707 } 708 709 private static int hashBytes( byte buff[], int start, int bytesLen ) { 710 int max=start+bytesLen; 711 byte bb[]=buff; 712 int code=0; 713 for (int i = start; i < max ; i++) { 714 code = code * 37 + bb[i]; 715 } 716 return code; 717 } 718 719 private static int hashBytesIC( byte bytes[], int start, 720 int bytesLen ) 721 { 722 int max=start+bytesLen; 723 byte bb[]=bytes; 724 int code=0; 725 for (int i = start; i < max ; i++) { 726 code = code * 37 + Ascii.toLower(bb[i]); 727 } 728 return code; 729 } 730 731 736 public int indexOf(char c, int starting) { 737 int ret = indexOf( buff, start+starting, end, c); 738 return (ret >= start) ? ret - start : -1; 739 } 740 741 public static int indexOf( byte bytes[], int off, int end, char qq ) 742 { 743 while( off < end ) { 745 byte b=bytes[off]; 746 if( b==qq ) 747 return off; 748 off++; 749 } 750 return -1; 751 } 752 753 756 public static int findChar( byte buf[], int start, int end, char c ) { 757 byte b=(byte)c; 758 int offset = start; 759 while (offset < end) { 760 if (buf[offset] == b) { 761 return offset; 762 } 763 offset++; 764 } 765 return -1; 766 } 767 768 771 public static int findChars( byte buf[], int start, int end, byte c[] ) { 772 int clen=c.length; 773 int offset = start; 774 while (offset < end) { 775 for( int i=0; i<clen; i++ ) 776 if (buf[offset] == c[i]) { 777 return offset; 778 } 779 offset++; 780 } 781 return -1; 782 } 783 784 787 public static int findNotChars( byte buf[], int start, int end, byte c[] ) 788 { 789 int clen=c.length; 790 int offset = start; 791 boolean found; 792 793 while (offset < end) { 794 found=true; 795 for( int i=0; i<clen; i++ ) { 796 if (buf[offset] == c[i]) { 797 found=false; 798 break; 799 } 800 } 801 if( found ) { return offset; 803 } 804 offset++; 805 } 806 return -1; 807 } 808 809 810 816 public static final byte[] convertToBytes(String value) { 817 byte[] result = new byte[value.length()]; 818 for (int i = 0; i < value.length(); i++) { 819 result[i] = (byte) value.charAt(i); 820 } 821 return result; 822 } 823 824 825 } 826 | Popular Tags |