View Javadoc

1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package 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   * A skeletal implementation of a buffer.
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     }
410 
411     public void writeShort(int value) {
412         setShort(writerIndex, value);
413         writerIndex += 2;
414     }
415 
416     public void writeMedium(int value) {
417         setMedium(writerIndex, value);
418         writerIndex += 3;
419     }
420 
421     public void writeInt(int value) {
422         setInt(writerIndex, value);
423         writerIndex += 4;
424     }
425 
426     public void writeLong(long value) {
427         setLong(writerIndex, value);
428         writerIndex += 8;
429     }
430 
431     public void writeChar(int value) {
432         writeShort(value);
433     }
434 
435     public void writeFloat(float value) {
436         writeInt(Float.floatToRawIntBits(value));
437     }
438 
439     public void writeDouble(double value) {
440         writeLong(Double.doubleToRawLongBits(value));
441     }
442 
443     public void writeBytes(byte[] src, int srcIndex, int length) {
444         setBytes(writerIndex, src, srcIndex, length);
445         writerIndex += length;
446     }
447 
448     public void writeBytes(byte[] src) {
449         writeBytes(src, 0, src.length);
450     }
451 
452     public void writeBytes(ChannelBuffer src) {
453         writeBytes(src, src.readableBytes());
454     }
455 
456     public void writeBytes(ChannelBuffer src, int length) {
457         if (length > src.readableBytes()) {
458             throw new IndexOutOfBoundsException("Too many bytes to write - Need "
459                     + length + ", maximum is " + src.readableBytes());
460         }
461         writeBytes(src, src.readerIndex(), length);
462         src.readerIndex(src.readerIndex() + length);
463     }
464 
465     public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
466         setBytes(writerIndex, src, srcIndex, length);
467         writerIndex += length;
468     }
469 
470     public void writeBytes(ByteBuffer src) {
471         int length = src.remaining();
472         setBytes(writerIndex, src);
473         writerIndex += length;
474     }
475 
476     public int writeBytes(InputStream in, int length)
477             throws IOException {
478         int writtenBytes = setBytes(writerIndex, in, length);
479         if (writtenBytes > 0) {
480             writerIndex += writtenBytes;
481         }
482         return writtenBytes;
483     }
484 
485     public int writeBytes(ScatteringByteChannel in, int length)
486             throws IOException {
487         int writtenBytes = setBytes(writerIndex, in, length);
488         if (writtenBytes > 0) {
489             writerIndex += writtenBytes;
490         }
491         return writtenBytes;
492     }
493 
494     public void writeZero(int length) {
495         if (length == 0) {
496             return;
497         }
498         if (length < 0) {
499             throw new IllegalArgumentException(
500                     "length must be 0 or greater than 0.");
501         }
502         int nLong = length >>> 3;
503         int nBytes = length & 7;
504         for (int i = nLong; i > 0; i --) {
505             writeLong(0);
506         }
507         if (nBytes == 4) {
508             writeInt(0);
509         } else if (nBytes < 4) {
510             for (int i = nBytes; i > 0; i --) {
511                 writeByte((byte) 0);
512             }
513         } else {
514             writeInt(0);
515             for (int i = nBytes - 4; i > 0; i --) {
516                 writeByte((byte) 0);
517             }
518         }
519     }
520 
521     public ChannelBuffer copy() {
522         return copy(readerIndex, readableBytes());
523     }
524 
525     public ChannelBuffer slice() {
526         return slice(readerIndex, readableBytes());
527     }
528 
529     public ByteBuffer toByteBuffer() {
530         return toByteBuffer(readerIndex, readableBytes());
531     }
532 
533     public ByteBuffer[] toByteBuffers() {
534         return toByteBuffers(readerIndex, readableBytes());
535     }
536 
537     public ByteBuffer[] toByteBuffers(int index, int length) {
538         return new ByteBuffer[] { toByteBuffer(index, length) };
539     }
540 
541     public String toString(Charset charset) {
542         return toString(readerIndex, readableBytes(), charset);
543     }
544 
545     public String toString(int index, int length, Charset charset) {
546         if (length == 0) {
547             return "";
548         }
549 
550         return ChannelBuffers.decodeString(
551                 toByteBuffer(index, length), charset);
552     }
553 
554     @Deprecated
555     public String toString(int index, int length, String charsetName,
556             ChannelBufferIndexFinder terminatorFinder) {
557         if (terminatorFinder == null) {
558             return toString(index, length, charsetName);
559         }
560 
561         int terminatorIndex = indexOf(index, index + length, terminatorFinder);
562         if (terminatorIndex < 0) {
563             return toString(index, length, charsetName);
564         }
565 
566         return toString(index, terminatorIndex - index, charsetName);
567     }
568 
569     @Deprecated
570     public String toString(int index, int length, String charsetName) {
571         return toString(index, length, Charset.forName(charsetName));
572     }
573 
574     @Deprecated
575     public String toString(String charsetName,
576             ChannelBufferIndexFinder terminatorFinder) {
577         return toString(readerIndex, readableBytes(), charsetName, terminatorFinder);
578     }
579 
580     @Deprecated
581     public String toString(String charsetName) {
582         return toString(Charset.forName(charsetName));
583     }
584 
585     public int indexOf(int fromIndex, int toIndex, byte value) {
586         return ChannelBuffers.indexOf(this, fromIndex, toIndex, value);
587     }
588 
589     public int indexOf(int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
590         return ChannelBuffers.indexOf(this, fromIndex, toIndex, indexFinder);
591     }
592 
593     public int bytesBefore(byte value) {
594         return bytesBefore(readerIndex(), readableBytes(), value);
595     }
596 
597     public int bytesBefore(ChannelBufferIndexFinder indexFinder) {
598         return bytesBefore(readerIndex(), readableBytes(), indexFinder);
599     }
600 
601     public int bytesBefore(int length, byte value) {
602         checkReadableBytes(length);
603         return bytesBefore(readerIndex(), length, value);
604     }
605 
606     public int bytesBefore(int length, ChannelBufferIndexFinder indexFinder) {
607         checkReadableBytes(length);
608         return bytesBefore(readerIndex(), length, indexFinder);
609     }
610 
611     public int bytesBefore(int index, int length, byte value) {
612         int endIndex = indexOf(index, index + length, value);
613         if (endIndex < 0) {
614             return -1;
615         }
616         return endIndex - index;
617     }
618 
619     public int bytesBefore(int index, int length,
620             ChannelBufferIndexFinder indexFinder) {
621         int endIndex = indexOf(index, index + length, indexFinder);
622         if (endIndex < 0) {
623             return -1;
624         }
625         return endIndex - index;
626     }
627 
628     @Override
629     public int hashCode() {
630         return ChannelBuffers.hashCode(this);
631     }
632 
633     @Override
634     public boolean equals(Object o) {
635         if (!(o instanceof ChannelBuffer)) {
636             return false;
637         }
638         return ChannelBuffers.equals(this, (ChannelBuffer) o);
639     }
640 
641     public int compareTo(ChannelBuffer that) {
642         return ChannelBuffers.compare(this, that);
643     }
644 
645     @Override
646     public String toString() {
647         return getClass().getSimpleName() + '(' +
648                "ridx=" + readerIndex + ", " +
649                "widx=" + writerIndex + ", " +
650                "cap=" + capacity() +
651                ')';
652     }
653 
654     /**
655      * Throws an {@link IndexOutOfBoundsException} if the current
656      * {@linkplain #readableBytes() readable bytes} of this buffer is less
657      * than the specified value.
658      */
659     protected void checkReadableBytes(int minimumReadableBytes) {
660         if (readableBytes() < minimumReadableBytes) {
661             throw new IndexOutOfBoundsException("Not enough readable bytes - Need "
662                     + minimumReadableBytes + ", maximum is " + readableBytes());
663         }
664     }
665 }