1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.buffer;
17
18 import io.netty.util.internal.EmptyArrays;
19 import io.netty.util.internal.RecyclableArrayList;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.nio.ByteBuffer;
25 import java.nio.ByteOrder;
26 import java.nio.ReadOnlyBufferException;
27 import java.nio.channels.FileChannel;
28 import java.nio.channels.GatheringByteChannel;
29 import java.nio.channels.ScatteringByteChannel;
30 import java.util.Collections;
31
32
33
34
35
36 final class FixedCompositeByteBuf extends AbstractReferenceCountedByteBuf {
37 private static final ByteBuf[] EMPTY = { Unpooled.EMPTY_BUFFER };
38 private final int nioBufferCount;
39 private final int capacity;
40 private final ByteBufAllocator allocator;
41 private final ByteOrder order;
42 private final ByteBuf[] buffers;
43 private final boolean direct;
44
45 FixedCompositeByteBuf(ByteBufAllocator allocator, ByteBuf... buffers) {
46 super(AbstractByteBufAllocator.DEFAULT_MAX_CAPACITY);
47 if (buffers.length == 0) {
48 this.buffers = EMPTY;
49 order = ByteOrder.BIG_ENDIAN;
50 nioBufferCount = 1;
51 capacity = 0;
52 direct = Unpooled.EMPTY_BUFFER.isDirect();
53 } else {
54 ByteBuf b = buffers[0];
55 this.buffers = buffers;
56 boolean direct = true;
57 int nioBufferCount = b.nioBufferCount();
58 int capacity = b.readableBytes();
59 order = b.order();
60 for (int i = 1; i < buffers.length; i++) {
61 b = buffers[i];
62 if (buffers[i].order() != order) {
63 throw new IllegalArgumentException("All ByteBufs need to have same ByteOrder");
64 }
65 nioBufferCount += b.nioBufferCount();
66 capacity += b.readableBytes();
67 if (!b.isDirect()) {
68 direct = false;
69 }
70 }
71 this.nioBufferCount = nioBufferCount;
72 this.capacity = capacity;
73 this.direct = direct;
74 }
75 setIndex(0, capacity());
76 this.allocator = allocator;
77 }
78
79 @Override
80 public boolean isWritable() {
81 return false;
82 }
83
84 @Override
85 public boolean isWritable(int size) {
86 return false;
87 }
88
89 @Override
90 public ByteBuf discardReadBytes() {
91 throw new ReadOnlyBufferException();
92 }
93
94 @Override
95 public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
96 throw new ReadOnlyBufferException();
97 }
98
99 @Override
100 public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
101 throw new ReadOnlyBufferException();
102 }
103
104 @Override
105 public ByteBuf setBytes(int index, ByteBuffer src) {
106 throw new ReadOnlyBufferException();
107 }
108
109 @Override
110 public ByteBuf setByte(int index, int value) {
111 throw new ReadOnlyBufferException();
112 }
113
114 @Override
115 protected void _setByte(int index, int value) {
116 throw new ReadOnlyBufferException();
117 }
118
119 @Override
120 public ByteBuf setShort(int index, int value) {
121 throw new ReadOnlyBufferException();
122 }
123
124 @Override
125 protected void _setShort(int index, int value) {
126 throw new ReadOnlyBufferException();
127 }
128
129 @Override
130 protected void _setShortLE(int index, int value) {
131 throw new ReadOnlyBufferException();
132 }
133
134 @Override
135 public ByteBuf setMedium(int index, int value) {
136 throw new ReadOnlyBufferException();
137 }
138
139 @Override
140 protected void _setMedium(int index, int value) {
141 throw new ReadOnlyBufferException();
142 }
143
144 @Override
145 protected void _setMediumLE(int index, int value) {
146 throw new ReadOnlyBufferException();
147 }
148
149 @Override
150 public ByteBuf setInt(int index, int value) {
151 throw new ReadOnlyBufferException();
152 }
153
154 @Override
155 protected void _setInt(int index, int value) {
156 throw new ReadOnlyBufferException();
157 }
158
159 @Override
160 protected void _setIntLE(int index, int value) {
161 throw new ReadOnlyBufferException();
162 }
163
164 @Override
165 public ByteBuf setLong(int index, long value) {
166 throw new ReadOnlyBufferException();
167 }
168
169 @Override
170 protected void _setLong(int index, long value) {
171 throw new ReadOnlyBufferException();
172 }
173
174 @Override
175 protected void _setLongLE(int index, long value) {
176 throw new ReadOnlyBufferException();
177 }
178
179 @Override
180 public int setBytes(int index, InputStream in, int length) {
181 throw new ReadOnlyBufferException();
182 }
183
184 @Override
185 public int setBytes(int index, ScatteringByteChannel in, int length) {
186 throw new ReadOnlyBufferException();
187 }
188
189 @Override
190 public int setBytes(int index, FileChannel in, long position, int length) {
191 throw new ReadOnlyBufferException();
192 }
193
194 @Override
195 public int capacity() {
196 return capacity;
197 }
198
199 @Override
200 public int maxCapacity() {
201 return capacity;
202 }
203
204 @Override
205 public ByteBuf capacity(int newCapacity) {
206 throw new ReadOnlyBufferException();
207 }
208
209 @Override
210 public ByteBufAllocator alloc() {
211 return allocator;
212 }
213
214 @Override
215 public ByteOrder order() {
216 return order;
217 }
218
219 @Override
220 public ByteBuf unwrap() {
221 return null;
222 }
223
224 @Override
225 public boolean isDirect() {
226 return direct;
227 }
228
229 private Component findComponent(int index) {
230 int readable = 0;
231 for (int i = 0 ; i < buffers.length; i++) {
232 Component comp = null;
233 ByteBuf b = buffers[i];
234 if (b instanceof Component) {
235 comp = (Component) b;
236 b = comp.buf;
237 }
238 readable += b.readableBytes();
239 if (index < readable) {
240 if (comp == null) {
241
242
243 comp = new Component(i, readable - b.readableBytes(), b);
244 buffers[i] = comp;
245 }
246 return comp;
247 }
248 }
249 throw new IllegalStateException();
250 }
251
252
253
254
255 private ByteBuf buffer(int i) {
256 ByteBuf b = buffers[i];
257 return b instanceof Component ? ((Component) b).buf : b;
258 }
259
260 @Override
261 public byte getByte(int index) {
262 return _getByte(index);
263 }
264
265 @Override
266 protected byte _getByte(int index) {
267 Component c = findComponent(index);
268 return c.buf.getByte(index - c.offset);
269 }
270
271 @Override
272 protected short _getShort(int index) {
273 Component c = findComponent(index);
274 if (index + 2 <= c.endOffset) {
275 return c.buf.getShort(index - c.offset);
276 } else if (order() == ByteOrder.BIG_ENDIAN) {
277 return (short) ((_getByte(index) & 0xff) << 8 | _getByte(index + 1) & 0xff);
278 } else {
279 return (short) (_getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8);
280 }
281 }
282
283 @Override
284 protected short _getShortLE(int index) {
285 Component c = findComponent(index);
286 if (index + 2 <= c.endOffset) {
287 return c.buf.getShortLE(index - c.offset);
288 } else if (order() == ByteOrder.BIG_ENDIAN) {
289 return (short) (_getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8);
290 } else {
291 return (short) ((_getByte(index) & 0xff) << 8 | _getByte(index + 1) & 0xff);
292 }
293 }
294
295 @Override
296 protected int _getUnsignedMedium(int index) {
297 Component c = findComponent(index);
298 if (index + 3 <= c.endOffset) {
299 return c.buf.getUnsignedMedium(index - c.offset);
300 } else if (order() == ByteOrder.BIG_ENDIAN) {
301 return (_getShort(index) & 0xffff) << 8 | _getByte(index + 2) & 0xff;
302 } else {
303 return _getShort(index) & 0xFFFF | (_getByte(index + 2) & 0xFF) << 16;
304 }
305 }
306
307 @Override
308 protected int _getUnsignedMediumLE(int index) {
309 Component c = findComponent(index);
310 if (index + 3 <= c.endOffset) {
311 return c.buf.getUnsignedMediumLE(index - c.offset);
312 } else if (order() == ByteOrder.BIG_ENDIAN) {
313 return _getShortLE(index) & 0xffff | (_getByte(index + 2) & 0xff) << 16;
314 } else {
315 return (_getShortLE(index) & 0xffff) << 8 | _getByte(index + 2) & 0xff;
316 }
317 }
318
319 @Override
320 protected int _getInt(int index) {
321 Component c = findComponent(index);
322 if (index + 4 <= c.endOffset) {
323 return c.buf.getInt(index - c.offset);
324 } else if (order() == ByteOrder.BIG_ENDIAN) {
325 return (_getShort(index) & 0xffff) << 16 | _getShort(index + 2) & 0xffff;
326 } else {
327 return _getShort(index) & 0xFFFF | (_getShort(index + 2) & 0xFFFF) << 16;
328 }
329 }
330
331 @Override
332 protected int _getIntLE(int index) {
333 Component c = findComponent(index);
334 if (index + 4 <= c.endOffset) {
335 return c.buf.getIntLE(index - c.offset);
336 } else if (order() == ByteOrder.BIG_ENDIAN) {
337 return _getShortLE(index) & 0xFFFF | (_getShortLE(index + 2) & 0xFFFF) << 16;
338 } else {
339 return (_getShortLE(index) & 0xffff) << 16 | _getShortLE(index + 2) & 0xffff;
340 }
341 }
342
343 @Override
344 protected long _getLong(int index) {
345 Component c = findComponent(index);
346 if (index + 8 <= c.endOffset) {
347 return c.buf.getLong(index - c.offset);
348 } else if (order() == ByteOrder.BIG_ENDIAN) {
349 return (_getInt(index) & 0xffffffffL) << 32 | _getInt(index + 4) & 0xffffffffL;
350 } else {
351 return _getInt(index) & 0xFFFFFFFFL | (_getInt(index + 4) & 0xFFFFFFFFL) << 32;
352 }
353 }
354
355 @Override
356 protected long _getLongLE(int index) {
357 Component c = findComponent(index);
358 if (index + 8 <= c.endOffset) {
359 return c.buf.getLongLE(index - c.offset);
360 } else if (order() == ByteOrder.BIG_ENDIAN) {
361 return _getIntLE(index) & 0xffffffffL | (_getIntLE(index + 4) & 0xffffffffL) << 32;
362 } else {
363 return (_getIntLE(index) & 0xffffffffL) << 32 | _getIntLE(index + 4) & 0xffffffffL;
364 }
365 }
366
367 @Override
368 public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
369 checkDstIndex(index, length, dstIndex, dst.length);
370 if (length == 0) {
371 return this;
372 }
373
374 Component c = findComponent(index);
375 int i = c.index;
376 int adjustment = c.offset;
377 ByteBuf s = c.buf;
378 for (;;) {
379 int localLength = Math.min(length, s.readableBytes() - (index - adjustment));
380 s.getBytes(index - adjustment, dst, dstIndex, localLength);
381 index += localLength;
382 dstIndex += localLength;
383 length -= localLength;
384 adjustment += s.readableBytes();
385 if (length <= 0) {
386 break;
387 }
388 s = buffer(++i);
389 }
390 return this;
391 }
392
393 @Override
394 public ByteBuf getBytes(int index, ByteBuffer dst) {
395 int limit = dst.limit();
396 int length = dst.remaining();
397
398 checkIndex(index, length);
399 if (length == 0) {
400 return this;
401 }
402
403 try {
404 Component c = findComponent(index);
405 int i = c.index;
406 int adjustment = c.offset;
407 ByteBuf s = c.buf;
408 for (;;) {
409 int localLength = Math.min(length, s.readableBytes() - (index - adjustment));
410 dst.limit(dst.position() + localLength);
411 s.getBytes(index - adjustment, dst);
412 index += localLength;
413 length -= localLength;
414 adjustment += s.readableBytes();
415 if (length <= 0) {
416 break;
417 }
418 s = buffer(++i);
419 }
420 } finally {
421 dst.limit(limit);
422 }
423 return this;
424 }
425
426 @Override
427 public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
428 checkDstIndex(index, length, dstIndex, dst.capacity());
429 if (length == 0) {
430 return this;
431 }
432
433 Component c = findComponent(index);
434 int i = c.index;
435 int adjustment = c.offset;
436 ByteBuf s = c.buf;
437 for (;;) {
438 int localLength = Math.min(length, s.readableBytes() - (index - adjustment));
439 s.getBytes(index - adjustment, dst, dstIndex, localLength);
440 index += localLength;
441 dstIndex += localLength;
442 length -= localLength;
443 adjustment += s.readableBytes();
444 if (length <= 0) {
445 break;
446 }
447 s = buffer(++i);
448 }
449 return this;
450 }
451
452 @Override
453 public int getBytes(int index, GatheringByteChannel out, int length)
454 throws IOException {
455 int count = nioBufferCount();
456 if (count == 1) {
457 return out.write(internalNioBuffer(index, length));
458 } else {
459 long writtenBytes = out.write(nioBuffers(index, length));
460 if (writtenBytes > Integer.MAX_VALUE) {
461 return Integer.MAX_VALUE;
462 } else {
463 return (int) writtenBytes;
464 }
465 }
466 }
467
468 @Override
469 public int getBytes(int index, FileChannel out, long position, int length)
470 throws IOException {
471 int count = nioBufferCount();
472 if (count == 1) {
473 return out.write(internalNioBuffer(index, length), position);
474 } else {
475 long writtenBytes = 0;
476 for (ByteBuffer buf : nioBuffers(index, length)) {
477 writtenBytes += out.write(buf, position + writtenBytes);
478 }
479 if (writtenBytes > Integer.MAX_VALUE) {
480 return Integer.MAX_VALUE;
481 } else {
482 return (int) writtenBytes;
483 }
484 }
485 }
486
487 @Override
488 public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
489 checkIndex(index, length);
490 if (length == 0) {
491 return this;
492 }
493
494 Component c = findComponent(index);
495 int i = c.index;
496 int adjustment = c.offset;
497 ByteBuf s = c.buf;
498 for (;;) {
499 int localLength = Math.min(length, s.readableBytes() - (index - adjustment));
500 s.getBytes(index - adjustment, out, localLength);
501 index += localLength;
502 length -= localLength;
503 adjustment += s.readableBytes();
504 if (length <= 0) {
505 break;
506 }
507 s = buffer(++i);
508 }
509 return this;
510 }
511
512 @Override
513 public ByteBuf copy(int index, int length) {
514 checkIndex(index, length);
515 boolean release = true;
516 ByteBuf buf = alloc().buffer(length);
517 try {
518 buf.writeBytes(this, index, length);
519 release = false;
520 return buf;
521 } finally {
522 if (release) {
523 buf.release();
524 }
525 }
526 }
527
528 @Override
529 public int nioBufferCount() {
530 return nioBufferCount;
531 }
532
533 @Override
534 public ByteBuffer nioBuffer(int index, int length) {
535 checkIndex(index, length);
536 if (buffers.length == 1) {
537 ByteBuf buf = buffer(0);
538 if (buf.nioBufferCount() == 1) {
539 return buf.nioBuffer(index, length);
540 }
541 }
542 ByteBuffer merged = ByteBuffer.allocate(length).order(order());
543 ByteBuffer[] buffers = nioBuffers(index, length);
544
545
546 for (int i = 0; i < buffers.length; i++) {
547 merged.put(buffers[i]);
548 }
549
550 merged.flip();
551 return merged;
552 }
553
554 @Override
555 public ByteBuffer internalNioBuffer(int index, int length) {
556 if (buffers.length == 1) {
557 return buffer(0).internalNioBuffer(index, length);
558 }
559 throw new UnsupportedOperationException();
560 }
561
562 @Override
563 public ByteBuffer[] nioBuffers(int index, int length) {
564 checkIndex(index, length);
565 if (length == 0) {
566 return EmptyArrays.EMPTY_BYTE_BUFFERS;
567 }
568
569 RecyclableArrayList array = RecyclableArrayList.newInstance(buffers.length);
570 try {
571 Component c = findComponent(index);
572 int i = c.index;
573 int adjustment = c.offset;
574 ByteBuf s = c.buf;
575 for (;;) {
576 int localLength = Math.min(length, s.readableBytes() - (index - adjustment));
577 switch (s.nioBufferCount()) {
578 case 0:
579 throw new UnsupportedOperationException();
580 case 1:
581 array.add(s.nioBuffer(index - adjustment, localLength));
582 break;
583 default:
584 Collections.addAll(array, s.nioBuffers(index - adjustment, localLength));
585 }
586
587 index += localLength;
588 length -= localLength;
589 adjustment += s.readableBytes();
590 if (length <= 0) {
591 break;
592 }
593 s = buffer(++i);
594 }
595
596 return array.toArray(EmptyArrays.EMPTY_BYTE_BUFFERS);
597 } finally {
598 array.recycle();
599 }
600 }
601
602 @Override
603 public boolean hasArray() {
604 switch (buffers.length) {
605 case 0:
606 return true;
607 case 1:
608 return buffer(0).hasArray();
609 default:
610 return false;
611 }
612 }
613
614 @Override
615 public byte[] array() {
616 switch (buffers.length) {
617 case 0:
618 return EmptyArrays.EMPTY_BYTES;
619 case 1:
620 return buffer(0).array();
621 default:
622 throw new UnsupportedOperationException();
623 }
624 }
625
626 @Override
627 public int arrayOffset() {
628 switch (buffers.length) {
629 case 0:
630 return 0;
631 case 1:
632 return buffer(0).arrayOffset();
633 default:
634 throw new UnsupportedOperationException();
635 }
636 }
637
638 @Override
639 public boolean hasMemoryAddress() {
640 switch (buffers.length) {
641 case 0:
642 return Unpooled.EMPTY_BUFFER.hasMemoryAddress();
643 case 1:
644 return buffer(0).hasMemoryAddress();
645 default:
646 return false;
647 }
648 }
649
650 @Override
651 public long memoryAddress() {
652 switch (buffers.length) {
653 case 0:
654 return Unpooled.EMPTY_BUFFER.memoryAddress();
655 case 1:
656 return buffer(0).memoryAddress();
657 default:
658 throw new UnsupportedOperationException();
659 }
660 }
661
662 @Override
663 protected void deallocate() {
664 for (int i = 0; i < buffers.length; i++) {
665 buffer(i).release();
666 }
667 }
668
669 @Override
670 public String toString() {
671 String result = super.toString();
672 result = result.substring(0, result.length() - 1);
673 return result + ", components=" + buffers.length + ')';
674 }
675
676 private static final class Component extends WrappedByteBuf {
677 private final int index;
678 private final int offset;
679 private final int endOffset;
680
681 Component(int index, int offset, ByteBuf buf) {
682 super(buf);
683 this.index = index;
684 this.offset = offset;
685 endOffset = offset + buf.readableBytes();
686 }
687 }
688 }