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 }