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