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 }