1 17 18 package org.apache.tomcat.util.buf; 19 20 import java.io.IOException ; 21 import java.io.Serializable ; 22 23 34 public final class CharChunk implements Cloneable , Serializable , CharSequence { 35 36 public static interface CharInputChannel { 38 43 public int realReadChars(char cbuf[], int off, int len) 44 throws IOException ; 45 } 46 50 public static interface CharOutputChannel { 51 54 public void realWriteChars(char cbuf[], int off, int len) 55 throws IOException ; 56 } 57 58 private char buff[]; 61 62 private int start; 63 private int end; 64 65 private boolean isSet=false; 67 private boolean isOutput=false; 68 69 private int limit=-1; 72 73 private CharInputChannel in = null; 74 private CharOutputChannel out = null; 75 76 private boolean optimizedWrite=true; 77 78 81 public CharChunk() { 82 } 83 84 public CharChunk(int size) { 85 allocate( size, -1 ); 86 } 87 88 90 public CharChunk getClone() { 91 try { 92 return (CharChunk)this.clone(); 93 } catch( Exception ex) { 94 return null; 95 } 96 } 97 98 public boolean isNull() { 99 if( end > 0 ) return false; 100 return !isSet; } 102 103 106 public void recycle() { 107 isSet=false; start=0; 110 end=0; 111 } 112 113 public void reset() { 114 buff=null; 115 } 116 117 119 public void allocate( int initial, int limit ) { 120 isOutput=true; 121 if( buff==null || buff.length < initial ) { 122 buff=new char[initial]; 123 } 124 this.limit=limit; 125 start=0; 126 end=0; 127 isOutput=true; 128 isSet=true; 129 } 130 131 132 public void setOptimizedWrite(boolean optimizedWrite) { 133 this.optimizedWrite = optimizedWrite; 134 } 135 136 public void setChars( char[] c, int off, int len ) { 137 buff=c; 138 start=off; 139 end=start + len; 140 isSet=true; 141 } 142 143 150 public void setLimit(int limit) { 151 this.limit=limit; 152 } 153 154 public int getLimit() { 155 return limit; 156 } 157 158 161 public void setCharInputChannel(CharInputChannel in) { 162 this.in = in; 163 } 164 165 170 public void setCharOutputChannel(CharOutputChannel out) { 171 this.out=out; 172 } 173 174 public char[] getChars() 176 { 177 return getBuffer(); 178 } 179 180 public char[] getBuffer() 181 { 182 return buff; 183 } 184 185 189 public int getStart() { 190 return start; 191 } 192 193 public int getOffset() { 194 return start; 195 } 196 197 200 public void setOffset(int off) { 201 start=off; 202 } 203 204 207 public int getLength() { 208 return end-start; 209 } 210 211 212 public int getEnd() { 213 return end; 214 } 215 216 public void setEnd( int i ) { 217 end=i; 218 } 219 220 222 public void append( char b ) 223 throws IOException 224 { 225 makeSpace( 1 ); 226 227 if( limit >0 && end >= limit ) { 229 flushBuffer(); 230 } 231 buff[end++]=b; 232 } 233 234 public void append( CharChunk src ) 235 throws IOException 236 { 237 append( src.getBuffer(), src.getOffset(), src.getLength()); 238 } 239 240 242 public void append( char src[], int off, int len ) 243 throws IOException 244 { 245 makeSpace( len ); 247 248 if( limit < 0 ) { 250 System.arraycopy( src, off, buff, end, len ); 252 end+=len; 253 return; 254 } 255 256 if ( optimizedWrite && len == limit && end == start && out != null ) { 260 out.realWriteChars( src, off, len ); 261 return; 262 } 263 264 if( len <= limit - end ) { 266 System.arraycopy( src, off, buff, end, len ); 269 270 end+=len; 271 return; 272 } 273 274 277 279 286 if( len + end < 2 * limit ) { 287 291 int avail=limit-end; 292 System.arraycopy(src, off, buff, end, avail); 293 end += avail; 294 295 flushBuffer(); 296 297 System.arraycopy(src, off+avail, buff, end, len - avail); 298 end+= len - avail; 299 300 } else { flushBuffer(); 304 305 out.realWriteChars( src, off, len ); 306 } 307 } 308 309 310 312 public void append( StringBuffer sb ) 313 throws IOException 314 { 315 int len=sb.length(); 316 317 makeSpace( len ); 319 320 if( limit < 0 ) { 322 sb.getChars(0, len, buff, end ); 324 end+=len; 325 return; 326 } 327 328 int off=0; 329 int sbOff = off; 330 int sbEnd = off + len; 331 while (sbOff < sbEnd) { 332 int d = min(limit - end, sbEnd - sbOff); 333 sb.getChars( sbOff, sbOff+d, buff, end); 334 sbOff += d; 335 end += d; 336 if (end >= limit) 337 flushBuffer(); 338 } 339 } 340 341 343 public void append(String s) throws IOException { 344 append(s, 0, s.length()); 345 } 346 347 349 public void append(String s, int off, int len) throws IOException { 350 if (s==null) return; 351 352 makeSpace( len ); 354 355 if( limit < 0 ) { 357 s.getChars(off, off+len, buff, end ); 359 end+=len; 360 return; 361 } 362 363 int sOff = off; 364 int sEnd = off + len; 365 while (sOff < sEnd) { 366 int d = min(limit - end, sEnd - sOff); 367 s.getChars( sOff, sOff+d, buff, end); 368 sOff += d; 369 end += d; 370 if (end >= limit) 371 flushBuffer(); 372 } 373 } 374 375 377 public int substract() 378 throws IOException { 379 380 if ((end - start) == 0) { 381 if (in == null) 382 return -1; 383 int n = in.realReadChars(buff, end, buff.length - end); 384 if (n < 0) 385 return -1; 386 } 387 388 return (buff[start++]); 389 390 } 391 392 public int substract(CharChunk src) 393 throws IOException { 394 395 if ((end - start) == 0) { 396 if (in == null) 397 return -1; 398 int n = in.realReadChars( buff, end, buff.length - end); 399 if (n < 0) 400 return -1; 401 } 402 403 int len = getLength(); 404 src.append(buff, start, len); 405 start = end; 406 return len; 407 408 } 409 410 public int substract( char src[], int off, int len ) 411 throws IOException { 412 413 if ((end - start) == 0) { 414 if (in == null) 415 return -1; 416 int n = in.realReadChars( buff, end, buff.length - end); 417 if (n < 0) 418 return -1; 419 } 420 421 int n = len; 422 if (len > getLength()) { 423 n = getLength(); 424 } 425 System.arraycopy(buff, start, src, off, n); 426 start += n; 427 return n; 428 429 } 430 431 432 public void flushBuffer() 433 throws IOException 434 { 435 if( out==null ) { 437 throw new IOException ( "Buffer overflow, no sink " + limit + " " + 438 buff.length ); 439 } 440 out.realWriteChars( buff, start, end - start ); 441 end=start; 442 } 443 444 447 private void makeSpace(int count) 448 { 449 char[] tmp = null; 450 451 int newSize; 452 int desiredSize=end + count; 453 454 if( limit > 0 && 456 desiredSize > limit) { 457 desiredSize=limit; 458 } 459 460 if( buff==null ) { 461 if( desiredSize < 256 ) desiredSize=256; buff=new char[desiredSize]; 463 } 464 465 if( desiredSize <= buff.length) { 468 return; 469 } 470 if( desiredSize < 2 * buff.length ) { 472 newSize= buff.length * 2; 473 if( limit >0 && 474 newSize > limit ) newSize=limit; 475 tmp=new char[newSize]; 476 } else { 477 newSize= buff.length * 2 + count ; 478 if( limit > 0 && 479 newSize > limit ) newSize=limit; 480 tmp=new char[newSize]; 481 } 482 483 System.arraycopy(buff, start, tmp, start, end-start); 484 buff = tmp; 485 tmp = null; 486 } 487 488 490 public String toString() { 491 if (null == buff) { 492 return null; 493 } else if (end-start == 0) { 494 return ""; 495 } 496 return StringCache.toString(this); 497 } 498 499 public String toStringInternal() { 500 return new String (buff, start, end-start); 501 } 502 503 public int getInt() 504 { 505 return Ascii.parseInt(buff, start, 506 end-start); 507 } 508 509 511 516 public boolean equals(String s) { 517 char[] c = buff; 518 int len = end-start; 519 if (c == null || len != s.length()) { 520 return false; 521 } 522 int off = start; 523 for (int i = 0; i < len; i++) { 524 if (c[off++] != s.charAt(i)) { 525 return false; 526 } 527 } 528 return true; 529 } 530 531 536 public boolean equalsIgnoreCase(String s) { 537 char[] c = buff; 538 int len = end-start; 539 if (c == null || len != s.length()) { 540 return false; 541 } 542 int off = start; 543 for (int i = 0; i < len; i++) { 544 if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) { 545 return false; 546 } 547 } 548 return true; 549 } 550 551 public boolean equals(CharChunk cc) { 552 return equals( cc.getChars(), cc.getOffset(), cc.getLength()); 553 } 554 555 public boolean equals(char b2[], int off2, int len2) { 556 char b1[]=buff; 557 if( b1==null && b2==null ) return true; 558 559 if (b1== null || b2==null || end-start != len2) { 560 return false; 561 } 562 int off1 = start; 563 int len=end-start; 564 while ( len-- > 0) { 565 if (b1[off1++] != b2[off2++]) { 566 return false; 567 } 568 } 569 return true; 570 } 571 572 public boolean equals(byte b2[], int off2, int len2) { 573 char b1[]=buff; 574 if( b2==null && b1==null ) return true; 575 576 if (b1== null || b2==null || end-start != len2) { 577 return false; 578 } 579 int off1 = start; 580 int len=end-start; 581 582 while ( len-- > 0) { 583 if ( b1[off1++] != (char)b2[off2++]) { 584 return false; 585 } 586 } 587 return true; 588 } 589 590 594 public boolean startsWith(String s) { 595 char[] c = buff; 596 int len = s.length(); 597 if (c == null || len > end-start) { 598 return false; 599 } 600 int off = start; 601 for (int i = 0; i < len; i++) { 602 if (c[off++] != s.charAt(i)) { 603 return false; 604 } 605 } 606 return true; 607 } 608 609 613 public boolean startsWithIgnoreCase(String s, int pos) { 614 char[] c = buff; 615 int len = s.length(); 616 if (c == null || len+pos > end-start) { 617 return false; 618 } 619 int off = start+pos; 620 for (int i = 0; i < len; i++) { 621 if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) { 622 return false; 623 } 624 } 625 return true; 626 } 627 628 629 631 public int hash() { 633 int code=0; 634 for (int i = start; i < start + end-start; i++) { 635 code = code * 37 + buff[i]; 636 } 637 return code; 638 } 639 640 public int hashIgnoreCase() { 642 int code=0; 643 for (int i = start; i < end; i++) { 644 code = code * 37 + Ascii.toLower(buff[i]); 645 } 646 return code; 647 } 648 649 public int indexOf(char c) { 650 return indexOf( c, start); 651 } 652 653 657 public int indexOf(char c, int starting) { 658 int ret = indexOf( buff, start+starting, end, c ); 659 return (ret >= start) ? ret - start : -1; 660 } 661 662 public static int indexOf( char chars[], int off, int cend, char qq ) 663 { 664 while( off < cend ) { 665 char b=chars[off]; 666 if( b==qq ) 667 return off; 668 off++; 669 } 670 return -1; 671 } 672 673 674 public int indexOf( String src, int srcOff, int srcLen, int myOff ) { 675 char first=src.charAt( srcOff ); 676 677 int srcEnd = srcOff + srcLen; 679 680 for( int i=myOff+start; i <= (end - srcLen); i++ ) { 681 if( buff[i] != first ) continue; 682 int myPos=i+1; 684 for( int srcPos=srcOff + 1; srcPos< srcEnd; ) { 685 if( buff[myPos++] != src.charAt( srcPos++ )) 686 break; 687 if( srcPos==srcEnd ) return i-start; } 689 } 690 return -1; 691 } 692 693 private int min(int a, int b) { 695 if (a < b) return a; 696 return b; 697 } 698 699 701 public char charAt(int index) { 702 return buff[index + start]; 703 } 704 705 public CharSequence subSequence(int start, int end) { 706 try { 707 CharChunk result = (CharChunk) this.clone(); 708 result.setOffset(this.start + start); 709 result.setEnd(this.start + end); 710 return result; 711 } catch (CloneNotSupportedException e) { 712 return null; 714 } 715 } 716 717 public int length() { 718 return end - start; 719 } 720 721 } 722 | Popular Tags |