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     public ChannelBuffer readSlice(int length) {
314         ChannelBuffer slice = slice(readerIndex, length);
315         readerIndex += length;
316         return slice;
317     }
318 
319     public void readBytes(byte[] dst, int dstIndex, int length) {
320         checkReadableBytes(length);
321         getBytes(readerIndex, dst, dstIndex, length);
322         readerIndex += length;
323     }
324 
325     public void readBytes(byte[] dst) {
326         readBytes(dst, 0, dst.length);
327     }
328 
329     public void readBytes(ChannelBuffer dst) {
330         readBytes(dst, dst.writableBytes());
331     }
332 
333     public void readBytes(ChannelBuffer dst, int length) {
334         if (length > dst.writableBytes()) {
335             throw new IndexOutOfBoundsException("Too many bytes to be read: Need "
336                     + length + ", maximum is " + dst.writableBytes());
337         }
338         readBytes(dst, dst.writerIndex(), length);
339         dst.writerIndex(dst.writerIndex() + length);
340     }
341 
342     public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
343         checkReadableBytes(length);
344         getBytes(readerIndex, dst, dstIndex, length);
345         readerIndex += length;
346     }
347 
348     public void readBytes(ByteBuffer dst) {
349         int length = dst.remaining();
350         checkReadableBytes(length);
351         getBytes(readerIndex, dst);
352         readerIndex += length;
353     }
354 
355     public int readBytes(GatheringByteChannel out, int length)
356             throws IOException {
357         checkReadableBytes(length);
358         int readBytes = getBytes(readerIndex, out, length);
359         readerIndex += readBytes;
360         return readBytes;
361     }
362 
363     public void readBytes(OutputStream out, int length) throws IOException {
364         checkReadableBytes(length);
365         getBytes(readerIndex, out, length);
366         readerIndex += length;
367     }
368 
369     public void skipBytes(int length) {
370         int newReaderIndex = readerIndex + length;
371         if (newReaderIndex > writerIndex) {
372             throw new IndexOutOfBoundsException("Readable bytes exceeded - Need "
373                     + newReaderIndex + ", maximum is " + writerIndex);
374         }
375         readerIndex = newReaderIndex;
376     }
377 
378     public void writeByte(int value) {
379         setByte(writerIndex, value);
380         writerIndex++;
381     }
382 
383     public void writeShort(int value) {
384         setShort(writerIndex, value);
385         writerIndex += 2;
386     }
387 
388     public void writeMedium(int value) {
389         setMedium(writerIndex, value);
390         writerIndex += 3;
391     }
392 
393     public void writeInt(int value) {
394         setInt(writerIndex, value);
395         writerIndex += 4;
396     }
397 
398     public void writeLong(long value) {
399         setLong(writerIndex, value);
400         writerIndex += 8;
401     }
402 
403     public void writeChar(int value) {
404         writeShort(value);
405     }
406 
407     public void writeFloat(float value) {
408         writeInt(Float.floatToRawIntBits(value));
409     }
410 
411     public void writeDouble(double value) {
412         writeLong(Double.doubleToRawLongBits(value));
413     }
414 
415     public void writeBytes(byte[] src, int srcIndex, int length) {
416         setBytes(writerIndex, src, srcIndex, length);
417         writerIndex += length;
418     }
419 
420     public void writeBytes(byte[] src) {
421         writeBytes(src, 0, src.length);
422     }
423 
424     public void writeBytes(ChannelBuffer src) {
425         writeBytes(src, src.readableBytes());
426     }
427 
428     public void writeBytes(ChannelBuffer src, int length) {
429         if (length > src.readableBytes()) {
430             throw new IndexOutOfBoundsException("Too many bytes to write - Need "
431                     + length + ", maximum is " + src.readableBytes());
432         }
433         writeBytes(src, src.readerIndex(), length);
434         src.readerIndex(src.readerIndex() + length);
435     }
436 
437     public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
438         setBytes(writerIndex, src, srcIndex, length);
439         writerIndex += length;
440     }
441 
442     public void writeBytes(ByteBuffer src) {
443         int length = src.remaining();
444         setBytes(writerIndex, src);
445         writerIndex += length;
446     }
447 
448     public int writeBytes(InputStream in, int length)
449             throws IOException {
450         int writtenBytes = setBytes(writerIndex, in, length);
451         if (writtenBytes > 0) {
452             writerIndex += writtenBytes;
453         }
454         return writtenBytes;
455     }
456 
457     public int writeBytes(ScatteringByteChannel in, int length)
458             throws IOException {
459         int writtenBytes = setBytes(writerIndex, in, length);
460         if (writtenBytes > 0) {
461             writerIndex += writtenBytes;
462         }
463         return writtenBytes;
464     }
465 
466     public void writeZero(int length) {
467         if (length == 0) {
468             return;
469         }
470         if (length < 0) {
471             throw new IllegalArgumentException(
472                     "length must be 0 or greater than 0.");
473         }
474         int nLong = length >>> 3;
475         int nBytes = length & 7;
476         for (int i = nLong; i > 0; i --) {
477             writeLong(0);
478         }
479         if (nBytes == 4) {
480             writeInt(0);
481         } else if (nBytes < 4) {
482             for (int i = nBytes; i > 0; i --) {
483                 writeByte((byte) 0);
484             }
485         } else {
486             writeInt(0);
487             for (int i = nBytes - 4; i > 0; i --) {
488                 writeByte((byte) 0);
489             }
490         }
491     }
492 
493     public ChannelBuffer copy() {
494         return copy(readerIndex, readableBytes());
495     }
496 
497     public ChannelBuffer slice() {
498         return slice(readerIndex, readableBytes());
499     }
500 
501     public ByteBuffer toByteBuffer() {
502         return toByteBuffer(readerIndex, readableBytes());
503     }
504 
505     public ByteBuffer[] toByteBuffers() {
506         return toByteBuffers(readerIndex, readableBytes());
507     }
508 
509     public ByteBuffer[] toByteBuffers(int index, int length) {
510         return new ByteBuffer[] { toByteBuffer(index, length) };
511     }
512 
513     public String toString(Charset charset) {
514         return toString(readerIndex, readableBytes(), charset);
515     }
516 
517     public String toString(int index, int length, Charset charset) {
518         if (length == 0) {
519             return "";
520         }
521 
522         return ChannelBuffers.decodeString(
523                 toByteBuffer(index, length), charset);
524     }
525 
526     public int indexOf(int fromIndex, int toIndex, byte value) {
527         return ChannelBuffers.indexOf(this, fromIndex, toIndex, value);
528     }
529 
530     public int indexOf(int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
531         return ChannelBuffers.indexOf(this, fromIndex, toIndex, indexFinder);
532     }
533 
534     public int bytesBefore(byte value) {
535         return bytesBefore(readerIndex(), readableBytes(), value);
536     }
537 
538     public int bytesBefore(ChannelBufferIndexFinder indexFinder) {
539         return bytesBefore(readerIndex(), readableBytes(), indexFinder);
540     }
541 
542     public int bytesBefore(int length, byte value) {
543         checkReadableBytes(length);
544         return bytesBefore(readerIndex(), length, value);
545     }
546 
547     public int bytesBefore(int length, ChannelBufferIndexFinder indexFinder) {
548         checkReadableBytes(length);
549         return bytesBefore(readerIndex(), length, indexFinder);
550     }
551 
552     public int bytesBefore(int index, int length, byte value) {
553         if (index < 0 || length < 0 || index + length > capacity()) {
554             throw new IndexOutOfBoundsException();
555         }
556         int endIndex = indexOf(index, index + length, value);
557         if (endIndex < 0) {
558             return -1;
559         }
560         return endIndex - index;
561     }
562 
563     public int bytesBefore(int index, int length,
564             ChannelBufferIndexFinder indexFinder) {
565         if (index < 0 || length < 0 || index + length > capacity()) {
566             throw new IndexOutOfBoundsException();
567         }
568         int endIndex = indexOf(index, index + length, indexFinder);
569         if (endIndex < 0) {
570             return -1;
571         }
572         return endIndex - index;
573     }
574 
575     @Override
576     public int hashCode() {
577         return ChannelBuffers.hashCode(this);
578     }
579 
580     @Override
581     public boolean equals(Object o) {
582         if (!(o instanceof ChannelBuffer)) {
583             return false;
584         }
585         return ChannelBuffers.equals(this, (ChannelBuffer) o);
586     }
587 
588     public int compareTo(ChannelBuffer that) {
589         return ChannelBuffers.compare(this, that);
590     }
591 
592     @Override
593     public String toString() {
594         return getClass().getSimpleName() + '(' +
595                "ridx=" + readerIndex + ", " +
596                "widx=" + writerIndex + ", " +
597                "cap=" + capacity() +
598                ')';
599     }
600 
601     /**
602      * Throws an {@link IndexOutOfBoundsException} if the current
603      * {@linkplain #readableBytes() readable bytes} of this buffer is less
604      * than the specified value.
605      */
606     protected void checkReadableBytes(int minimumReadableBytes) {
607         if (readableBytes() < minimumReadableBytes) {
608             throw new IndexOutOfBoundsException("Not enough readable bytes - Need "
609                     + minimumReadableBytes + ", maximum is " + readableBytes());
610         }
611     }
612 }