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