View Javadoc

    1   /*
    2    * Copyright 2009 Red Hat, Inc.
    3    *
    4    * Red Hat licenses this file to you under the Apache License, version 2.0
    5    * (the "License"); you may not use this file except in compliance with the
    6    * 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.DataInput;
    19  import java.io.DataInputStream;
    20  import java.io.EOFException;
    21  import java.io.IOException;
    22  import java.io.InputStream;
    23
    24  /**
    25   * An {@link InputStream} which reads data from a {@link ChannelBuffer}.
    26   * <p>
    27   * A read operation against this stream will occur at the {@code readerIndex}
    28   * of its underlying buffer and the {@code readerIndex} will increase during
    29   * the read operation.
    30   * <p>
    31   * This stream implements {@link DataInput} for your convenience.
    32   * The endianness of the stream is not always big endian but depends on
    33   * the endianness of the underlying buffer.
    34   *
    35   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
    36   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
    37   *
    38   * @version $Rev: 2080 $, $Date: 2010-01-26 18:04:19 +0900 (Tue, 26 Jan 2010) $
    39   *
    40   * @see ChannelBufferOutputStream
    41   * @apiviz.uses org.jboss.netty.buffer.ChannelBuffer
    42   */
    43  public class ChannelBufferInputStream extends InputStream implements DataInput {
    44
    45      private final ChannelBuffer buffer;
    46      private final int startIndex;
    47      private final int endIndex;
    48
    49      /**
    50       * Creates a new stream which reads data from the specified {@code buffer}
    51       * starting at the current {@code readerIndex} and ending at the current
    52       * {@code writerIndex}.
    53       */
    54      public ChannelBufferInputStream(ChannelBuffer buffer) {
    55          this(buffer, buffer.readableBytes());
    56      }
    57
    58      /**
    59       * Creates a new stream which reads data from the specified {@code buffer}
    60       * starting at the current {@code readerIndex} and ending at
    61       * {@code readerIndex + length}.
    62       *
    63       * @throws IndexOutOfBoundsException
    64       *         if {@code readerIndex + length} is greater than
    65       *            {@code writerIndex}
    66       */
    67      public ChannelBufferInputStream(ChannelBuffer buffer, int length) {
    68          if (buffer == null) {
    69              throw new NullPointerException("buffer");
    70          }
    71          if (length < 0) {
    72              throw new IllegalArgumentException("length: " + length);
    73          }
    74          if (length > buffer.readableBytes()) {
    75              throw new IndexOutOfBoundsException();
    76          }
    77
    78          this.buffer = buffer;
    79          startIndex = buffer.readerIndex();
    80          endIndex = startIndex + length;
    81          buffer.markReaderIndex();
    82      }
    83
    84      /**
    85       * Returns the number of read bytes by this stream so far.
    86       */
    87      public int readBytes() {
    88          return buffer.readerIndex() - startIndex;
    89      }
    90
    91      @Override
    92      public int available() throws IOException {
    93          return endIndex - buffer.readerIndex();
    94      }
    95
    96      @Override
    97      public void mark(int readlimit) {
    98          buffer.markReaderIndex();
    99      }
    100
    101     @Override
    102     public boolean markSupported() {
    103         return true;
    104     }
    105
    106     @Override
    107     public int read() throws IOException {
    108         if (!buffer.readable()) {
    109             return -1;
    110         }
    111         return buffer.readByte() & 0xff;
    112     }
    113
    114     @Override
    115     public int read(byte[] b, int off, int len) throws IOException {
    116         int available = available();
    117         if (available == 0) {
    118             return -1;
    119         }
    120
    121         len = Math.min(available, len);
    122         buffer.readBytes(b, off, len);
    123         return len;
    124     }
    125
    126     @Override
    127     public void reset() throws IOException {
    128         buffer.resetReaderIndex();
    129     }
    130
    131     @Override
    132     public long skip(long n) throws IOException {
    133         if (n > Integer.MAX_VALUE) {
    134             return skipBytes(Integer.MAX_VALUE);
    135         } else {
    136             return skipBytes((int) n);
    137         }
    138     }
    139
    140     public boolean readBoolean() throws IOException {
    141         checkAvailable(1);
    142         return read() != 0;
    143     }
    144
    145     public byte readByte() throws IOException {
    146         if (!buffer.readable()) {
    147             throw new EOFException();
    148         }
    149         return buffer.readByte();
    150     }
    151
    152     public char readChar() throws IOException {
    153         return (char) readShort();
    154     }
    155
    156     public double readDouble() throws IOException {
    157         return Double.longBitsToDouble(readLong());
    158     }
    159
    160     public float readFloat() throws IOException {
    161         return Float.intBitsToFloat(readInt());
    162     }
    163
    164     public void readFully(byte[] b) throws IOException {
    165         readFully(b, 0, b.length);
    166     }
    167
    168     public void readFully(byte[] b, int off, int len) throws IOException {
    169         checkAvailable(len);
    170         buffer.readBytes(b, off, len);
    171     }
    172
    173     public int readInt() throws IOException {
    174         checkAvailable(4);
    175         return buffer.readInt();
    176     }
    177
    178     private final StringBuilder lineBuf = new StringBuilder();
    179
    180     public String readLine() throws IOException {
    181         lineBuf.setLength(0);
    182         for (;;) {
    183             int b = read();
    184             if (b < 0 || b == '\n') {
    185                 break;
    186             }
    187
    188             lineBuf.append((char) b);
    189         }
    190
    191         while (lineBuf.charAt(lineBuf.length() - 1) == '\r') {
    192             lineBuf.setLength(lineBuf.length() - 1);
    193         }
    194
    195         return lineBuf.toString();
    196     }
    197
    198     public long readLong() throws IOException {
    199         checkAvailable(8);
    200         return buffer.readLong();
    201     }
    202
    203     public short readShort() throws IOException {
    204         checkAvailable(2);
    205         return buffer.readShort();
    206     }
    207
    208     public String readUTF() throws IOException {
    209         return DataInputStream.readUTF(this);
    210     }
    211
    212     public int readUnsignedByte() throws IOException {
    213         return readByte() & 0xff;
    214     }
    215
    216     public int readUnsignedShort() throws IOException {
    217         return readShort() & 0xffff;
    218     }
    219
    220     public int skipBytes(int n) throws IOException {
    221         int nBytes = Math.min(available(), n);
    222         buffer.skipBytes(nBytes);
    223         return nBytes;
    224     }
    225
    226     private void checkAvailable(int fieldSize) throws IOException {
    227         if (fieldSize < 0) {
    228             throw new IndexOutOfBoundsException();
    229         }
    230         if (fieldSize > available()) {
    231             throw new EOFException();
    232         }
    233     }
    234 }