View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.buffer;
17  
18  import io.netty.buffer.CompositeByteBuf.ByteWrapper;
19  import io.netty.util.internal.ObjectUtil;
20  import io.netty.util.CharsetUtil;
21  import io.netty.util.internal.PlatformDependent;
22  
23  import java.nio.ByteBuffer;
24  import java.nio.ByteOrder;
25  import java.nio.CharBuffer;
26  import java.nio.charset.Charset;
27  import java.util.Arrays;
28  
29  
30  /**
31   * Creates a new {@link ByteBuf} by allocating new space or by wrapping
32   * or copying existing byte arrays, byte buffers and a string.
33   *
34   * <h3>Use static import</h3>
35   * This classes is intended to be used with Java 5 static import statement:
36   *
37   * <pre>
38   * import static io.netty.buffer.{@link Unpooled}.*;
39   *
40   * {@link ByteBuf} heapBuffer    = buffer(128);
41   * {@link ByteBuf} directBuffer  = directBuffer(256);
42   * {@link ByteBuf} wrappedBuffer = wrappedBuffer(new byte[128], new byte[256]);
43   * {@link ByteBuf} copiedBuffer  = copiedBuffer({@link ByteBuffer}.allocate(128));
44   * </pre>
45   *
46   * <h3>Allocating a new buffer</h3>
47   *
48   * Three buffer types are provided out of the box.
49   *
50   * <ul>
51   * <li>{@link #buffer(int)} allocates a new fixed-capacity heap buffer.</li>
52   * <li>{@link #directBuffer(int)} allocates a new fixed-capacity direct buffer.</li>
53   * </ul>
54   *
55   * <h3>Creating a wrapped buffer</h3>
56   *
57   * Wrapped buffer is a buffer which is a view of one or more existing
58   * byte arrays and byte buffers.  Any changes in the content of the original
59   * array or buffer will be visible in the wrapped buffer.  Various wrapper
60   * methods are provided and their name is all {@code wrappedBuffer()}.
61   * You might want to take a look at the methods that accept varargs closely if
62   * you want to create a buffer which is composed of more than one array to
63   * reduce the number of memory copy.
64   *
65   * <h3>Creating a copied buffer</h3>
66   *
67   * Copied buffer is a deep copy of one or more existing byte arrays, byte
68   * buffers or a string.  Unlike a wrapped buffer, there's no shared data
69   * between the original data and the copied buffer.  Various copy methods are
70   * provided and their name is all {@code copiedBuffer()}.  It is also convenient
71   * to use this operation to merge multiple buffers into one buffer.
72   */
73  public final class Unpooled {
74  
75      private static final ByteBufAllocator ALLOC = UnpooledByteBufAllocator.DEFAULT;
76  
77      /**
78       * Big endian byte order.
79       */
80      public static final ByteOrder BIG_ENDIAN = ByteOrder.BIG_ENDIAN;
81  
82      /**
83       * Little endian byte order.
84       */
85      public static final ByteOrder LITTLE_ENDIAN = ByteOrder.LITTLE_ENDIAN;
86  
87      /**
88       * A buffer whose capacity is {@code 0}.
89       */
90      @SuppressWarnings("checkstyle:StaticFinalBuffer")  // EmptyByteBuf is not writeable or readable.
91      public static final ByteBuf EMPTY_BUFFER = ALLOC.buffer(0, 0);
92  
93      static {
94          assert EMPTY_BUFFER instanceof EmptyByteBuf: "EMPTY_BUFFER must be an EmptyByteBuf.";
95      }
96  
97      /**
98       * Creates a new big-endian Java heap buffer with reasonably small initial capacity, which
99       * expands its capacity boundlessly on demand.
100      */
101     public static ByteBuf buffer() {
102         return ALLOC.heapBuffer();
103     }
104 
105     /**
106      * Creates a new big-endian direct buffer with reasonably small initial capacity, which
107      * expands its capacity boundlessly on demand.
108      */
109     public static ByteBuf directBuffer() {
110         return ALLOC.directBuffer();
111     }
112 
113     /**
114      * Creates a new big-endian Java heap buffer with the specified {@code capacity}, which
115      * expands its capacity boundlessly on demand.  The new buffer's {@code readerIndex} and
116      * {@code writerIndex} are {@code 0}.
117      */
118     public static ByteBuf buffer(int initialCapacity) {
119         return ALLOC.heapBuffer(initialCapacity);
120     }
121 
122     /**
123      * Creates a new big-endian direct buffer with the specified {@code capacity}, which
124      * expands its capacity boundlessly on demand.  The new buffer's {@code readerIndex} and
125      * {@code writerIndex} are {@code 0}.
126      */
127     public static ByteBuf directBuffer(int initialCapacity) {
128         return ALLOC.directBuffer(initialCapacity);
129     }
130 
131     /**
132      * Creates a new big-endian Java heap buffer with the specified
133      * {@code initialCapacity}, that may grow up to {@code maxCapacity}
134      * The new buffer's {@code readerIndex} and {@code writerIndex} are
135      * {@code 0}.
136      */
137     public static ByteBuf buffer(int initialCapacity, int maxCapacity) {
138         return ALLOC.heapBuffer(initialCapacity, maxCapacity);
139     }
140 
141     /**
142      * Creates a new big-endian direct buffer with the specified
143      * {@code initialCapacity}, that may grow up to {@code maxCapacity}.
144      * The new buffer's {@code readerIndex} and {@code writerIndex} are
145      * {@code 0}.
146      */
147     public static ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
148         return ALLOC.directBuffer(initialCapacity, maxCapacity);
149     }
150 
151     /**
152      * Creates a new big-endian buffer which wraps the specified {@code array}.
153      * A modification on the specified array's content will be visible to the
154      * returned buffer.
155      */
156     public static ByteBuf wrappedBuffer(byte[] array) {
157         if (array.length == 0) {
158             return EMPTY_BUFFER;
159         }
160         return new UnpooledHeapByteBuf(ALLOC, array, array.length);
161     }
162 
163     /**
164      * Creates a new big-endian buffer which wraps the sub-region of the
165      * specified {@code array}.  A modification on the specified array's
166      * content will be visible to the returned buffer.
167      */
168     public static ByteBuf wrappedBuffer(byte[] array, int offset, int length) {
169         if (length == 0) {
170             return EMPTY_BUFFER;
171         }
172 
173         if (offset == 0 && length == array.length) {
174             return wrappedBuffer(array);
175         }
176 
177         return wrappedBuffer(array).slice(offset, length);
178     }
179 
180     /**
181      * Creates a new buffer which wraps the specified NIO buffer's current
182      * slice.  A modification on the specified buffer's content will be
183      * visible to the returned buffer.
184      */
185     public static ByteBuf wrappedBuffer(ByteBuffer buffer) {
186         if (!buffer.hasRemaining()) {
187             return EMPTY_BUFFER;
188         }
189         if (!buffer.isDirect() && buffer.hasArray()) {
190             return wrappedBuffer(
191                     buffer.array(),
192                     buffer.arrayOffset() + buffer.position(),
193                     buffer.remaining()).order(buffer.order());
194         } else if (PlatformDependent.hasUnsafe()) {
195             if (buffer.isReadOnly()) {
196                 if (buffer.isDirect()) {
197                     return new ReadOnlyUnsafeDirectByteBuf(ALLOC, buffer);
198                 } else {
199                     return new ReadOnlyByteBufferBuf(ALLOC, buffer);
200                 }
201             } else {
202                 return new UnpooledUnsafeDirectByteBuf(ALLOC, buffer, buffer.remaining());
203             }
204         } else {
205             if (buffer.isReadOnly()) {
206                 return new ReadOnlyByteBufferBuf(ALLOC, buffer);
207             }  else {
208                 return new UnpooledDirectByteBuf(ALLOC, buffer, buffer.remaining());
209             }
210         }
211     }
212 
213     /**
214      * Creates a new buffer which wraps the specified memory address. If {@code doFree} is true the
215      * memoryAddress will automatically be freed once the reference count of the {@link ByteBuf} reaches {@code 0}.
216      */
217     public static ByteBuf wrappedBuffer(long memoryAddress, int size, boolean doFree) {
218         return new WrappedUnpooledUnsafeDirectByteBuf(ALLOC, memoryAddress, size, doFree);
219     }
220 
221     /**
222      * Creates a new buffer which wraps the specified buffer's readable bytes.
223      * A modification on the specified buffer's content will be visible to the
224      * returned buffer.
225      * @param buffer The buffer to wrap. Reference count ownership of this variable is transferred to this method.
226      * @return The readable portion of the {@code buffer}, or an empty buffer if there is no readable portion.
227      * The caller is responsible for releasing this buffer.
228      */
229     public static ByteBuf wrappedBuffer(ByteBuf buffer) {
230         if (buffer.isReadable()) {
231             return buffer.slice();
232         } else {
233             buffer.release();
234             return EMPTY_BUFFER;
235         }
236     }
237 
238     /**
239      * Creates a new big-endian composite buffer which wraps the specified
240      * arrays without copying them.  A modification on the specified arrays'
241      * content will be visible to the returned buffer.
242      */
243     public static ByteBuf wrappedBuffer(byte[]... arrays) {
244         return wrappedBuffer(arrays.length, arrays);
245     }
246 
247     /**
248      * Creates a new big-endian composite buffer which wraps the readable bytes of the
249      * specified buffers without copying them.  A modification on the content
250      * of the specified buffers will be visible to the returned buffer.
251      * @param buffers The buffers to wrap. Reference count ownership of all variables is transferred to this method.
252      * @return The readable portion of the {@code buffers}. The caller is responsible for releasing this buffer.
253      */
254     public static ByteBuf wrappedBuffer(ByteBuf... buffers) {
255         return wrappedBuffer(buffers.length, buffers);
256     }
257 
258     /**
259      * Creates a new big-endian composite buffer which wraps the slices of the specified
260      * NIO buffers without copying them.  A modification on the content of the
261      * specified buffers will be visible to the returned buffer.
262      */
263     public static ByteBuf wrappedBuffer(ByteBuffer... buffers) {
264         return wrappedBuffer(buffers.length, buffers);
265     }
266 
267     static <T> ByteBuf wrappedBuffer(int maxNumComponents, ByteWrapper<T> wrapper, T[] array) {
268         switch (array.length) {
269         case 0:
270             break;
271         case 1:
272             if (!wrapper.isEmpty(array[0])) {
273                 return wrapper.wrap(array[0]);
274             }
275             break;
276         default:
277             for (int i = 0, len = array.length; i < len; i++) {
278                 T bytes = array[i];
279                 if (bytes == null) {
280                     return EMPTY_BUFFER;
281                 }
282                 if (!wrapper.isEmpty(bytes)) {
283                     return new CompositeByteBuf(ALLOC, false, maxNumComponents, wrapper, array, i);
284                 }
285             }
286         }
287 
288         return EMPTY_BUFFER;
289     }
290 
291     /**
292      * Creates a new big-endian composite buffer which wraps the specified
293      * arrays without copying them.  A modification on the specified arrays'
294      * content will be visible to the returned buffer.
295      */
296     public static ByteBuf wrappedBuffer(int maxNumComponents, byte[]... arrays) {
297         return wrappedBuffer(maxNumComponents, CompositeByteBuf.BYTE_ARRAY_WRAPPER, arrays);
298     }
299 
300     /**
301      * Creates a new big-endian composite buffer which wraps the readable bytes of the
302      * specified buffers without copying them.  A modification on the content
303      * of the specified buffers will be visible to the returned buffer.
304      * @param maxNumComponents Advisement as to how many independent buffers are allowed to exist before
305      * consolidation occurs.
306      * @param buffers The buffers to wrap. Reference count ownership of all variables is transferred to this method.
307      * @return The readable portion of the {@code buffers}. The caller is responsible for releasing this buffer.
308      */
309     public static ByteBuf wrappedBuffer(int maxNumComponents, ByteBuf... buffers) {
310         switch (buffers.length) {
311         case 0:
312             break;
313         case 1:
314             ByteBuf buffer = buffers[0];
315             if (buffer.isReadable()) {
316                 return wrappedBuffer(buffer.order(BIG_ENDIAN));
317             } else {
318                 buffer.release();
319             }
320             break;
321         default:
322             for (int i = 0; i < buffers.length; i++) {
323                 ByteBuf buf = buffers[i];
324                 if (buf.isReadable()) {
325                     return new CompositeByteBuf(ALLOC, false, maxNumComponents, buffers, i);
326                 }
327                 buf.release();
328             }
329             break;
330         }
331         return EMPTY_BUFFER;
332     }
333 
334     /**
335      * Creates a new big-endian composite buffer which wraps the slices of the specified
336      * NIO buffers without copying them.  A modification on the content of the
337      * specified buffers will be visible to the returned buffer.
338      */
339     public static ByteBuf wrappedBuffer(int maxNumComponents, ByteBuffer... buffers) {
340         return wrappedBuffer(maxNumComponents, CompositeByteBuf.BYTE_BUFFER_WRAPPER, buffers);
341     }
342 
343     /**
344      * Returns a new big-endian composite buffer with no components.
345      */
346     public static CompositeByteBuf compositeBuffer() {
347         return compositeBuffer(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS);
348     }
349 
350     /**
351      * Returns a new big-endian composite buffer with no components.
352      */
353     public static CompositeByteBuf compositeBuffer(int maxNumComponents) {
354         return new CompositeByteBuf(ALLOC, false, maxNumComponents);
355     }
356 
357     /**
358      * Creates a new big-endian buffer whose content is a copy of the
359      * specified {@code array}.  The new buffer's {@code readerIndex} and
360      * {@code writerIndex} are {@code 0} and {@code array.length} respectively.
361      */
362     public static ByteBuf copiedBuffer(byte[] array) {
363         if (array.length == 0) {
364             return EMPTY_BUFFER;
365         }
366         return wrappedBuffer(array.clone());
367     }
368 
369     /**
370      * Creates a new big-endian buffer whose content is a copy of the
371      * specified {@code array}'s sub-region.  The new buffer's
372      * {@code readerIndex} and {@code writerIndex} are {@code 0} and
373      * the specified {@code length} respectively.
374      */
375     public static ByteBuf copiedBuffer(byte[] array, int offset, int length) {
376         if (length == 0) {
377             return EMPTY_BUFFER;
378         }
379         byte[] copy = PlatformDependent.allocateUninitializedArray(length);
380         System.arraycopy(array, offset, copy, 0, length);
381         return wrappedBuffer(copy);
382     }
383 
384     /**
385      * Creates a new buffer whose content is a copy of the specified
386      * {@code buffer}'s current slice.  The new buffer's {@code readerIndex}
387      * and {@code writerIndex} are {@code 0} and {@code buffer.remaining}
388      * respectively.
389      */
390     public static ByteBuf copiedBuffer(ByteBuffer buffer) {
391         int length = buffer.remaining();
392         if (length == 0) {
393             return EMPTY_BUFFER;
394         }
395         byte[] copy = PlatformDependent.allocateUninitializedArray(length);
396         // Duplicate the buffer so we not adjust the position during our get operation.
397         // See https://github.com/netty/netty/issues/3896
398         ByteBuffer duplicate = buffer.duplicate();
399         duplicate.get(copy);
400         return wrappedBuffer(copy).order(duplicate.order());
401     }
402 
403     /**
404      * Creates a new buffer whose content is a copy of the specified
405      * {@code buffer}'s readable bytes.  The new buffer's {@code readerIndex}
406      * and {@code writerIndex} are {@code 0} and {@code buffer.readableBytes}
407      * respectively.
408      */
409     public static ByteBuf copiedBuffer(ByteBuf buffer) {
410         int readable = buffer.readableBytes();
411         if (readable > 0) {
412             ByteBuf copy = buffer(readable);
413             copy.writeBytes(buffer, buffer.readerIndex(), readable);
414             return copy;
415         } else {
416             return EMPTY_BUFFER;
417         }
418     }
419 
420     /**
421      * Creates a new big-endian buffer whose content is a merged copy of
422      * the specified {@code arrays}.  The new buffer's {@code readerIndex}
423      * and {@code writerIndex} are {@code 0} and the sum of all arrays'
424      * {@code length} respectively.
425      */
426     public static ByteBuf copiedBuffer(byte[]... arrays) {
427         switch (arrays.length) {
428         case 0:
429             return EMPTY_BUFFER;
430         case 1:
431             if (arrays[0].length == 0) {
432                 return EMPTY_BUFFER;
433             } else {
434                 return copiedBuffer(arrays[0]);
435             }
436         }
437 
438         // Merge the specified arrays into one array.
439         int length = 0;
440         for (byte[] a: arrays) {
441             if (Integer.MAX_VALUE - length < a.length) {
442                 throw new IllegalArgumentException(
443                         "The total length of the specified arrays is too big.");
444             }
445             length += a.length;
446         }
447 
448         if (length == 0) {
449             return EMPTY_BUFFER;
450         }
451 
452         byte[] mergedArray = PlatformDependent.allocateUninitializedArray(length);
453         for (int i = 0, j = 0; i < arrays.length; i ++) {
454             byte[] a = arrays[i];
455             System.arraycopy(a, 0, mergedArray, j, a.length);
456             j += a.length;
457         }
458 
459         return wrappedBuffer(mergedArray);
460     }
461 
462     /**
463      * Creates a new buffer whose content is a merged copy of the specified
464      * {@code buffers}' readable bytes.  The new buffer's {@code readerIndex}
465      * and {@code writerIndex} are {@code 0} and the sum of all buffers'
466      * {@code readableBytes} respectively.
467      *
468      * @throws IllegalArgumentException
469      *         if the specified buffers' endianness are different from each
470      *         other
471      */
472     public static ByteBuf copiedBuffer(ByteBuf... buffers) {
473         switch (buffers.length) {
474         case 0:
475             return EMPTY_BUFFER;
476         case 1:
477             return copiedBuffer(buffers[0]);
478         }
479 
480         // Merge the specified buffers into one buffer.
481         ByteOrder order = null;
482         int length = 0;
483         for (ByteBuf b: buffers) {
484             int bLen = b.readableBytes();
485             if (bLen <= 0) {
486                 continue;
487             }
488             if (Integer.MAX_VALUE - length < bLen) {
489                 throw new IllegalArgumentException(
490                         "The total length of the specified buffers is too big.");
491             }
492             length += bLen;
493             if (order != null) {
494                 if (!order.equals(b.order())) {
495                     throw new IllegalArgumentException("inconsistent byte order");
496                 }
497             } else {
498                 order = b.order();
499             }
500         }
501 
502         if (length == 0) {
503             return EMPTY_BUFFER;
504         }
505 
506         byte[] mergedArray = PlatformDependent.allocateUninitializedArray(length);
507         for (int i = 0, j = 0; i < buffers.length; i ++) {
508             ByteBuf b = buffers[i];
509             int bLen = b.readableBytes();
510             b.getBytes(b.readerIndex(), mergedArray, j, bLen);
511             j += bLen;
512         }
513 
514         return wrappedBuffer(mergedArray).order(order);
515     }
516 
517     /**
518      * Creates a new buffer whose content is a merged copy of the specified
519      * {@code buffers}' slices.  The new buffer's {@code readerIndex} and
520      * {@code writerIndex} are {@code 0} and the sum of all buffers'
521      * {@code remaining} respectively.
522      *
523      * @throws IllegalArgumentException
524      *         if the specified buffers' endianness are different from each
525      *         other
526      */
527     public static ByteBuf copiedBuffer(ByteBuffer... buffers) {
528         switch (buffers.length) {
529         case 0:
530             return EMPTY_BUFFER;
531         case 1:
532             return copiedBuffer(buffers[0]);
533         }
534 
535         // Merge the specified buffers into one buffer.
536         ByteOrder order = null;
537         int length = 0;
538         for (ByteBuffer b: buffers) {
539             int bLen = b.remaining();
540             if (bLen <= 0) {
541                 continue;
542             }
543             if (Integer.MAX_VALUE - length < bLen) {
544                 throw new IllegalArgumentException(
545                         "The total length of the specified buffers is too big.");
546             }
547             length += bLen;
548             if (order != null) {
549                 if (!order.equals(b.order())) {
550                     throw new IllegalArgumentException("inconsistent byte order");
551                 }
552             } else {
553                 order = b.order();
554             }
555         }
556 
557         if (length == 0) {
558             return EMPTY_BUFFER;
559         }
560 
561         byte[] mergedArray = PlatformDependent.allocateUninitializedArray(length);
562         for (int i = 0, j = 0; i < buffers.length; i ++) {
563             // Duplicate the buffer so we not adjust the position during our get operation.
564             // See https://github.com/netty/netty/issues/3896
565             ByteBuffer b = buffers[i].duplicate();
566             int bLen = b.remaining();
567             b.get(mergedArray, j, bLen);
568             j += bLen;
569         }
570 
571         return wrappedBuffer(mergedArray).order(order);
572     }
573 
574     /**
575      * Creates a new big-endian buffer whose content is the specified
576      * {@code string} encoded in the specified {@code charset}.
577      * The new buffer's {@code readerIndex} and {@code writerIndex} are
578      * {@code 0} and the length of the encoded string respectively.
579      */
580     public static ByteBuf copiedBuffer(CharSequence string, Charset charset) {
581         ObjectUtil.checkNotNull(string, "string");
582         if (CharsetUtil.UTF_8.equals(charset)) {
583             return copiedBufferUtf8(string);
584         }
585         if (CharsetUtil.US_ASCII.equals(charset)) {
586             return copiedBufferAscii(string);
587         }
588         if (string instanceof CharBuffer) {
589             return copiedBuffer((CharBuffer) string, charset);
590         }
591 
592         return copiedBuffer(CharBuffer.wrap(string), charset);
593     }
594 
595     private static ByteBuf copiedBufferUtf8(CharSequence string) {
596         boolean release = true;
597         // Mimic the same behavior as other copiedBuffer implementations.
598         int byteLength = ByteBufUtil.utf8Bytes(string);
599         ByteBuf buffer = ALLOC.heapBuffer(byteLength);
600         try {
601             ByteBufUtil.reserveAndWriteUtf8(buffer, string, byteLength);
602             release = false;
603             return buffer;
604         } finally {
605             if (release) {
606                 buffer.release();
607             }
608         }
609     }
610 
611     private static ByteBuf copiedBufferAscii(CharSequence string) {
612         boolean release = true;
613         // Mimic the same behavior as other copiedBuffer implementations.
614         ByteBuf buffer = ALLOC.heapBuffer(string.length());
615         try {
616             ByteBufUtil.writeAscii(buffer, string);
617             release = false;
618             return buffer;
619         } finally {
620             if (release) {
621                 buffer.release();
622             }
623         }
624     }
625 
626     /**
627      * Creates a new big-endian buffer whose content is a subregion of
628      * the specified {@code string} encoded in the specified {@code charset}.
629      * The new buffer's {@code readerIndex} and {@code writerIndex} are
630      * {@code 0} and the length of the encoded string respectively.
631      */
632     public static ByteBuf copiedBuffer(
633             CharSequence string, int offset, int length, Charset charset) {
634         ObjectUtil.checkNotNull(string, "string");
635         if (length == 0) {
636             return EMPTY_BUFFER;
637         }
638 
639         if (string instanceof CharBuffer) {
640             CharBuffer buf = (CharBuffer) string;
641             if (buf.hasArray()) {
642                 return copiedBuffer(
643                         buf.array(),
644                         buf.arrayOffset() + buf.position() + offset,
645                         length, charset);
646             }
647 
648             buf = buf.slice();
649             buf.limit(length);
650             buf.position(offset);
651             return copiedBuffer(buf, charset);
652         }
653 
654         return copiedBuffer(CharBuffer.wrap(string, offset, offset + length), charset);
655     }
656 
657     /**
658      * Creates a new big-endian buffer whose content is the specified
659      * {@code array} encoded in the specified {@code charset}.
660      * The new buffer's {@code readerIndex} and {@code writerIndex} are
661      * {@code 0} and the length of the encoded string respectively.
662      */
663     public static ByteBuf copiedBuffer(char[] array, Charset charset) {
664         ObjectUtil.checkNotNull(array, "array");
665         return copiedBuffer(array, 0, array.length, charset);
666     }
667 
668     /**
669      * Creates a new big-endian buffer whose content is a subregion of
670      * the specified {@code array} encoded in the specified {@code charset}.
671      * The new buffer's {@code readerIndex} and {@code writerIndex} are
672      * {@code 0} and the length of the encoded string respectively.
673      */
674     public static ByteBuf copiedBuffer(char[] array, int offset, int length, Charset charset) {
675         ObjectUtil.checkNotNull(array, "array");
676         if (length == 0) {
677             return EMPTY_BUFFER;
678         }
679         return copiedBuffer(CharBuffer.wrap(array, offset, length), charset);
680     }
681 
682     private static ByteBuf copiedBuffer(CharBuffer buffer, Charset charset) {
683         return ByteBufUtil.encodeString0(ALLOC, true, buffer, charset, 0);
684     }
685 
686     /**
687      * Creates a read-only buffer which disallows any modification operations
688      * on the specified {@code buffer}.  The new buffer has the same
689      * {@code readerIndex} and {@code writerIndex} with the specified
690      * {@code buffer}.
691      *
692      * @deprecated Use {@link ByteBuf#asReadOnly()}.
693      */
694     @Deprecated
695     public static ByteBuf unmodifiableBuffer(ByteBuf buffer) {
696         ByteOrder endianness = buffer.order();
697         if (endianness == BIG_ENDIAN) {
698             return newReadyOnlyBuffer(buffer);
699         }
700 
701         return newReadyOnlyBuffer(buffer.order(BIG_ENDIAN)).order(LITTLE_ENDIAN);
702     }
703 
704     private static ReadOnlyByteBuf newReadyOnlyBuffer(ByteBuf buffer) {
705         return buffer instanceof AbstractByteBuf ?
706                 new ReadOnlyAbstractByteBuf((AbstractByteBuf) buffer) :
707                 new ReadOnlyByteBuf(buffer);
708     }
709 
710     /**
711      * Creates a new 4-byte big-endian buffer that holds the specified 32-bit integer.
712      */
713     public static ByteBuf copyInt(int value) {
714         ByteBuf buf = buffer(4);
715         buf.writeInt(value);
716         return buf;
717     }
718 
719     /**
720      * Create a big-endian buffer that holds a sequence of the specified 32-bit integers.
721      */
722     public static ByteBuf copyInt(int... values) {
723         if (values == null || values.length == 0) {
724             return EMPTY_BUFFER;
725         }
726         ByteBuf buffer = buffer(values.length * 4);
727         for (int v: values) {
728             buffer.writeInt(v);
729         }
730         return buffer;
731     }
732 
733     /**
734      * Creates a new 2-byte big-endian buffer that holds the specified 16-bit integer.
735      */
736     public static ByteBuf copyShort(int value) {
737         ByteBuf buf = buffer(2);
738         buf.writeShort(value);
739         return buf;
740     }
741 
742     /**
743      * Create a new big-endian buffer that holds a sequence of the specified 16-bit integers.
744      */
745     public static ByteBuf copyShort(short... values) {
746         if (values == null || values.length == 0) {
747             return EMPTY_BUFFER;
748         }
749         ByteBuf buffer = buffer(values.length * 2);
750         for (int v: values) {
751             buffer.writeShort(v);
752         }
753         return buffer;
754     }
755 
756     /**
757      * Create a new big-endian buffer that holds a sequence of the specified 16-bit integers.
758      */
759     public static ByteBuf copyShort(int... values) {
760         if (values == null || values.length == 0) {
761             return EMPTY_BUFFER;
762         }
763         ByteBuf buffer = buffer(values.length * 2);
764         for (int v: values) {
765             buffer.writeShort(v);
766         }
767         return buffer;
768     }
769 
770     /**
771      * Creates a new 3-byte big-endian buffer that holds the specified 24-bit integer.
772      */
773     public static ByteBuf copyMedium(int value) {
774         ByteBuf buf = buffer(3);
775         buf.writeMedium(value);
776         return buf;
777     }
778 
779     /**
780      * Create a new big-endian buffer that holds a sequence of the specified 24-bit integers.
781      */
782     public static ByteBuf copyMedium(int... values) {
783         if (values == null || values.length == 0) {
784             return EMPTY_BUFFER;
785         }
786         ByteBuf buffer = buffer(values.length * 3);
787         for (int v: values) {
788             buffer.writeMedium(v);
789         }
790         return buffer;
791     }
792 
793     /**
794      * Creates a new 8-byte big-endian buffer that holds the specified 64-bit integer.
795      */
796     public static ByteBuf copyLong(long value) {
797         ByteBuf buf = buffer(8);
798         buf.writeLong(value);
799         return buf;
800     }
801 
802     /**
803      * Create a new big-endian buffer that holds a sequence of the specified 64-bit integers.
804      */
805     public static ByteBuf copyLong(long... values) {
806         if (values == null || values.length == 0) {
807             return EMPTY_BUFFER;
808         }
809         ByteBuf buffer = buffer(values.length * 8);
810         for (long v: values) {
811             buffer.writeLong(v);
812         }
813         return buffer;
814     }
815 
816     /**
817      * Creates a new single-byte big-endian buffer that holds the specified boolean value.
818      */
819     public static ByteBuf copyBoolean(boolean value) {
820         ByteBuf buf = buffer(1);
821         buf.writeBoolean(value);
822         return buf;
823     }
824 
825     /**
826      * Create a new big-endian buffer that holds a sequence of the specified boolean values.
827      */
828     public static ByteBuf copyBoolean(boolean... values) {
829         if (values == null || values.length == 0) {
830             return EMPTY_BUFFER;
831         }
832         ByteBuf buffer = buffer(values.length);
833         for (boolean v: values) {
834             buffer.writeBoolean(v);
835         }
836         return buffer;
837     }
838 
839     /**
840      * Creates a new 4-byte big-endian buffer that holds the specified 32-bit floating point number.
841      */
842     public static ByteBuf copyFloat(float value) {
843         ByteBuf buf = buffer(4);
844         buf.writeFloat(value);
845         return buf;
846     }
847 
848     /**
849      * Create a new big-endian buffer that holds a sequence of the specified 32-bit floating point numbers.
850      */
851     public static ByteBuf copyFloat(float... values) {
852         if (values == null || values.length == 0) {
853             return EMPTY_BUFFER;
854         }
855         ByteBuf buffer = buffer(values.length * 4);
856         for (float v: values) {
857             buffer.writeFloat(v);
858         }
859         return buffer;
860     }
861 
862     /**
863      * Creates a new 8-byte big-endian buffer that holds the specified 64-bit floating point number.
864      */
865     public static ByteBuf copyDouble(double value) {
866         ByteBuf buf = buffer(8);
867         buf.writeDouble(value);
868         return buf;
869     }
870 
871     /**
872      * Create a new big-endian buffer that holds a sequence of the specified 64-bit floating point numbers.
873      */
874     public static ByteBuf copyDouble(double... values) {
875         if (values == null || values.length == 0) {
876             return EMPTY_BUFFER;
877         }
878         ByteBuf buffer = buffer(values.length * 8);
879         for (double v: values) {
880             buffer.writeDouble(v);
881         }
882         return buffer;
883     }
884 
885     /**
886      * Return a unreleasable view on the given {@link ByteBuf} which will just ignore release and retain calls.
887      */
888     public static ByteBuf unreleasableBuffer(ByteBuf buf) {
889         return new UnreleasableByteBuf(buf);
890     }
891 
892     /**
893      * Wrap the given {@link ByteBuf}s in an unmodifiable {@link ByteBuf}. Be aware the returned {@link ByteBuf} will
894      * not try to slice the given {@link ByteBuf}s to reduce GC-Pressure.
895      *
896      * @deprecated Use {@link #wrappedUnmodifiableBuffer(ByteBuf...)}.
897      */
898     @Deprecated
899     public static ByteBuf unmodifiableBuffer(ByteBuf... buffers) {
900         return wrappedUnmodifiableBuffer(true, buffers);
901     }
902 
903     /**
904      * Wrap the given {@link ByteBuf}s in an unmodifiable {@link ByteBuf}. Be aware the returned {@link ByteBuf} will
905      * not try to slice the given {@link ByteBuf}s to reduce GC-Pressure.
906      *
907      * The returned {@link ByteBuf} may wrap the provided array directly, and so should not be subsequently modified.
908      */
909     public static ByteBuf wrappedUnmodifiableBuffer(ByteBuf... buffers) {
910         return wrappedUnmodifiableBuffer(false, buffers);
911     }
912 
913     private static ByteBuf wrappedUnmodifiableBuffer(boolean copy, ByteBuf... buffers) {
914         switch (buffers.length) {
915         case 0:
916             return EMPTY_BUFFER;
917         case 1:
918             return buffers[0].asReadOnly();
919         default:
920             if (copy) {
921                 buffers = Arrays.copyOf(buffers, buffers.length, ByteBuf[].class);
922             }
923             return new FixedCompositeByteBuf(ALLOC, buffers);
924         }
925     }
926 
927     private Unpooled() {
928         // Unused
929     }
930 }