001    /*
002     * Copyright (C) 2008  Trustin Heuiseung Lee
003     *
004     * This library is free software; you can redistribute it and/or
005     * modify it under the terms of the GNU Lesser General Public
006     * License as published by the Free Software Foundation; either
007     * version 2.1 of the License, or (at your option) any later version.
008     *
009     * This library is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this library; if not, write to the Free Software
016     * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
017     */
018    package net.gleamynode.netty.buffer;
019    
020    import java.io.DataInput;
021    import java.io.DataInputStream;
022    import java.io.EOFException;
023    import java.io.IOException;
024    import java.io.InputStream;
025    
026    /**
027     *
028     * @author The Netty Project (netty@googlegroups.com)
029     * @author Trustin Lee (trustin@gmail.com)
030     *
031     * @version $Rev$, $Date$
032     *
033     * @see ChannelBufferOutputStream
034     * @apiviz.uses net.gleamynode.netty.buffer.ChannelBuffer
035     */
036    public class ChannelBufferInputStream extends InputStream implements DataInput {
037    
038        private final ChannelBuffer buffer;
039        private final int startIndex;
040        private final int endIndex;
041    
042        public ChannelBufferInputStream(ChannelBuffer buffer) {
043            this(buffer, buffer.readableBytes());
044        }
045    
046        public ChannelBufferInputStream(ChannelBuffer buffer, int length) {
047            if (buffer == null) {
048                throw new NullPointerException("buffer");
049            }
050            if (length > buffer.readableBytes()) {
051                throw new IndexOutOfBoundsException();
052            }
053    
054            this.buffer = buffer;
055            startIndex = buffer.readerIndex();
056            endIndex = startIndex + length;
057            buffer.markReaderIndex();
058        }
059    
060        public int readBytes() {
061            return buffer.readerIndex() - startIndex;
062        }
063    
064        @Override
065        public int available() throws IOException {
066            return endIndex - buffer.readerIndex();
067        }
068    
069        @Override
070        public void mark(int readlimit) {
071            buffer.markReaderIndex();
072        }
073    
074        @Override
075        public boolean markSupported() {
076            return true;
077        }
078    
079        @Override
080        public int read() throws IOException {
081            if (!buffer.readable()) {
082                return -1;
083            }
084            return buffer.readByte() & 0xff;
085        }
086    
087        @Override
088        public int read(byte[] b, int off, int len) throws IOException {
089            int available = available();
090            if (available == 0) {
091                return -1;
092            }
093    
094            len = Math.min(available, len);
095            buffer.readBytes(b, off, len);
096            return len;
097        }
098    
099        @Override
100        public void reset() throws IOException {
101            buffer.resetReaderIndex();
102        }
103    
104        @Override
105        public long skip(long n) throws IOException {
106            if (n > Integer.MAX_VALUE) {
107                return skipBytes(Integer.MAX_VALUE);
108            } else {
109                return skipBytes((int) n);
110            }
111        }
112    
113        public boolean readBoolean() throws IOException {
114            int b = read();
115            if (b < 0) {
116                throw new EOFException();
117            }
118            return b != 0;
119        }
120    
121        public byte readByte() throws IOException {
122            if (!buffer.readable()) {
123                throw new EOFException();
124            }
125            return buffer.readByte();
126        }
127    
128        public char readChar() throws IOException {
129            return (char) readShort();
130        }
131    
132        public double readDouble() throws IOException {
133            return Double.longBitsToDouble(readLong());
134        }
135    
136        public float readFloat() throws IOException {
137            return Float.intBitsToFloat(readInt());
138        }
139    
140        public void readFully(byte[] b) throws IOException {
141            readFully(b, 0, b.length);
142        }
143    
144        public void readFully(byte[] b, int off, int len) throws IOException {
145            checkAvailable(len);
146            buffer.readBytes(b, off, len);
147        }
148    
149        public int readInt() throws IOException {
150            checkAvailable(4);
151            return buffer.readInt();
152        }
153    
154        private final StringBuilder lineBuf = new StringBuilder();
155    
156        public String readLine() throws IOException {
157            lineBuf.setLength(0);
158            for (;;) {
159                int b = read();
160                if (b < 0 || b == '\n') {
161                    break;
162                }
163    
164                lineBuf.append((char) b);
165            }
166    
167            while (lineBuf.charAt(lineBuf.length() - 1) == '\r') {
168                lineBuf.setLength(lineBuf.length() - 1);
169            }
170    
171            return lineBuf.toString();
172        }
173    
174        public long readLong() throws IOException {
175            checkAvailable(8);
176            return buffer.readLong();
177        }
178    
179        public short readShort() throws IOException {
180            checkAvailable(2);
181            return buffer.readShort();
182        }
183    
184        public String readUTF() throws IOException {
185            return DataInputStream.readUTF(this);
186        }
187    
188        public int readUnsignedByte() throws IOException {
189            return readByte() & 0xff;
190        }
191    
192        public int readUnsignedShort() throws IOException {
193            return readShort() & 0xffff;
194        }
195    
196        public int skipBytes(int n) throws IOException {
197            int nBytes = Math.min(available(), n);
198            buffer.skipBytes(n);
199            return nBytes;
200        }
201    
202        private void checkAvailable(int fieldSize) throws IOException {
203            if (fieldSize < 0) {
204                throw new IllegalArgumentException();
205            }
206            if (fieldSize > available()) {
207                throw new EOFException();
208            }
209        }
210    }