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 /** 069 * @return the underlying data array 070 */ 071 public byte[] getRawData() { 072 return buf; 073 } 074 075 /** 076 * reset the <code>StoreByteArrayInputStream</code> to use an new byte 077 * array 078 * 079 * @param newBuff 080 */ 081 public void restart(byte[] newBuff) { 082 buf = newBuff; 083 pos = 0; 084 } 085 086 /** 087 * reset the <code>StoreByteArrayInputStream</code> to use an new 088 * ByteSequence 089 * 090 * @param sequence 091 */ 092 public void restart(ByteSequence sequence) { 093 this.buf = sequence.getData(); 094 this.pos = sequence.getOffset(); 095 } 096 097 /** 098 * re-start the input stream - reusing the current buffer 099 * 100 * @param size 101 */ 102 public void restart(int size) { 103 if (buf == null || buf.length < size) { 104 buf = new byte[size]; 105 } 106 restart(buf); 107 } 108 109 /** 110 * Reads the next byte of data from this input stream. The value byte is 111 * returned as an <code>int</code> in the range <code>0</code> to 112 * <code>255</code>. If no byte is available because the end of the 113 * stream has been reached, the value <code>-1</code> is returned. 114 * <p> 115 * This <code>read</code> method cannot block. 116 * 117 * @return the next byte of data, or <code>-1</code> if the end of the 118 * stream has been reached. 119 */ 120 public int read() { 121 return (pos < buf.length) ? (buf[pos++] & 0xff) : -1; 122 } 123 124 public int readOrIOException() throws IOException { 125 int rc = read(); 126 if( rc == -1 ) { 127 throw new EOFException(); 128 } 129 return rc; 130 } 131 132 /** 133 * Reads up to <code>len</code> bytes of data into an array of bytes from 134 * this input stream. 135 * 136 * @param b the buffer into which the data is read. 137 * @param off the start offset of the data. 138 * @param len the maximum number of bytes read. 139 * @return the total number of bytes read into the buffer, or 140 * <code>-1</code> if there is no more data because the end of the 141 * stream has been reached. 142 */ 143 public int read(byte b[], int off, int len) { 144 if (b == null) { 145 throw new NullPointerException(); 146 } 147 if (pos >= buf.length) { 148 return -1; 149 } 150 if (pos + len > buf.length) { 151 len = buf.length - pos; 152 } 153 if (len <= 0) { 154 return 0; 155 } 156 System.arraycopy(buf, pos, b, off, len); 157 pos += len; 158 return len; 159 } 160 161 /** 162 * @return the number of bytes that can be read from the input stream 163 * without blocking. 164 */ 165 public int available() { 166 return buf.length - pos; 167 } 168 169 public void readFully(byte[] b) { 170 read(b, 0, b.length); 171 } 172 173 public void readFully(byte[] b, int off, int len) { 174 read(b, off, len); 175 } 176 177 public int skipBytes(int n) { 178 if (pos + n > buf.length) { 179 n = buf.length - pos; 180 } 181 if (n < 0) { 182 return 0; 183 } 184 pos += n; 185 return n; 186 } 187 188 public boolean readBoolean() throws IOException { 189 return readOrIOException() != 0; 190 } 191 192 public byte readByte() throws IOException { 193 return (byte)readOrIOException(); 194 } 195 196 public int readUnsignedByte() throws IOException { 197 return readOrIOException(); 198 } 199 200 public short readShort() throws IOException { 201 int ch1 = readOrIOException(); 202 int ch2 = readOrIOException(); 203 return (short)((ch1 << 8) + (ch2 << 0)); 204 } 205 206 public int readUnsignedShort() throws IOException { 207 int ch1 = readOrIOException(); 208 int ch2 = readOrIOException(); 209 return (ch1 << 8) + (ch2 << 0); 210 } 211 212 public char readChar() throws IOException { 213 int ch1 = readOrIOException(); 214 int ch2 = readOrIOException(); 215 return (char)((ch1 << 8) + (ch2 << 0)); 216 } 217 218 public int readInt() throws IOException { 219 int ch1 = readOrIOException(); 220 int ch2 = readOrIOException(); 221 int ch3 = readOrIOException(); 222 int ch4 = readOrIOException(); 223 return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0); 224 } 225 226 public long readLong() throws IOException { 227 if (pos >= buf.length ) { 228 throw new EOFException(); 229 } 230 long rc = ((long)buf[pos++] << 56) + ((long)(buf[pos++] & 255) << 48) + ((long)(buf[pos++] & 255) << 40) + ((long)(buf[pos++] & 255) << 32); 231 return rc + ((long)(buf[pos++] & 255) << 24) + ((buf[pos++] & 255) << 16) + ((buf[pos++] & 255) << 8) + ((buf[pos++] & 255) << 0); 232 } 233 234 public float readFloat() throws IOException { 235 return Float.intBitsToFloat(readInt()); 236 } 237 238 public double readDouble() throws IOException { 239 return Double.longBitsToDouble(readLong()); 240 } 241 242 public String readLine() { 243 int start = pos; 244 while (pos < buf.length) { 245 int c = read(); 246 if (c == '\n') { 247 break; 248 } 249 if (c == '\r') { 250 c = read(); 251 if (c != '\n' && c != -1) { 252 pos--; 253 } 254 break; 255 } 256 } 257 return new String(buf, start, pos); 258 } 259 260 public String readUTF() throws IOException { 261 int length = readUnsignedShort(); 262 if (pos + length > buf.length) { 263 throw new UTFDataFormatException("bad string"); 264 } 265 char chararr[] = new char[length]; 266 String result = MarshallingSupport.convertUTF8WithBuf(buf, chararr, pos, length); 267 pos += length; 268 return result; 269 } 270}