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      */
allocate(int capacity)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      */
wrap(char[] array)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      */
wrap(char[] array, int start, int charCount)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      */
wrap(CharSequence chseq)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      */
wrap(CharSequence cs, int start, int end)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 
CharBuffer(int capacity, long effectiveDirectAddress)140     CharBuffer(int capacity, long effectiveDirectAddress) {
141         super(1, capacity, effectiveDirectAddress);
142     }
143 
array()144     public final char[] array() {
145         return protectedArray();
146     }
147 
arrayOffset()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      */
asReadOnlyBuffer()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      */
charAt(int index)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      */
compact()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      */
compareTo(CharBuffer otherBuffer)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      */
duplicate()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
equals(Object other)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      */
get()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      */
get(char[] dst)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      */
get(char[] dst, int dstOffset, int charCount)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      */
get(int index)333     public abstract char get(int index);
334 
hasArray()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
hashCode()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      */
isDirect()365     public abstract boolean isDirect();
366 
367     /**
368      * Returns the number of remaining chars.
369      *
370      * @return the number of remaining chars.
371      */
length()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      */
order()386     public abstract ByteOrder order();
387 
388     /**
389      * Child class implements this method to realize {@code array()}.
390      *
391      * @see #array()
392      */
protectedArray()393     abstract char[] protectedArray();
394 
395     /**
396      * Child class implements this method to realize {@code arrayOffset()}.
397      *
398      * @see #arrayOffset()
399      */
protectedArrayOffset()400     abstract int protectedArrayOffset();
401 
402     /**
403      * Child class implements this method to realize {@code hasArray()}.
404      *
405      * @see #hasArray()
406      */
protectedHasArray()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      */
put(char c)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      */
put(char[] src)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      */
put(char[] src, int srcOffset, int charCount)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      */
put(CharBuffer src)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      */
put(int index, char c)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      */
put(String str)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      */
put(String str, int start, int end)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      */
slice()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      */
subSequence(int start, int end)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
toString()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      */
append(char c)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      */
append(CharSequence csq)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      */
append(CharSequence csq, int start, int end)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      */
read(CharBuffer target)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