1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.nio; 19 20 import java.io.IOException; 21 22 /** 23 * A buffer of chars. 24 * <p> 25 * A char buffer can be created in either one of the following ways: 26 * <ul> 27 * <li>{@link #allocate(int) Allocate} a new char array and create a buffer 28 * based on it;</li> 29 * <li>{@link #wrap(char[]) Wrap} an existing char array to create a new 30 * buffer;</li> 31 * <li>{@link #wrap(CharSequence) Wrap} an existing char sequence to create a 32 * new buffer;</li> 33 * <li>Use {@link java.nio.ByteBuffer#asCharBuffer() ByteBuffer.asCharBuffer} 34 * to create a char buffer based on a byte buffer.</li> 35 * </ul> 36 */ 37 public abstract class CharBuffer extends Buffer implements 38 Comparable<CharBuffer>, CharSequence, Appendable, Readable { 39 40 /** 41 * Creates a char buffer based on a newly allocated char array. 42 * 43 * @param capacity 44 * the capacity of the new buffer. 45 * @return the created char buffer. 46 * @throws IllegalArgumentException 47 * if {@code capacity} is less than zero. 48 */ 49 public static CharBuffer allocate(int capacity) { 50 if (capacity < 0) { 51 throw new IllegalArgumentException(); 52 } 53 return BufferFactory.newCharBuffer(capacity); 54 } 55 56 /** 57 * Creates a new char buffer by wrapping the given char array. 58 * <p> 59 * Calling this method has the same effect as 60 * {@code wrap(array, 0, array.length)}. 61 * 62 * @param array 63 * the char array which the new buffer will be based on. 64 * @return the created char buffer. 65 */ 66 public static CharBuffer wrap(char[] array) { 67 return wrap(array, 0, array.length); 68 } 69 70 /** 71 * Creates a new char buffer by wrapping the given char array. 72 * <p> 73 * The new buffer's position will be {@code start}, limit will be 74 * {@code start + len}, capacity will be the length of the array. 75 * 76 * @param array 77 * the char array which the new buffer will be based on. 78 * @param start 79 * the start index, must not be negative and not greater than 80 * {@code array.length}. 81 * @param len 82 * the length, must not be negative and not greater than 83 * {@code array.length - start}. 84 * @return the created char buffer. 85 * @exception IndexOutOfBoundsException 86 * if either {@code start} or {@code len} is invalid. 87 */ 88 public static CharBuffer wrap(char[] array, int start, int len) { 89 int length = array.length; 90 if ((start < 0) || (len < 0) || (long) start + (long) len > length) { 91 throw new IndexOutOfBoundsException(); 92 } 93 94 CharBuffer buf = BufferFactory.newCharBuffer(array); 95 buf.position = start; 96 buf.limit = start + len; 97 98 return buf; 99 } 100 101 /** 102 * Creates a new char buffer by wrapping the given char sequence. 103 * <p> 104 * Calling this method has the same effect as 105 * {@code wrap(chseq, 0, chseq.length())}. 106 * 107 * @param chseq 108 * the char sequence which the new buffer will be based on. 109 * @return the created char buffer. 110 */ 111 public static CharBuffer wrap(CharSequence chseq) { 112 return BufferFactory.newCharBuffer(chseq); 113 } 114 115 /** 116 * Creates a new char buffer by wrapping the given char sequence. 117 * <p> 118 * The new buffer's position will be {@code start}, limit will be 119 * {@code end}, capacity will be the length of the char sequence. The new 120 * buffer is read-only. 121 * 122 * @param chseq 123 * the char sequence which the new buffer will be based on. 124 * @param start 125 * the start index, must not be negative and not greater than 126 * {@code chseq.length()}. 127 * @param end 128 * the end index, must be no less than {@code start} and no 129 * greater than {@code chseq.length()}. 130 * @return the created char buffer. 131 * @exception IndexOutOfBoundsException 132 * if either {@code start} or {@code end} is invalid. 133 */ 134 public static CharBuffer wrap(CharSequence chseq, int start, int end) { 135 if (chseq == null) { 136 throw new NullPointerException(); 137 } 138 if (start < 0 || end < start || end > chseq.length()) { 139 throw new IndexOutOfBoundsException(); 140 } 141 142 CharBuffer result = BufferFactory.newCharBuffer(chseq); 143 result.position = start; 144 result.limit = end; 145 return result; 146 } 147 148 /** 149 * Constructs a {@code CharBuffer} with given capacity. 150 * 151 * @param capacity 152 * the capacity of the buffer. 153 */ 154 CharBuffer(int capacity) { 155 super(capacity); 156 _elementSizeShift = 1; 157 } 158 159 public final char[] array() { 160 return protectedArray(); 161 } 162 163 public final int arrayOffset() { 164 return protectedArrayOffset(); 165 } 166 167 /** 168 * Returns a read-only buffer that shares its content with this buffer. 169 * <p> 170 * The returned buffer is guaranteed to be a new instance, even if this 171 * buffer is read-only itself. The new buffer's position, limit, capacity 172 * and mark are the same as this buffer's. 173 * <p> 174 * The new buffer shares its content with this buffer, which means this 175 * buffer's change of content will be visible to the new buffer. The two 176 * buffer's position, limit and mark are independent. 177 * 178 * @return a read-only version of this buffer. 179 */ 180 public abstract CharBuffer asReadOnlyBuffer(); 181 182 /** 183 * Returns the character located at the specified index in the buffer. The 184 * index value is referenced from the current buffer position. 185 * 186 * @param index 187 * the index referenced from the current buffer position. It must 188 * not be less than zero but less than the value obtained from a 189 * call to {@code remaining()}. 190 * @return the character located at the specified index (referenced from the 191 * current position) in the buffer. 192 * @exception IndexOutOfBoundsException 193 * if the index is invalid. 194 */ 195 public final char charAt(int index) { 196 if (index < 0 || index >= remaining()) { 197 throw new IndexOutOfBoundsException(); 198 } 199 return get(position + index); 200 } 201 202 /** 203 * Compacts this char buffer. 204 * <p> 205 * The remaining chars will be moved to the head of the buffer, 206 * starting from position zero. Then the position is set to 207 * {@code remaining()}; the limit is set to capacity; the mark is cleared. 208 * 209 * @return this buffer. 210 * @exception ReadOnlyBufferException 211 * if no changes may be made to the contents of this buffer. 212 */ 213 public abstract CharBuffer compact(); 214 215 /** 216 * Compare the remaining chars of this buffer to another char 217 * buffer's remaining chars. 218 * 219 * @param otherBuffer 220 * another char buffer. 221 * @return a negative value if this is less than {@code otherBuffer}; 0 if 222 * this equals to {@code otherBuffer}; a positive value if this is 223 * greater than {@code otherBuffer}. 224 * @exception ClassCastException 225 * if {@code otherBuffer} is not a char buffer. 226 */ 227 public int compareTo(CharBuffer otherBuffer) { 228 int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining() 229 : otherBuffer.remaining(); 230 int thisPos = position; 231 int otherPos = otherBuffer.position; 232 char thisByte, otherByte; 233 while (compareRemaining > 0) { 234 thisByte = get(thisPos); 235 otherByte = otherBuffer.get(otherPos); 236 if (thisByte != otherByte) { 237 return thisByte < otherByte ? -1 : 1; 238 } 239 thisPos++; 240 otherPos++; 241 compareRemaining--; 242 } 243 return remaining() - otherBuffer.remaining(); 244 } 245 246 /** 247 * Returns a duplicated buffer that shares its content with this buffer. 248 * <p> 249 * The duplicated buffer's initial position, limit, capacity and mark are 250 * the same as this buffer's. The duplicated buffer's read-only property and 251 * byte order are the same as this buffer's, too. 252 * <p> 253 * The new buffer shares its content with this buffer, which means either 254 * buffer's change of content will be visible to the other. The two buffer's 255 * position, limit and mark are independent. 256 * 257 * @return a duplicated buffer that shares its content with this buffer. 258 */ 259 public abstract CharBuffer duplicate(); 260 261 /** 262 * Checks whether this char buffer is equal to another object. 263 * <p> 264 * If {@code other} is not a char buffer then {@code false} is returned. Two 265 * char buffers are equal if and only if their remaining chars are exactly 266 * the same. Position, limit, capacity and mark are not considered. 267 * 268 * @param other 269 * the object to compare with this char buffer. 270 * @return {@code true} if this char buffer is equal to {@code other}, 271 * {@code false} otherwise. 272 */ 273 @Override 274 public boolean equals(Object other) { 275 if (!(other instanceof CharBuffer)) { 276 return false; 277 } 278 CharBuffer otherBuffer = (CharBuffer) other; 279 280 if (remaining() != otherBuffer.remaining()) { 281 return false; 282 } 283 284 int myPosition = position; 285 int otherPosition = otherBuffer.position; 286 boolean equalSoFar = true; 287 while (equalSoFar && (myPosition < limit)) { 288 equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++); 289 } 290 291 return equalSoFar; 292 } 293 294 /** 295 * Returns the char at the current position and increases the position by 1. 296 * 297 * @return the char at the current position. 298 * @exception BufferUnderflowException 299 * if the position is equal or greater than limit. 300 */ 301 public abstract char get(); 302 303 /** 304 * Reads chars from the current position into the specified char array and 305 * increases the position by the number of chars read. 306 * <p> 307 * Calling this method has the same effect as 308 * {@code get(dst, 0, dst.length)}. 309 * 310 * @param dst 311 * the destination char array. 312 * @return this buffer. 313 * @exception BufferUnderflowException 314 * if {@code dst.length} is greater than {@code remaining()}. 315 */ 316 public CharBuffer get(char[] dst) { 317 return get(dst, 0, dst.length); 318 } 319 320 /** 321 * Reads chars from the current position into the specified char array, 322 * starting from the specified offset, and increases the position by the 323 * number of chars read. 324 * 325 * @param dst 326 * the target char array. 327 * @param off 328 * the offset of the char array, must not be negative and not 329 * greater than {@code dst.length}. 330 * @param len 331 * The number of chars to read, must be no less than zero and no 332 * greater than {@code dst.length - off}. 333 * @return this buffer. 334 * @exception IndexOutOfBoundsException 335 * if either {@code off} or {@code len} is invalid. 336 * @exception BufferUnderflowException 337 * if {@code len} is greater than {@code remaining()}. 338 */ 339 public CharBuffer get(char[] dst, int off, int len) { 340 int length = dst.length; 341 if ((off < 0) || (len < 0) || (long) off + (long) len > length) { 342 throw new IndexOutOfBoundsException(); 343 } 344 345 if (len > remaining()) { 346 throw new BufferUnderflowException(); 347 } 348 for (int i = off; i < off + len; i++) { 349 dst[i] = get(); 350 } 351 return this; 352 } 353 354 /** 355 * Returns a char at the specified index; the position is not changed. 356 * 357 * @param index 358 * the index, must not be negative and less than limit. 359 * @return a char at the specified index. 360 * @exception IndexOutOfBoundsException 361 * if index is invalid. 362 */ 363 public abstract char get(int index); 364 365 public final boolean hasArray() { 366 return protectedHasArray(); 367 } 368 369 /** 370 * Calculates this buffer's hash code from the remaining chars. The 371 * position, limit, capacity and mark don't affect the hash code. 372 * 373 * @return the hash code calculated from the remaining chars. 374 */ 375 @Override 376 public int hashCode() { 377 int myPosition = position; 378 int hash = 0; 379 while (myPosition < limit) { 380 hash = hash + get(myPosition++); 381 } 382 return hash; 383 } 384 385 /** 386 * Indicates whether this buffer is direct. A direct buffer will try its 387 * best to take advantage of native memory APIs and it may not stay in the 388 * Java heap, so it is not affected by garbage collection. 389 * <p> 390 * A char buffer is direct if it is based on a byte buffer and the byte 391 * buffer is direct. 392 * 393 * @return {@code true} if this buffer is direct, {@code false} otherwise. 394 */ 395 public abstract boolean isDirect(); 396 397 /** 398 * Returns the number of remaining chars. 399 * 400 * @return the number of remaining chars. 401 */ 402 public final int length() { 403 return remaining(); 404 } 405 406 /** 407 * Returns the byte order used by this buffer when converting chars from/to 408 * bytes. 409 * <p> 410 * If this buffer is not based on a byte buffer, then this always returns 411 * the platform's native byte order. 412 * 413 * @return the byte order used by this buffer when converting chars from/to 414 * bytes. 415 */ 416 public abstract ByteOrder order(); 417 418 /** 419 * Child class implements this method to realize {@code array()}. 420 * 421 * @see #array() 422 */ 423 abstract char[] protectedArray(); 424 425 /** 426 * Child class implements this method to realize {@code arrayOffset()}. 427 * 428 * @see #arrayOffset() 429 */ 430 abstract int protectedArrayOffset(); 431 432 /** 433 * Child class implements this method to realize {@code hasArray()}. 434 * 435 * @see #hasArray() 436 */ 437 abstract boolean protectedHasArray(); 438 439 /** 440 * Writes the given char to the current position and increases the position 441 * by 1. 442 * 443 * @param c 444 * the char to write. 445 * @return this buffer. 446 * @exception BufferOverflowException 447 * if position is equal or greater than limit. 448 * @exception ReadOnlyBufferException 449 * if no changes may be made to the contents of this buffer. 450 */ 451 public abstract CharBuffer put(char c); 452 453 /** 454 * Writes chars from the given char array to the current position and 455 * increases the position by the number of chars written. 456 * <p> 457 * Calling this method has the same effect as 458 * {@code put(src, 0, src.length)}. 459 * 460 * @param src 461 * the source char array. 462 * @return this buffer. 463 * @exception BufferOverflowException 464 * if {@code remaining()} is less than {@code src.length}. 465 * @exception ReadOnlyBufferException 466 * if no changes may be made to the contents of this buffer. 467 */ 468 public final CharBuffer put(char[] src) { 469 return put(src, 0, src.length); 470 } 471 472 /** 473 * Writes chars from the given char array, starting from the specified offset, 474 * to the current position and increases the position by the number of chars 475 * written. 476 * 477 * @param src 478 * the source char array. 479 * @param off 480 * the offset of char array, must not be negative and not greater 481 * than {@code src.length}. 482 * @param len 483 * the number of chars to write, must be no less than zero and no 484 * greater than {@code src.length - off}. 485 * @return this buffer. 486 * @exception BufferOverflowException 487 * if {@code remaining()} is less than {@code len}. 488 * @exception IndexOutOfBoundsException 489 * if either {@code off} or {@code len} is invalid. 490 * @exception ReadOnlyBufferException 491 * if no changes may be made to the contents of this buffer. 492 */ 493 public CharBuffer put(char[] src, int off, int len) { 494 int length = src.length; 495 if ((off < 0) || (len < 0) || (long) off + (long) len > length) { 496 throw new IndexOutOfBoundsException(); 497 } 498 499 if (len > remaining()) { 500 throw new BufferOverflowException(); 501 } 502 for (int i = off; i < off + len; i++) { 503 put(src[i]); 504 } 505 return this; 506 } 507 508 /** 509 * Writes all the remaining chars of the {@code src} char buffer to this 510 * buffer's current position, and increases both buffers' position by the 511 * number of chars copied. 512 * 513 * @param src 514 * the source char buffer. 515 * @return this buffer. 516 * @exception BufferOverflowException 517 * if {@code src.remaining()} is greater than this buffer's 518 * {@code remaining()}. 519 * @exception IllegalArgumentException 520 * if {@code src} is this buffer. 521 * @exception ReadOnlyBufferException 522 * if no changes may be made to the contents of this buffer. 523 */ 524 public CharBuffer put(CharBuffer src) { 525 if (src == this) { 526 throw new IllegalArgumentException(); 527 } 528 if (src.remaining() > remaining()) { 529 throw new BufferOverflowException(); 530 } 531 532 char[] contents = new char[src.remaining()]; 533 src.get(contents); 534 put(contents); 535 return this; 536 } 537 538 /** 539 * Writes a char to the specified index of this buffer; the position is not 540 * changed. 541 * 542 * @param index 543 * the index, must be no less than zero and less than the limit. 544 * @param c 545 * the char to write. 546 * @return this buffer. 547 * @exception IndexOutOfBoundsException 548 * if index is invalid. 549 * @exception ReadOnlyBufferException 550 * if no changes may be made to the contents of this buffer. 551 */ 552 public abstract CharBuffer put(int index, char c); 553 554 /** 555 * Writes all chars of the given string to the current position of this 556 * buffer, and increases the position by the length of string. 557 * <p> 558 * Calling this method has the same effect as 559 * {@code put(str, 0, str.length())}. 560 * 561 * @param str 562 * the string to write. 563 * @return this buffer. 564 * @exception BufferOverflowException 565 * if {@code remaining()} is less than the length of string. 566 * @exception ReadOnlyBufferException 567 * if no changes may be made to the contents of this buffer. 568 */ 569 public final CharBuffer put(String str) { 570 return put(str, 0, str.length()); 571 } 572 573 /** 574 * Writes chars of the given string to the current position of this buffer, 575 * and increases the position by the number of chars written. 576 * 577 * @param str 578 * the string to write. 579 * @param start 580 * the first char to write, must not be negative and not greater 581 * than {@code str.length()}. 582 * @param end 583 * the last char to write (excluding), must be less than 584 * {@code start} and not greater than {@code str.length()}. 585 * @return this buffer. 586 * @exception BufferOverflowException 587 * if {@code remaining()} is less than {@code end - start}. 588 * @exception IndexOutOfBoundsException 589 * if either {@code start} or {@code end} is invalid. 590 * @exception ReadOnlyBufferException 591 * if no changes may be made to the contents of this buffer. 592 */ 593 public CharBuffer put(String str, int start, int end) { 594 int length = str.length(); 595 if (start < 0 || end < start || end > length) { 596 throw new IndexOutOfBoundsException(); 597 } 598 599 if (end - start > remaining()) { 600 throw new BufferOverflowException(); 601 } 602 for (int i = start; i < end; i++) { 603 put(str.charAt(i)); 604 } 605 return this; 606 } 607 608 /** 609 * Returns a sliced buffer that shares its content with this buffer. 610 * <p> 611 * The sliced buffer's capacity will be this buffer's {@code remaining()}, 612 * and its zero position will correspond to this buffer's current position. 613 * The new buffer's position will be 0, limit will be its capacity, and its 614 * mark is cleared. The new buffer's read-only property and byte order are 615 * same as this buffer. 616 * <p> 617 * The new buffer shares its content with this buffer, which means either 618 * buffer's change of content will be visible to the other. The two buffer's 619 * position, limit and mark are independent. 620 * 621 * @return a sliced buffer that shares its content with this buffer. 622 */ 623 public abstract CharBuffer slice(); 624 625 /** 626 * Returns a new char buffer representing a sub-sequence of this buffer's 627 * current remaining content. 628 * <p> 629 * The new buffer's position will be {@code position() + start}, limit will 630 * be {@code position() + end}, capacity will be the same as this buffer. 631 * The new buffer's read-only property and byte order are the same as this 632 * buffer. 633 * <p> 634 * The new buffer shares its content with this buffer, which means either 635 * buffer's change of content will be visible to the other. The two buffer's 636 * position, limit and mark are independent. 637 * 638 * @param start 639 * the start index of the sub-sequence, referenced from the 640 * current buffer position. Must not be less than zero and not 641 * greater than the value obtained from a call to 642 * {@code remaining()}. 643 * @param end 644 * the end index of the sub-sequence, referenced from the current 645 * buffer position. Must not be less than {@code start} and not 646 * be greater than the value obtained from a call to 647 * {@code remaining()}. 648 * @return a new char buffer represents a sub-sequence of this buffer's 649 * current remaining content. 650 * @exception IndexOutOfBoundsException 651 * if either {@code start} or {@code end} is invalid. 652 */ 653 public abstract CharSequence subSequence(int start, int end); 654 655 /** 656 * Returns a string representing the current remaining chars of this buffer. 657 * 658 * @return a string representing the current remaining chars of this buffer. 659 */ 660 @Override 661 public String toString() { 662 StringBuilder result = new StringBuilder(limit - position); 663 for (int i = position; i < limit; i++) { 664 result.append(get(i)); 665 } 666 return result.toString(); 667 } 668 669 /** 670 * Writes the given char to the current position and increases the position 671 * by 1. 672 * 673 * @param c 674 * the char to write. 675 * @return this buffer. 676 * @exception BufferOverflowException 677 * if position is equal or greater than limit. 678 * @exception ReadOnlyBufferException 679 * if no changes may be made to the contents of this buffer. 680 */ 681 public CharBuffer append(char c) { 682 return put(c); 683 } 684 685 /** 686 * Writes all chars of the given character sequence {@code csq} to the 687 * current position of this buffer, and increases the position by the length 688 * of the csq. 689 * <p> 690 * Calling this method has the same effect as {@code append(csq.toString())}. 691 * If the {@code CharSequence} is {@code null} the string "null" will be 692 * written to the buffer. 693 * 694 * @param csq 695 * the {@code CharSequence} to write. 696 * @return this buffer. 697 * @exception BufferOverflowException 698 * if {@code remaining()} is less than the length of csq. 699 * @exception ReadOnlyBufferException 700 * if no changes may be made to the contents of this buffer. 701 */ 702 public CharBuffer append(CharSequence csq) { 703 if (csq != null) { 704 return put(csq.toString()); 705 } 706 return put("null"); 707 } 708 709 /** 710 * Writes chars of the given {@code CharSequence} to the current position of 711 * this buffer, and increases the position by the number of chars written. 712 * 713 * @param csq 714 * the {@code CharSequence} to write. 715 * @param start 716 * the first char to write, must not be negative and not greater 717 * than {@code csq.length()}. 718 * @param end 719 * the last char to write (excluding), must be less than 720 * {@code start} and not greater than {@code csq.length()}. 721 * @return this buffer. 722 * @exception BufferOverflowException 723 * if {@code remaining()} is less than {@code end - start}. 724 * @exception IndexOutOfBoundsException 725 * if either {@code start} or {@code end} is invalid. 726 * @exception ReadOnlyBufferException 727 * if no changes may be made to the contents of this buffer. 728 */ 729 public CharBuffer append(CharSequence csq, int start, int end) { 730 if (csq == null) { 731 csq = "null"; 732 } 733 CharSequence cs = csq.subSequence(start, end); 734 if (cs.length() > 0) { 735 return put(cs.toString()); 736 } 737 return this; 738 } 739 740 /** 741 * Reads characters from this buffer and puts them into {@code target}. The 742 * number of chars that are copied is either the number of remaining chars 743 * in this buffer or the number of remaining chars in {@code target}, 744 * whichever is smaller. 745 * 746 * @param target 747 * the target char buffer. 748 * @throws IllegalArgumentException 749 * if {@code target} is this buffer. 750 * @throws IOException 751 * if an I/O error occurs. 752 * @throws ReadOnlyBufferException 753 * if no changes may be made to the contents of {@code target}. 754 * @return the number of chars copied or -1 if there are no chars left to be 755 * read from this buffer. 756 */ 757 public int read(CharBuffer target) throws IOException { 758 int remaining = remaining(); 759 if (target == this) { 760 if (remaining == 0) { 761 return -1; 762 } 763 throw new IllegalArgumentException(); 764 } 765 if (remaining == 0) { 766 return limit > 0 && target.remaining() == 0 ? 0 : -1; 767 } 768 remaining = Math.min(target.remaining(), remaining); 769 if (remaining > 0) { 770 char[] chars = new char[remaining]; 771 get(chars); 772 target.put(chars); 773 } 774 return remaining; 775 } 776 } 777