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