查看本类的 API文档回源码主页即时通讯网 - 即时通讯开发者社区!
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         ByteBuf buffer = ALLOC.heapBuffer(ByteBufUtil.utf8Bytes(string));
599         try {
600             ByteBufUtil.writeUtf8(buffer, string);
601             release = false;
602             return buffer;
603         } finally {
604             if (release) {
605                 buffer.release();
606             }
607         }
608     }
609 
610     private static ByteBuf copiedBufferAscii(CharSequence string) {
611         boolean release = true;
612         // Mimic the same behavior as other copiedBuffer implementations.
613         ByteBuf buffer = ALLOC.heapBuffer(string.length());
614         try {
615             ByteBufUtil.writeAscii(buffer, string);
616             release = false;
617             return buffer;
618         } finally {
619             if (release) {
620                 buffer.release();
621             }
622         }
623     }
624 
625     /**
626      * Creates a new big-endian buffer whose content is a subregion of
627      * the specified {@code string} encoded in the specified {@code charset}.
628      * The new buffer's {@code readerIndex} and {@code writerIndex} are
629      * {@code 0} and the length of the encoded string respectively.
630      */
631     public static ByteBuf copiedBuffer(
632             CharSequence string, int offset, int length, Charset charset) {
633         ObjectUtil.checkNotNull(string, "string");
634         if (length == 0) {
635             return EMPTY_BUFFER;
636         }
637 
638         if (string instanceof CharBuffer) {
639             CharBuffer buf = (CharBuffer) string;
640             if (buf.hasArray()) {
641                 return copiedBuffer(
642                         buf.array(),
643                         buf.arrayOffset() + buf.position() + offset,
644                         length, charset);
645             }
646 
647             buf = buf.slice();
648             buf.limit(length);
649             buf.position(offset);
650             return copiedBuffer(buf, charset);
651         }
652 
653         return copiedBuffer(CharBuffer.wrap(string, offset, offset + length), charset);
654     }
655 
656     /**
657      * Creates a new big-endian buffer whose content is the specified
658      * {@code array} encoded in the specified {@code charset}.
659      * The new buffer's {@code readerIndex} and {@code writerIndex} are
660      * {@code 0} and the length of the encoded string respectively.
661      */
662     public static ByteBuf copiedBuffer(char[] array, Charset charset) {
663         ObjectUtil.checkNotNull(array, "array");
664         return copiedBuffer(array, 0, array.length, charset);
665     }
666 
667     /**
668      * Creates a new big-endian buffer whose content is a subregion of
669      * the specified {@code array} encoded in the specified {@code charset}.
670      * The new buffer's {@code readerIndex} and {@code writerIndex} are
671      * {@code 0} and the length of the encoded string respectively.
672      */
673     public static ByteBuf copiedBuffer(char[] array, int offset, int length, Charset charset) {
674         ObjectUtil.checkNotNull(array, "array");
675         if (length == 0) {
676             return EMPTY_BUFFER;
677         }
678         return copiedBuffer(CharBuffer.wrap(array, offset, length), charset);
679     }
680 
681     private static ByteBuf copiedBuffer(CharBuffer buffer, Charset charset) {
682         return ByteBufUtil.encodeString0(ALLOC, true, buffer, charset, 0);
683     }
684 
685     /**
686      * Creates a read-only buffer which disallows any modification operations
687      * on the specified {@code buffer}.  The new buffer has the same
688      * {@code readerIndex} and {@code writerIndex} with the specified
689      * {@code buffer}.
690      *
691      * @deprecated Use {@link ByteBuf#asReadOnly()}.
692      */
693     @Deprecated
694     public static ByteBuf unmodifiableBuffer(ByteBuf buffer) {
695         ByteOrder endianness = buffer.order();
696         if (endianness == BIG_ENDIAN) {
697             return new ReadOnlyByteBuf(buffer);
698         }
699 
700         return new ReadOnlyByteBuf(buffer.order(BIG_ENDIAN)).order(LITTLE_ENDIAN);
701     }
702 
703     /**
704      * Creates a new 4-byte big-endian buffer that holds the specified 32-bit integer.
705      */
706     public static ByteBuf copyInt(int value) {
707         ByteBuf buf = buffer(4);
708         buf.writeInt(value);
709         return buf;
710     }
711 
712     /**
713      * Create a big-endian buffer that holds a sequence of the specified 32-bit integers.
714      */
715     public static ByteBuf copyInt(int... values) {
716         if (values == null || values.length == 0) {
717             return EMPTY_BUFFER;
718         }
719         ByteBuf buffer = buffer(values.length * 4);
720         for (int v: values) {
721             buffer.writeInt(v);
722         }
723         return buffer;
724     }
725 
726     /**
727      * Creates a new 2-byte big-endian buffer that holds the specified 16-bit integer.
728      */
729     public static ByteBuf copyShort(int value) {
730         ByteBuf buf = buffer(2);
731         buf.writeShort(value);
732         return buf;
733     }
734 
735     /**
736      * Create a new big-endian buffer that holds a sequence of the specified 16-bit integers.
737      */
738     public static ByteBuf copyShort(short... values) {
739         if (values == null || values.length == 0) {
740             return EMPTY_BUFFER;
741         }
742         ByteBuf buffer = buffer(values.length * 2);
743         for (int v: values) {
744             buffer.writeShort(v);
745         }
746         return buffer;
747     }
748 
749     /**
750      * Create a new big-endian buffer that holds a sequence of the specified 16-bit integers.
751      */
752     public static ByteBuf copyShort(int... values) {
753         if (values == null || values.length == 0) {
754             return EMPTY_BUFFER;
755         }
756         ByteBuf buffer = buffer(values.length * 2);
757         for (int v: values) {
758             buffer.writeShort(v);
759         }
760         return buffer;
761     }
762 
763     /**
764      * Creates a new 3-byte big-endian buffer that holds the specified 24-bit integer.
765      */
766     public static ByteBuf copyMedium(int value) {
767         ByteBuf buf = buffer(3);
768         buf.writeMedium(value);
769         return buf;
770     }
771 
772     /**
773      * Create a new big-endian buffer that holds a sequence of the specified 24-bit integers.
774      */
775     public static ByteBuf copyMedium(int... values) {
776         if (values == null || values.length == 0) {
777             return EMPTY_BUFFER;
778         }
779         ByteBuf buffer = buffer(values.length * 3);
780         for (int v: values) {
781             buffer.writeMedium(v);
782         }
783         return buffer;
784     }
785 
786     /**
787      * Creates a new 8-byte big-endian buffer that holds the specified 64-bit integer.
788      */
789     public static ByteBuf copyLong(long value) {
790         ByteBuf buf = buffer(8);
791         buf.writeLong(value);
792         return buf;
793     }
794 
795     /**
796      * Create a new big-endian buffer that holds a sequence of the specified 64-bit integers.
797      */
798     public static ByteBuf copyLong(long... values) {
799         if (values == null || values.length == 0) {
800             return EMPTY_BUFFER;
801         }
802         ByteBuf buffer = buffer(values.length * 8);
803         for (long v: values) {
804             buffer.writeLong(v);
805         }
806         return buffer;
807     }
808 
809     /**
810      * Creates a new single-byte big-endian buffer that holds the specified boolean value.
811      */
812     public static ByteBuf copyBoolean(boolean value) {
813         ByteBuf buf = buffer(1);
814         buf.writeBoolean(value);
815         return buf;
816     }
817 
818     /**
819      * Create a new big-endian buffer that holds a sequence of the specified boolean values.
820      */
821     public static ByteBuf copyBoolean(boolean... values) {
822         if (values == null || values.length == 0) {
823             return EMPTY_BUFFER;
824         }
825         ByteBuf buffer = buffer(values.length);
826         for (boolean v: values) {
827             buffer.writeBoolean(v);
828         }
829         return buffer;
830     }
831 
832     /**
833      * Creates a new 4-byte big-endian buffer that holds the specified 32-bit floating point number.
834      */
835     public static ByteBuf copyFloat(float value) {
836         ByteBuf buf = buffer(4);
837         buf.writeFloat(value);
838         return buf;
839     }
840 
841     /**
842      * Create a new big-endian buffer that holds a sequence of the specified 32-bit floating point numbers.
843      */
844     public static ByteBuf copyFloat(float... values) {
845         if (values == null || values.length == 0) {
846             return EMPTY_BUFFER;
847         }
848         ByteBuf buffer = buffer(values.length * 4);
849         for (float v: values) {
850             buffer.writeFloat(v);
851         }
852         return buffer;
853     }
854 
855     /**
856      * Creates a new 8-byte big-endian buffer that holds the specified 64-bit floating point number.
857      */
858     public static ByteBuf copyDouble(double value) {
859         ByteBuf buf = buffer(8);
860         buf.writeDouble(value);
861         return buf;
862     }
863 
864     /**
865      * Create a new big-endian buffer that holds a sequence of the specified 64-bit floating point numbers.
866      */
867     public static ByteBuf copyDouble(double... values) {
868         if (values == null || values.length == 0) {
869             return EMPTY_BUFFER;
870         }
871         ByteBuf buffer = buffer(values.length * 8);
872         for (double v: values) {
873             buffer.writeDouble(v);
874         }
875         return buffer;
876     }
877 
878     /**
879      * Return a unreleasable view on the given {@link ByteBuf} which will just ignore release and retain calls.
880      */
881     public static ByteBuf unreleasableBuffer(ByteBuf buf) {
882         return new UnreleasableByteBuf(buf);
883     }
884 
885     /**
886      * Wrap the given {@link ByteBuf}s in an unmodifiable {@link ByteBuf}. Be aware the returned {@link ByteBuf} will
887      * not try to slice the given {@link ByteBuf}s to reduce GC-Pressure.
888      *
889      * @deprecated Use {@link #wrappedUnmodifiableBuffer(ByteBuf...)}.
890      */
891     @Deprecated
892     public static ByteBuf unmodifiableBuffer(ByteBuf... buffers) {
893         return wrappedUnmodifiableBuffer(true, buffers);
894     }
895 
896     /**
897      * Wrap the given {@link ByteBuf}s in an unmodifiable {@link ByteBuf}. Be aware the returned {@link ByteBuf} will
898      * not try to slice the given {@link ByteBuf}s to reduce GC-Pressure.
899      *
900      * The returned {@link ByteBuf} may wrap the provided array directly, and so should not be subsequently modified.
901      */
902     public static ByteBuf wrappedUnmodifiableBuffer(ByteBuf... buffers) {
903         return wrappedUnmodifiableBuffer(false, buffers);
904     }
905 
906     private static ByteBuf wrappedUnmodifiableBuffer(boolean copy, ByteBuf... buffers) {
907         switch (buffers.length) {
908         case 0:
909             return EMPTY_BUFFER;
910         case 1:
911             return buffers[0].asReadOnly();
912         default:
913             if (copy) {
914                 buffers = Arrays.copyOf(buffers, buffers.length, ByteBuf[].class);
915             }
916             return new FixedCompositeByteBuf(ALLOC, buffers);
917         }
918     }
919 
920     private Unpooled() {
921         // Unused
922     }
923 }