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