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