Home | History | Annotate | Download | only in nio
      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