1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.buffer;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.OutputStream;
21 import java.nio.ByteBuffer;
22 import java.nio.channels.GatheringByteChannel;
23 import java.nio.channels.ScatteringByteChannel;
24 import java.nio.charset.Charset;
25 import java.util.NoSuchElementException;
26
27
28
29
30
31 public abstract class AbstractChannelBuffer implements ChannelBuffer {
32
33 private int readerIndex;
34 private int writerIndex;
35 private int markedReaderIndex;
36 private int markedWriterIndex;
37
38 public int readerIndex() {
39 return readerIndex;
40 }
41
42 public void readerIndex(int readerIndex) {
43 if (readerIndex < 0 || readerIndex > writerIndex) {
44 throw new IndexOutOfBoundsException();
45 }
46 this.readerIndex = readerIndex;
47 }
48
49 public int writerIndex() {
50 return writerIndex;
51 }
52
53 public void writerIndex(int writerIndex) {
54 if (writerIndex < readerIndex || writerIndex > capacity()) {
55 throw new IndexOutOfBoundsException("Invalid readerIndex: "
56 + readerIndex + " - Maximum is " + writerIndex);
57 }
58 this.writerIndex = writerIndex;
59 }
60
61 public void setIndex(int readerIndex, int writerIndex) {
62 if (readerIndex < 0 || readerIndex > writerIndex || writerIndex > capacity()) {
63 throw new IndexOutOfBoundsException("Invalid writerIndex: "
64 + writerIndex + " - Maximum is " + readerIndex + " or " + capacity());
65 }
66 this.readerIndex = readerIndex;
67 this.writerIndex = writerIndex;
68 }
69
70 public void clear() {
71 readerIndex = writerIndex = 0;
72 }
73
74 public boolean readable() {
75 return readableBytes() > 0;
76 }
77
78 public boolean writable() {
79 return writableBytes() > 0;
80 }
81
82 public int readableBytes() {
83 return writerIndex - readerIndex;
84 }
85
86 public int writableBytes() {
87 return capacity() - writerIndex;
88 }
89
90 public void markReaderIndex() {
91 markedReaderIndex = readerIndex;
92 }
93
94 public void resetReaderIndex() {
95 readerIndex(markedReaderIndex);
96 }
97
98 public void markWriterIndex() {
99 markedWriterIndex = writerIndex;
100 }
101
102 public void resetWriterIndex() {
103 writerIndex = markedWriterIndex;
104 }
105
106 public void discardReadBytes() {
107 if (readerIndex == 0) {
108 return;
109 }
110 setBytes(0, this, readerIndex, writerIndex - readerIndex);
111 writerIndex -= readerIndex;
112 markedReaderIndex = Math.max(markedReaderIndex - readerIndex, 0);
113 markedWriterIndex = Math.max(markedWriterIndex - readerIndex, 0);
114 readerIndex = 0;
115 }
116
117 public void ensureWritableBytes(int writableBytes) {
118 if (writableBytes > writableBytes()) {
119 throw new IndexOutOfBoundsException("Writable bytes exceeded: Got "
120 + writableBytes + ", maximum is " + writableBytes());
121 }
122 }
123
124 public short getUnsignedByte(int index) {
125 return (short) (getByte(index) & 0xFF);
126 }
127
128 public int getUnsignedShort(int index) {
129 return getShort(index) & 0xFFFF;
130 }
131
132 public int getMedium(int index) {
133 int value = getUnsignedMedium(index);
134 if ((value & 0x800000) != 0) {
135 value |= 0xff000000;
136 }
137 return value;
138 }
139
140 public long getUnsignedInt(int index) {
141 return getInt(index) & 0xFFFFFFFFL;
142 }
143
144 public char getChar(int index) {
145 return (char) getShort(index);
146 }
147
148 public float getFloat(int index) {
149 return Float.intBitsToFloat(getInt(index));
150 }
151
152 public double getDouble(int index) {
153 return Double.longBitsToDouble(getLong(index));
154 }
155
156 public void getBytes(int index, byte[] dst) {
157 getBytes(index, dst, 0, dst.length);
158 }
159
160 public void getBytes(int index, ChannelBuffer dst) {
161 getBytes(index, dst, dst.writableBytes());
162 }
163
164 public void getBytes(int index, ChannelBuffer dst, int length) {
165 if (length > dst.writableBytes()) {
166 throw new IndexOutOfBoundsException("Too many bytes to be read: Need "
167 + length + ", maximum is " + dst.writableBytes());
168 }
169 getBytes(index, dst, dst.writerIndex(), length);
170 dst.writerIndex(dst.writerIndex() + length);
171 }
172
173 public void setChar(int index, int value) {
174 setShort(index, value);
175 }
176
177 public void setFloat(int index, float value) {
178 setInt(index, Float.floatToRawIntBits(value));
179 }
180
181 public void setDouble(int index, double value) {
182 setLong(index, Double.doubleToRawLongBits(value));
183 }
184
185 public void setBytes(int index, byte[] src) {
186 setBytes(index, src, 0, src.length);
187 }
188
189 public void setBytes(int index, ChannelBuffer src) {
190 setBytes(index, src, src.readableBytes());
191 }
192
193 public void setBytes(int index, ChannelBuffer src, int length) {
194 if (length > src.readableBytes()) {
195 throw new IndexOutOfBoundsException("Too many bytes to write: Need "
196 + length + ", maximum is " + src.readableBytes());
197 }
198 setBytes(index, src, src.readerIndex(), length);
199 src.readerIndex(src.readerIndex() + length);
200 }
201
202 public void setZero(int index, int length) {
203 if (length == 0) {
204 return;
205 }
206 if (length < 0) {
207 throw new IllegalArgumentException(
208 "length must be 0 or greater than 0.");
209 }
210
211 int nLong = length >>> 3;
212 int nBytes = length & 7;
213 for (int i = nLong; i > 0; i --) {
214 setLong(index, 0);
215 index += 8;
216 }
217 if (nBytes == 4) {
218 setInt(index, 0);
219 } else if (nBytes < 4) {
220 for (int i = nBytes; i > 0; i --) {
221 setByte(index, (byte) 0);
222 index ++;
223 }
224 } else {
225 setInt(index, 0);
226 index += 4;
227 for (int i = nBytes - 4; i > 0; i --) {
228 setByte(index, (byte) 0);
229 index ++;
230 }
231 }
232 }
233
234 public byte readByte() {
235 if (readerIndex == writerIndex) {
236 throw new IndexOutOfBoundsException("Readable byte limit exceeded: "
237 + readerIndex);
238 }
239 return getByte(readerIndex ++);
240 }
241
242 public short readUnsignedByte() {
243 return (short) (readByte() & 0xFF);
244 }
245
246 public short readShort() {
247 checkReadableBytes(2);
248 short v = getShort(readerIndex);
249 readerIndex += 2;
250 return v;
251 }
252
253 public int readUnsignedShort() {
254 return readShort() & 0xFFFF;
255 }
256
257 public int readMedium() {
258 int value = readUnsignedMedium();
259 if ((value & 0x800000) != 0) {
260 value |= 0xff000000;
261 }
262 return value;
263 }
264
265 public int readUnsignedMedium() {
266 checkReadableBytes(3);
267 int v = getUnsignedMedium(readerIndex);
268 readerIndex += 3;
269 return v;
270 }
271
272 public int readInt() {
273 checkReadableBytes(4);
274 int v = getInt(readerIndex);
275 readerIndex += 4;
276 return v;
277 }
278
279 public long readUnsignedInt() {
280 return readInt() & 0xFFFFFFFFL;
281 }
282
283 public long readLong() {
284 checkReadableBytes(8);
285 long v = getLong(readerIndex);
286 readerIndex += 8;
287 return v;
288 }
289
290 public char readChar() {
291 return (char) readShort();
292 }
293
294 public float readFloat() {
295 return Float.intBitsToFloat(readInt());
296 }
297
298 public double readDouble() {
299 return Double.longBitsToDouble(readLong());
300 }
301
302 public ChannelBuffer readBytes(int length) {
303 checkReadableBytes(length);
304 if (length == 0) {
305 return ChannelBuffers.EMPTY_BUFFER;
306 }
307 ChannelBuffer buf = factory().getBuffer(order(), length);
308 buf.writeBytes(this, readerIndex, length);
309 readerIndex += length;
310 return buf;
311 }
312
313 @Deprecated
314 public ChannelBuffer readBytes(ChannelBufferIndexFinder endIndexFinder) {
315 int endIndex = indexOf(readerIndex, writerIndex, endIndexFinder);
316 if (endIndex < 0) {
317 throw new NoSuchElementException();
318 }
319 return readBytes(endIndex - readerIndex);
320 }
321
322 public ChannelBuffer readSlice(int length) {
323 ChannelBuffer slice = slice(readerIndex, length);
324 readerIndex += length;
325 return slice;
326 }
327
328 @Deprecated
329 public ChannelBuffer readSlice(ChannelBufferIndexFinder endIndexFinder) {
330 int endIndex = indexOf(readerIndex, writerIndex, endIndexFinder);
331 if (endIndex < 0) {
332 throw new NoSuchElementException();
333 }
334 return readSlice(endIndex - readerIndex);
335 }
336
337 public void readBytes(byte[] dst, int dstIndex, int length) {
338 checkReadableBytes(length);
339 getBytes(readerIndex, dst, dstIndex, length);
340 readerIndex += length;
341 }
342
343 public void readBytes(byte[] dst) {
344 readBytes(dst, 0, dst.length);
345 }
346
347 public void readBytes(ChannelBuffer dst) {
348 readBytes(dst, dst.writableBytes());
349 }
350
351 public void readBytes(ChannelBuffer dst, int length) {
352 if (length > dst.writableBytes()) {
353 throw new IndexOutOfBoundsException("Too many bytes to be read: Need "
354 + length + ", maximum is " + dst.writableBytes());
355 }
356 readBytes(dst, dst.writerIndex(), length);
357 dst.writerIndex(dst.writerIndex() + length);
358 }
359
360 public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
361 checkReadableBytes(length);
362 getBytes(readerIndex, dst, dstIndex, length);
363 readerIndex += length;
364 }
365
366 public void readBytes(ByteBuffer dst) {
367 int length = dst.remaining();
368 checkReadableBytes(length);
369 getBytes(readerIndex, dst);
370 readerIndex += length;
371 }
372
373 public int readBytes(GatheringByteChannel out, int length)
374 throws IOException {
375 checkReadableBytes(length);
376 int readBytes = getBytes(readerIndex, out, length);
377 readerIndex += readBytes;
378 return readBytes;
379 }
380
381 public void readBytes(OutputStream out, int length) throws IOException {
382 checkReadableBytes(length);
383 getBytes(readerIndex, out, length);
384 readerIndex += length;
385 }
386
387 public void skipBytes(int length) {
388 int newReaderIndex = readerIndex + length;
389 if (newReaderIndex > writerIndex) {
390 throw new IndexOutOfBoundsException("Readable bytes exceeded - Need "
391 + newReaderIndex + ", maximum is " + writerIndex);
392 }
393 readerIndex = newReaderIndex;
394 }
395
396 @Deprecated
397 public int skipBytes(ChannelBufferIndexFinder firstIndexFinder) {
398 int oldReaderIndex = readerIndex;
399 int newReaderIndex = indexOf(oldReaderIndex, writerIndex, firstIndexFinder);
400 if (newReaderIndex < 0) {
401 throw new NoSuchElementException();
402 }
403 readerIndex(newReaderIndex);
404 return newReaderIndex - oldReaderIndex;
405 }
406
407 public void writeByte(int value) {
408 setByte(writerIndex, value);
409 writerIndex++;
410 }
411
412 public void writeShort(int value) {
413 setShort(writerIndex, value);
414 writerIndex += 2;
415 }
416
417 public void writeMedium(int value) {
418 setMedium(writerIndex, value);
419 writerIndex += 3;
420 }
421
422 public void writeInt(int value) {
423 setInt(writerIndex, value);
424 writerIndex += 4;
425 }
426
427 public void writeLong(long value) {
428 setLong(writerIndex, value);
429 writerIndex += 8;
430 }
431
432 public void writeChar(int value) {
433 writeShort(value);
434 }
435
436 public void writeFloat(float value) {
437 writeInt(Float.floatToRawIntBits(value));
438 }
439
440 public void writeDouble(double value) {
441 writeLong(Double.doubleToRawLongBits(value));
442 }
443
444 public void writeBytes(byte[] src, int srcIndex, int length) {
445 setBytes(writerIndex, src, srcIndex, length);
446 writerIndex += length;
447 }
448
449 public void writeBytes(byte[] src) {
450 writeBytes(src, 0, src.length);
451 }
452
453 public void writeBytes(ChannelBuffer src) {
454 writeBytes(src, src.readableBytes());
455 }
456
457 public void writeBytes(ChannelBuffer src, int length) {
458 if (length > src.readableBytes()) {
459 throw new IndexOutOfBoundsException("Too many bytes to write - Need "
460 + length + ", maximum is " + src.readableBytes());
461 }
462 writeBytes(src, src.readerIndex(), length);
463 src.readerIndex(src.readerIndex() + length);
464 }
465
466 public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
467 setBytes(writerIndex, src, srcIndex, length);
468 writerIndex += length;
469 }
470
471 public void writeBytes(ByteBuffer src) {
472 int length = src.remaining();
473 setBytes(writerIndex, src);
474 writerIndex += length;
475 }
476
477 public int writeBytes(InputStream in, int length)
478 throws IOException {
479 int writtenBytes = setBytes(writerIndex, in, length);
480 if (writtenBytes > 0) {
481 writerIndex += writtenBytes;
482 }
483 return writtenBytes;
484 }
485
486 public int writeBytes(ScatteringByteChannel in, int length)
487 throws IOException {
488 int writtenBytes = setBytes(writerIndex, in, length);
489 if (writtenBytes > 0) {
490 writerIndex += writtenBytes;
491 }
492 return writtenBytes;
493 }
494
495 public void writeZero(int length) {
496 if (length == 0) {
497 return;
498 }
499 if (length < 0) {
500 throw new IllegalArgumentException(
501 "length must be 0 or greater than 0.");
502 }
503 int nLong = length >>> 3;
504 int nBytes = length & 7;
505 for (int i = nLong; i > 0; i --) {
506 writeLong(0);
507 }
508 if (nBytes == 4) {
509 writeInt(0);
510 } else if (nBytes < 4) {
511 for (int i = nBytes; i > 0; i --) {
512 writeByte((byte) 0);
513 }
514 } else {
515 writeInt(0);
516 for (int i = nBytes - 4; i > 0; i --) {
517 writeByte((byte) 0);
518 }
519 }
520 }
521
522 public ChannelBuffer copy() {
523 return copy(readerIndex, readableBytes());
524 }
525
526 public ChannelBuffer slice() {
527 return slice(readerIndex, readableBytes());
528 }
529
530 public ByteBuffer toByteBuffer() {
531 return toByteBuffer(readerIndex, readableBytes());
532 }
533
534 public ByteBuffer[] toByteBuffers() {
535 return toByteBuffers(readerIndex, readableBytes());
536 }
537
538 public ByteBuffer[] toByteBuffers(int index, int length) {
539 return new ByteBuffer[] { toByteBuffer(index, length) };
540 }
541
542 public String toString(Charset charset) {
543 return toString(readerIndex, readableBytes(), charset);
544 }
545
546 public String toString(int index, int length, Charset charset) {
547 if (length == 0) {
548 return "";
549 }
550
551 return ChannelBuffers.decodeString(
552 toByteBuffer(index, length), charset);
553 }
554
555 @Deprecated
556 public String toString(int index, int length, String charsetName,
557 ChannelBufferIndexFinder terminatorFinder) {
558 if (terminatorFinder == null) {
559 return toString(index, length, charsetName);
560 }
561
562 int terminatorIndex = indexOf(index, index + length, terminatorFinder);
563 if (terminatorIndex < 0) {
564 return toString(index, length, charsetName);
565 }
566
567 return toString(index, terminatorIndex - index, charsetName);
568 }
569
570 @Deprecated
571 public String toString(int index, int length, String charsetName) {
572 return toString(index, length, Charset.forName(charsetName));
573 }
574
575 @Deprecated
576 public String toString(String charsetName,
577 ChannelBufferIndexFinder terminatorFinder) {
578 return toString(readerIndex, readableBytes(), charsetName, terminatorFinder);
579 }
580
581 @Deprecated
582 public String toString(String charsetName) {
583 return toString(Charset.forName(charsetName));
584 }
585
586 public int indexOf(int fromIndex, int toIndex, byte value) {
587 return ChannelBuffers.indexOf(this, fromIndex, toIndex, value);
588 }
589
590 public int indexOf(int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
591 return ChannelBuffers.indexOf(this, fromIndex, toIndex, indexFinder);
592 }
593
594 public int bytesBefore(byte value) {
595 return bytesBefore(readerIndex(), readableBytes(), value);
596 }
597
598 public int bytesBefore(ChannelBufferIndexFinder indexFinder) {
599 return bytesBefore(readerIndex(), readableBytes(), indexFinder);
600 }
601
602 public int bytesBefore(int length, byte value) {
603 checkReadableBytes(length);
604 return bytesBefore(readerIndex(), length, value);
605 }
606
607 public int bytesBefore(int length, ChannelBufferIndexFinder indexFinder) {
608 checkReadableBytes(length);
609 return bytesBefore(readerIndex(), length, indexFinder);
610 }
611
612 public int bytesBefore(int index, int length, byte value) {
613 if (index < 0 || length < 0 || index + length > capacity()) {
614 throw new IndexOutOfBoundsException();
615 }
616 int endIndex = indexOf(index, index + length, value);
617 if (endIndex < 0) {
618 return -1;
619 }
620 return endIndex - index;
621 }
622
623 public int bytesBefore(int index, int length,
624 ChannelBufferIndexFinder indexFinder) {
625 if (index < 0 || length < 0 || index + length > capacity()) {
626 throw new IndexOutOfBoundsException();
627 }
628 int endIndex = indexOf(index, index + length, indexFinder);
629 if (endIndex < 0) {
630 return -1;
631 }
632 return endIndex - index;
633 }
634
635 @Override
636 public int hashCode() {
637 return ChannelBuffers.hashCode(this);
638 }
639
640 @Override
641 public boolean equals(Object o) {
642 if (!(o instanceof ChannelBuffer)) {
643 return false;
644 }
645 return ChannelBuffers.equals(this, (ChannelBuffer) o);
646 }
647
648 public int compareTo(ChannelBuffer that) {
649 return ChannelBuffers.compare(this, that);
650 }
651
652 @Override
653 public String toString() {
654 return getClass().getSimpleName() + '(' +
655 "ridx=" + readerIndex + ", " +
656 "widx=" + writerIndex + ", " +
657 "cap=" + capacity() +
658 ')';
659 }
660
661
662
663
664
665
666 protected void checkReadableBytes(int minimumReadableBytes) {
667 if (readableBytes() < minimumReadableBytes) {
668 throw new IndexOutOfBoundsException("Not enough readable bytes - Need "
669 + minimumReadableBytes + ", maximum is " + readableBytes());
670 }
671 }
672 }