1 /* $RCSfile$ 2 * $Author: egonw $ 3 * $Date: 2006-03-18 15:59:33 -0600 (Sat, 18 Mar 2006) $ 4 * $Revision: 4652 $ 5 * 6 * Copyright (C) 2003-2005 Miguel, Jmol Development, www.jmol.org 7 * 8 * Contact: hansonr@stolaf.edu 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23 */ 24 package javajs.util; 25 26 27 import java.io.BufferedInputStream; 28 import java.io.DataInputStream; 29 import java.io.IOException; 30 import java.util.Map; 31 32 import javajs.api.GenericBinaryDocument; 33 import javajs.api.GenericOutputChannel; 34 35 /* a basic binary file reader (extended by CompoundDocument). 36 * 37 * Note that YOU are responsible for determining whether a file 38 * is bigEndian or littleEndian; the default is bigEndian. 39 * 40 * JavaScript note: readShort() malfunctioned because (short) (xx << 8) 41 * isn't the same as (int) (xx << 8); same problem in java.io.DataStream 42 * 43 * 44 */ 45 46 public class BinaryDocument extends BC implements GenericBinaryDocument { 47 48 /** 49 * @j2sIgnore 50 */ BinaryDocument()51 public BinaryDocument() { 52 } 53 54 55 // called by reflection 56 57 protected DataInputStream stream; 58 protected boolean isRandom = false; 59 protected boolean isBigEndian = true; 60 protected BufferedInputStream bis; 61 protected long nBytes; 62 protected GenericOutputChannel out; 63 64 65 @Override close()66 public void close() { 67 if (stream != null) 68 try { 69 stream.close(); 70 } catch (IOException e) { 71 // ignore 72 } 73 if (out != null) 74 out.closeChannel(); 75 } 76 77 @Override setStream(BufferedInputStream bis, boolean isBigEndian)78 public BinaryDocument setStream(BufferedInputStream bis, boolean isBigEndian) { 79 this.bis = bis; 80 if (bis != null) { 81 stream = new DataInputStream(bis); 82 } 83 this.isBigEndian = isBigEndian; 84 return this; 85 } 86 87 @Override getInputStream()88 public BufferedInputStream getInputStream() { 89 return bis; 90 } 91 92 @Override setStreamData(DataInputStream stream, boolean isBigEndian)93 public void setStreamData(DataInputStream stream, boolean isBigEndian) { 94 if (stream != null) 95 this.stream = stream; 96 this.isBigEndian = isBigEndian; 97 } 98 99 @Override setOutputChannel(GenericOutputChannel out)100 public void setOutputChannel(GenericOutputChannel out) { 101 this.out = out; 102 } 103 setRandom(boolean TF)104 public void setRandom(boolean TF) { 105 isRandom = TF; 106 //CANNOT be random for web 107 } 108 109 @Override readByte()110 public byte readByte() throws IOException { 111 nBytes++; 112 return ioReadByte(); 113 } 114 115 @Override readUInt8()116 public int readUInt8() throws IOException { 117 nBytes++; 118 int b = stream.readUnsignedByte(); 119 if (out != null) 120 out.writeByteAsInt(b); 121 return b; 122 } 123 ioReadByte()124 private byte ioReadByte() throws IOException { 125 byte b = stream.readByte(); 126 if (out != null) 127 out.writeByteAsInt(b); 128 return b; 129 } 130 131 @Override readBytes(int n)132 public byte[] readBytes(int n) throws IOException { 133 byte[] b = new byte[n]; 134 readByteArray(b, 0, n); 135 return b; 136 } 137 138 @Override readByteArray(byte[] b, int off, int len)139 public int readByteArray(byte[] b, int off, int len) throws IOException { 140 int n = ioRead(b, off, len); 141 nBytes += n; 142 return n; 143 } 144 ioRead(byte[] b, int off, int len)145 private int ioRead(byte[] b, int off, int len) throws IOException { 146 int m = 0; 147 while (len > 0) { 148 int n = stream.read(b, off, len); 149 m += n; 150 if (n > 0 && out != null) 151 out.write(b, off, n); 152 if (n >= len) 153 break; 154 off += n; 155 len -= n; 156 } 157 return m; 158 } 159 160 @Override readString(int nChar)161 public String readString(int nChar) throws IOException { 162 byte[] temp = new byte[nChar]; 163 int n = readByteArray(temp, 0, nChar); 164 return new String(temp, 0, n, "UTF-8"); 165 } 166 167 @Override readShort()168 public short readShort() throws IOException { 169 nBytes += 2; 170 short n = (isBigEndian ? ioReadShort() 171 : (short) ((ioReadByte() & 0xff) 172 | (ioReadByte() & 0xff) << 8)); 173 /** 174 * @j2sNative 175 * 176 * return (n > 0x7FFF ? n - 0x10000 : n); 177 */ 178 { 179 return n; 180 } 181 } 182 ioReadShort()183 private short ioReadShort() throws IOException { 184 short b = stream.readShort(); 185 if (out != null) 186 out.writeShort(b); 187 return b; 188 } 189 190 191 @Override readIntLE()192 public int readIntLE() throws IOException { 193 nBytes += 4; 194 return readLEInt(); 195 } 196 197 @Override readInt()198 public int readInt() throws IOException { 199 nBytes += 4; 200 return (isBigEndian ? ioReadInt() : readLEInt()); 201 } 202 ioReadInt()203 private int ioReadInt() throws IOException { 204 int i = stream.readInt(); 205 if (out != null) 206 out.writeInt(i); 207 return i; 208 } 209 210 @Override swapBytesI(int n)211 public int swapBytesI(int n) { 212 return (((n >> 24) & 0xff) 213 | ((n >> 16) & 0xff) << 8 214 | ((n >> 8) & 0xff) << 16 215 | (n & 0xff) << 24); 216 } 217 218 @Override swapBytesS(short n)219 public short swapBytesS(short n) { 220 return (short) ((((n >> 8) & 0xff) 221 | (n & 0xff) << 8)); 222 } 223 224 225 @Override readUnsignedShort()226 public int readUnsignedShort() throws IOException { 227 nBytes += 2; 228 int a = (ioReadByte() & 0xff); 229 int b = (ioReadByte() & 0xff); 230 return (isBigEndian ? (a << 8) + b : (b << 8) + a); 231 } 232 233 @Override readLong()234 public long readLong() throws IOException { 235 nBytes += 8; 236 return (isBigEndian ? ioReadLong() 237 : ((((long) ioReadByte()) & 0xff) 238 | (((long) ioReadByte()) & 0xff) << 8 239 | (((long) ioReadByte()) & 0xff) << 16 240 | (((long) ioReadByte()) & 0xff) << 24 241 | (((long) ioReadByte()) & 0xff) << 32 242 | (((long) ioReadByte()) & 0xff) << 40 243 | (((long) ioReadByte()) & 0xff) << 48 244 | (((long) ioReadByte()) & 0xff) << 54)); 245 } 246 ioReadLong()247 private long ioReadLong() throws IOException { 248 long b = stream.readLong(); 249 if (out != null) 250 out.writeLong(b); 251 return b; 252 } 253 readLEInt()254 private int readLEInt() throws IOException { 255 ioRead(t8, 0, 4); 256 return bytesToInt(t8, 0, false); 257 } 258 259 byte[] t8 = new byte[8]; 260 261 @Override readFloat()262 public float readFloat() throws Exception { 263 return intToFloat(readInt()); 264 } 265 266 @Override readDouble()267 public double readDouble() throws IOException { 268 /** 269 * 270 * reading the float equivalent here in JavaScript 271 * 272 * @j2sNative 273 * 274 * this.readByteArray(this.t8, 0, 8); 275 * return this.bytesToDoubleToFloat(this.t8, 0, this.isBigEndian); 276 * 277 */ 278 { 279 nBytes += 8; 280 return (isBigEndian ? ioReadDouble() : Double.longBitsToDouble(readLELong())); 281 } 282 } 283 ioReadDouble()284 private double ioReadDouble() throws IOException { 285 double d = stream.readDouble(); 286 if (out != null) 287 out.writeLong(Double.doubleToRawLongBits(d)); 288 return d; 289 } 290 readLELong()291 private long readLELong() throws IOException { 292 return ((((long) ioReadByte()) & 0xff) 293 | (((long) ioReadByte()) & 0xff) << 8 294 | (((long) ioReadByte()) & 0xff) << 16 295 | (((long) ioReadByte()) & 0xff) << 24 296 | (((long) ioReadByte()) & 0xff) << 32 297 | (((long) ioReadByte()) & 0xff) << 40 298 | (((long) ioReadByte()) & 0xff) << 48 299 | (((long) ioReadByte()) & 0xff) << 56); 300 } 301 302 @Override seek(long offset)303 public void seek(long offset) { 304 // slower, but all that is available using the applet 305 try { 306 if (offset == nBytes) 307 return; 308 if (offset < nBytes) { 309 stream.reset(); 310 if (out != null && nBytes != 0) 311 out.reset(); 312 nBytes = 0; 313 } else { 314 offset -= nBytes; 315 } 316 if (out == null) { 317 stream.skipBytes((int)offset); 318 } else { 319 readByteArray(new byte[(int)offset], 0, (int) offset); 320 } 321 nBytes += offset; 322 } catch (IOException e) { 323 System.out.println(e.toString()); 324 } 325 } 326 327 @Override getPosition()328 public long getPosition() { 329 return nBytes; 330 } 331 332 @Override getAllDataFiles(String binaryFileList, String firstFile)333 public SB getAllDataFiles(String binaryFileList, String firstFile) { 334 return null; 335 } 336 337 @Override getAllDataMapped(String replace, String string, Map<String, String> fileData)338 public void getAllDataMapped(String replace, String string, 339 Map<String, String> fileData) { 340 } 341 342 343 /* random access -- application only: 344 * 345 void seekFile(long offset) { 346 try { 347 file.seek(offset); 348 } catch (IOException e) { 349 System.out.println(e.getMessage()); 350 } 351 } 352 */ 353 } 354