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 */ 017 package org.apache.activemq.util; 018 019 import java.io.DataInput; 020 import java.io.IOException; 021 import java.io.InputStream; 022 import java.io.UTFDataFormatException; 023 024 /** 025 * Optimized ByteArrayInputStream that can be used more than once 026 * 027 * @version $Revision: 1.1.1.1 $ 028 */ 029 public final class DataByteArrayInputStream extends InputStream implements DataInput { 030 private byte[] buf; 031 private int pos; 032 private int offset; 033 034 /** 035 * Creates a <code>StoreByteArrayInputStream</code>. 036 * 037 * @param buf the input buffer. 038 */ 039 public DataByteArrayInputStream(byte buf[]) { 040 this.buf = buf; 041 this.pos = 0; 042 this.offset = 0; 043 } 044 045 /** 046 * Creates a <code>StoreByteArrayInputStream</code>. 047 * 048 * @param sequence the input buffer. 049 */ 050 public DataByteArrayInputStream(ByteSequence sequence) { 051 this.buf = sequence.getData(); 052 this.offset = sequence.getOffset(); 053 this.pos = this.offset; 054 } 055 056 /** 057 * Creates <code>WireByteArrayInputStream</code> with a minmalist byte 058 * array 059 */ 060 public DataByteArrayInputStream() { 061 this(new byte[0]); 062 } 063 064 /** 065 * @return the size 066 */ 067 public int size() { 068 return pos - offset; 069 } 070 071 /** 072 * @return the underlying data array 073 */ 074 public byte[] getRawData() { 075 return buf; 076 } 077 078 /** 079 * reset the <code>StoreByteArrayInputStream</code> to use an new byte 080 * array 081 * 082 * @param newBuff 083 */ 084 public void restart(byte[] newBuff) { 085 buf = newBuff; 086 pos = 0; 087 } 088 089 /** 090 * reset the <code>StoreByteArrayInputStream</code> to use an new 091 * ByteSequence 092 * 093 * @param sequence 094 */ 095 public void restart(ByteSequence sequence) { 096 this.buf = sequence.getData(); 097 this.pos = sequence.getOffset(); 098 } 099 100 /** 101 * re-start the input stream - reusing the current buffer 102 * 103 * @param size 104 */ 105 public void restart(int size) { 106 if (buf == null || buf.length < size) { 107 buf = new byte[size]; 108 } 109 restart(buf); 110 } 111 112 /** 113 * Reads the next byte of data from this input stream. The value byte is 114 * returned as an <code>int</code> in the range <code>0</code> to 115 * <code>255</code>. If no byte is available because the end of the 116 * stream has been reached, the value <code>-1</code> is returned. 117 * <p> 118 * This <code>read</code> method cannot block. 119 * 120 * @return the next byte of data, or <code>-1</code> if the end of the 121 * stream has been reached. 122 */ 123 public int read() { 124 return (pos < buf.length) ? (buf[pos++] & 0xff) : -1; 125 } 126 127 /** 128 * Reads up to <code>len</code> bytes of data into an array of bytes from 129 * this input stream. 130 * 131 * @param b the buffer into which the data is read. 132 * @param off the start offset of the data. 133 * @param len the maximum number of bytes read. 134 * @return the total number of bytes read into the buffer, or 135 * <code>-1</code> if there is no more data because the end of the 136 * stream has been reached. 137 */ 138 public int read(byte b[], int off, int len) { 139 if (b == null) { 140 throw new NullPointerException(); 141 } 142 if (pos >= buf.length) { 143 return -1; 144 } 145 if (pos + len > buf.length) { 146 len = buf.length - pos; 147 } 148 if (len <= 0) { 149 return 0; 150 } 151 System.arraycopy(buf, pos, b, off, len); 152 pos += len; 153 return len; 154 } 155 156 /** 157 * @return the number of bytes that can be read from the input stream 158 * without blocking. 159 */ 160 public int available() { 161 return buf.length - pos; 162 } 163 164 public void readFully(byte[] b) { 165 read(b, 0, b.length); 166 } 167 168 public void readFully(byte[] b, int off, int len) { 169 read(b, off, len); 170 } 171 172 public int skipBytes(int n) { 173 if (pos + n > buf.length) { 174 n = buf.length - pos; 175 } 176 if (n < 0) { 177 return 0; 178 } 179 pos += n; 180 return n; 181 } 182 183 public boolean readBoolean() { 184 return read() != 0; 185 } 186 187 public byte readByte() { 188 return (byte)read(); 189 } 190 191 public int readUnsignedByte() { 192 return read(); 193 } 194 195 public short readShort() { 196 int ch1 = read(); 197 int ch2 = read(); 198 return (short)((ch1 << 8) + (ch2 << 0)); 199 } 200 201 public int readUnsignedShort() { 202 int ch1 = read(); 203 int ch2 = read(); 204 return (ch1 << 8) + (ch2 << 0); 205 } 206 207 public char readChar() { 208 int ch1 = read(); 209 int ch2 = read(); 210 return (char)((ch1 << 8) + (ch2 << 0)); 211 } 212 213 public int readInt() { 214 int ch1 = read(); 215 int ch2 = read(); 216 int ch3 = read(); 217 int ch4 = read(); 218 return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0); 219 } 220 221 public long readLong() { 222 long rc = ((long)buf[pos++] << 56) + ((long)(buf[pos++] & 255) << 48) + ((long)(buf[pos++] & 255) << 40) + ((long)(buf[pos++] & 255) << 32); 223 return rc + ((long)(buf[pos++] & 255) << 24) + ((buf[pos++] & 255) << 16) + ((buf[pos++] & 255) << 8) + ((buf[pos++] & 255) << 0); 224 } 225 226 public float readFloat() throws IOException { 227 return Float.intBitsToFloat(readInt()); 228 } 229 230 public double readDouble() throws IOException { 231 return Double.longBitsToDouble(readLong()); 232 } 233 234 public String readLine() { 235 int start = pos; 236 while (pos < buf.length) { 237 int c = read(); 238 if (c == '\n') { 239 break; 240 } 241 if (c == '\r') { 242 c = read(); 243 if (c != '\n' && c != -1) { 244 pos--; 245 } 246 break; 247 } 248 } 249 return new String(buf, start, pos); 250 } 251 252 public String readUTF() throws IOException { 253 int length = readUnsignedShort(); 254 char[] characters = new char[length]; 255 int c; 256 int c2; 257 int c3; 258 int count = 0; 259 int total = pos + length; 260 while (pos < total) { 261 c = (int)buf[pos] & 0xff; 262 if (c > 127) { 263 break; 264 } 265 pos++; 266 characters[count++] = (char)c; 267 } 268 while (pos < total) { 269 c = (int)buf[pos] & 0xff; 270 switch (c >> 4) { 271 case 0: 272 case 1: 273 case 2: 274 case 3: 275 case 4: 276 case 5: 277 case 6: 278 case 7: 279 pos++; 280 characters[count++] = (char)c; 281 break; 282 case 12: 283 case 13: 284 pos += 2; 285 if (pos > total) { 286 throw new UTFDataFormatException("bad string"); 287 } 288 c2 = (int)buf[pos - 1]; 289 if ((c2 & 0xC0) != 0x80) { 290 throw new UTFDataFormatException("bad string"); 291 } 292 characters[count++] = (char)(((c & 0x1F) << 6) | (c2 & 0x3F)); 293 break; 294 case 14: 295 pos += 3; 296 if (pos > total) { 297 throw new UTFDataFormatException("bad string"); 298 } 299 c2 = (int)buf[pos - 2]; 300 c3 = (int)buf[pos - 1]; 301 if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) { 302 throw new UTFDataFormatException("bad string"); 303 } 304 characters[count++] = (char)(((c & 0x0F) << 12) | ((c2 & 0x3F) << 6) | ((c3 & 0x3F) << 0)); 305 break; 306 default: 307 throw new UTFDataFormatException("bad string"); 308 } 309 } 310 return new String(characters, 0, count); 311 } 312 }