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         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      * Throws an {@link IndexOutOfBoundsException} if the current
663      * {@linkplain #readableBytes() readable bytes} of this buffer is less
664      * than the specified value.
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 }