001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.util; 018 019import java.io.*; 020 021/** 022 * Optimized ByteArrayInputStream that can be used more than once 023 * 024 * 025 */ 026public final class DataByteArrayInputStream extends InputStream implements DataInput { 027 private byte[] buf; 028 private int pos; 029 private int offset; 030 031 /** 032 * Creates a <code>StoreByteArrayInputStream</code>. 033 * 034 * @param buf the input buffer. 035 */ 036 public DataByteArrayInputStream(byte buf[]) { 037 this.buf = buf; 038 this.pos = 0; 039 this.offset = 0; 040 } 041 042 /** 043 * Creates a <code>StoreByteArrayInputStream</code>. 044 * 045 * @param sequence the input buffer. 046 */ 047 public DataByteArrayInputStream(ByteSequence sequence) { 048 this.buf = sequence.getData(); 049 this.offset = sequence.getOffset(); 050 this.pos = this.offset; 051 } 052 053 /** 054 * Creates <code>WireByteArrayInputStream</code> with a minmalist byte 055 * array 056 */ 057 public DataByteArrayInputStream() { 058 this(new byte[0]); 059 } 060 061 /** 062 * @return the size 063 */ 064 public int size() { 065 return pos - offset; 066 } 067 068 public int position() { return pos; } 069 070 /** 071 * @return the underlying data array 072 */ 073 public byte[] getRawData() { 074 return buf; 075 } 076 077 /** 078 * reset the <code>StoreByteArrayInputStream</code> to use an new byte 079 * array 080 * 081 * @param newBuff 082 */ 083 public void restart(byte[] newBuff) { 084 buf = newBuff; 085 pos = 0; 086 } 087 088 /** 089 * reset the <code>StoreByteArrayInputStream</code> to use an new 090 * ByteSequence 091 * 092 * @param sequence 093 */ 094 public void restart(ByteSequence sequence) { 095 this.buf = sequence.getData(); 096 this.pos = sequence.getOffset(); 097 } 098 099 /** 100 * re-start the input stream - reusing the current buffer 101 * 102 * @param size 103 */ 104 public void restart(int size) { 105 if (buf == null || buf.length < size) { 106 buf = new byte[size]; 107 } 108 restart(buf); 109 } 110 111 /** 112 * Reads the next byte of data from this input stream. The value byte is 113 * returned as an <code>int</code> in the range <code>0</code> to 114 * <code>255</code>. If no byte is available because the end of the 115 * stream has been reached, the value <code>-1</code> is returned. 116 * <p> 117 * This <code>read</code> method cannot block. 118 * 119 * @return the next byte of data, or <code>-1</code> if the end of the 120 * stream has been reached. 121 */ 122 public int read() { 123 return (pos < buf.length) ? (buf[pos++] & 0xff) : -1; 124 } 125 126 public int readOrIOException() throws IOException { 127 int rc = read(); 128 if( rc == -1 ) { 129 throw new EOFException(); 130 } 131 return rc; 132 } 133 134 /** 135 * Reads up to <code>len</code> bytes of data into an array of bytes from 136 * this input stream. 137 * 138 * @param b the buffer into which the data is read. 139 * @param off the start offset of the data. 140 * @param len the maximum number of bytes read. 141 * @return the total number of bytes read into the buffer, or 142 * <code>-1</code> if there is no more data because the end of the 143 * stream has been reached. 144 */ 145 public int read(byte b[], int off, int len) { 146 if (b == null) { 147 throw new NullPointerException(); 148 } 149 if (pos >= buf.length) { 150 return -1; 151 } 152 if (pos + len > buf.length) { 153 len = buf.length - pos; 154 } 155 if (len <= 0) { 156 return 0; 157 } 158 System.arraycopy(buf, pos, b, off, len); 159 pos += len; 160 return len; 161 } 162 163 /** 164 * @return the number of bytes that can be read from the input stream 165 * without blocking. 166 */ 167 public int available() { 168 return buf.length - pos; 169 } 170 171 public void readFully(byte[] b) { 172 read(b, 0, b.length); 173 } 174 175 public void readFully(byte[] b, int off, int len) { 176 read(b, off, len); 177 } 178 179 public int skipBytes(int n) { 180 if (pos + n > buf.length) { 181 n = buf.length - pos; 182 } 183 if (n < 0) { 184 return 0; 185 } 186 pos += n; 187 return n; 188 } 189 190 public boolean readBoolean() throws IOException { 191 return readOrIOException() != 0; 192 } 193 194 public byte readByte() throws IOException { 195 return (byte)readOrIOException(); 196 } 197 198 public int readUnsignedByte() throws IOException { 199 return readOrIOException(); 200 } 201 202 public short readShort() throws IOException { 203 int ch1 = readOrIOException(); 204 int ch2 = readOrIOException(); 205 return (short)((ch1 << 8) + (ch2 << 0)); 206 } 207 208 public int readUnsignedShort() throws IOException { 209 int ch1 = readOrIOException(); 210 int ch2 = readOrIOException(); 211 return (ch1 << 8) + (ch2 << 0); 212 } 213 214 public char readChar() throws IOException { 215 int ch1 = readOrIOException(); 216 int ch2 = readOrIOException(); 217 return (char)((ch1 << 8) + (ch2 << 0)); 218 } 219 220 public int readInt() throws IOException { 221 int ch1 = readOrIOException(); 222 int ch2 = readOrIOException(); 223 int ch3 = readOrIOException(); 224 int ch4 = readOrIOException(); 225 return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0); 226 } 227 228 public long readLong() throws IOException { 229 if (pos + 8 > buf.length ) { 230 throw new EOFException(); 231 } 232 long rc = ((long)buf[pos++] << 56) + ((long)(buf[pos++] & 255) << 48) + ((long)(buf[pos++] & 255) << 40) + ((long)(buf[pos++] & 255) << 32); 233 return rc + ((long)(buf[pos++] & 255) << 24) + ((buf[pos++] & 255) << 16) + ((buf[pos++] & 255) << 8) + ((buf[pos++] & 255) << 0); 234 } 235 236 public float readFloat() throws IOException { 237 return Float.intBitsToFloat(readInt()); 238 } 239 240 public double readDouble() throws IOException { 241 return Double.longBitsToDouble(readLong()); 242 } 243 244 public String readLine() { 245 int start = pos; 246 while (pos < buf.length) { 247 int c = read(); 248 if (c == '\n') { 249 break; 250 } 251 if (c == '\r') { 252 c = read(); 253 if (c != '\n' && c != -1) { 254 pos--; 255 } 256 break; 257 } 258 } 259 return new String(buf, start, pos); 260 } 261 262 public String readUTF() throws IOException { 263 int length = readUnsignedShort(); 264 if (pos + length > buf.length) { 265 throw new UTFDataFormatException("bad string"); 266 } 267 char chararr[] = new char[length]; 268 String result = MarshallingSupport.convertUTF8WithBuf(buf, chararr, pos, length); 269 pos += length; 270 return result; 271 } 272}