]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.graph/src/org/simantics/graph/representation/ByteFileReader.java
Fixing PrettyPrintTG to not concatenate strings in logging
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / representation / ByteFileReader.java
1 package org.simantics.graph.representation;
2
3 import java.io.Closeable;
4 import java.io.EOFException;
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.nio.ByteBuffer;
10 import java.nio.channels.ReadableByteChannel;
11
12 /**
13  * Must be closed after using by invoking {@link #close()}.
14  */
15 public class ByteFileReader implements Closeable {
16
17         final char[] chars = new char[3*128];
18
19         final private File file;
20         
21         /**
22          * May be <code>null</code>. If specified, it will be closed in
23          * {@link #close()}.
24          */
25         private InputStream stream;
26
27         /**
28          * A readable channel must always be specified since it is used for all
29          * reading. Channel is never closed by this class.
30          */
31         private ReadableByteChannel channel;
32         
33         final private ByteBuffer byteBuffer;
34         
35         final protected byte[] bytes;
36         private int size;
37
38         protected int byteIndex = 0;
39
40         final protected ReadableByteChannel getChannel() {
41                 return channel;
42         }
43         
44         final protected ByteBuffer getByteBuffer() {
45                 return byteBuffer;
46         }
47
48         final protected byte[] getBytes() {
49                 return bytes;
50
51         }
52         final protected String utf(byte[] bytes, int index, int target) {
53                 int i = 0;
54                 while(index < target) {
55                         int c = bytes[index++]&0xff;
56                         if(c <= 0x7F) {
57                                 chars[i++] = (char)(c&0x7F);
58                         } else if (c > 0x07FF) {
59                                 int c2 = bytes[index++]&0xff;
60                                 int c3 = bytes[index++]&0xff;
61                                 chars[i++] = (char)(((c&0xf)<<12) + ((c2&0x3f)<<6) + (c3&0x3f)); 
62                         } else {
63                                 int c2 = bytes[index++]&0xff;
64                                 chars[i++] = (char)(((c&0x1f)<<6) + (c2&0x3f)); 
65                         }
66                         
67                 }
68                 return new String(chars, 0, i);
69         }
70
71         final protected byte[] safeBytes(int amount) throws IOException {
72
73                 byte[] result = new byte[amount];
74                 
75                 int has = size-byteIndex;
76                 if(amount >= has) {
77                         ReadableByteChannel c = channel;
78                 ByteBuffer bb = byteBuffer;
79                         System.arraycopy(bytes, byteIndex, result, 0, has);
80                         ByteBuffer bb2 = ByteBuffer.wrap(result);
81                         bb2.position(has);
82                         // For some peculiar reason this seems to avoid OOM with large blocks as compared to c.read(bb2
83                         while(has < amount) {
84                                 int todo = Math.min(amount-has, 65536);
85                                 bb2.limit(has+todo);
86                                 int got = c.read(bb2);
87                                 if(got == -1) throw new IOException("Unexpected end-of-file");
88                                 has += got; 
89                         }
90                         size = c.read(bb);
91                         bb.position(0);
92                         byteIndex = 0;
93                 } else {
94                         System.arraycopy(bytes, byteIndex, result, 0, amount);
95                         byteIndex += amount;
96                 }
97
98                 return result;
99                 
100         }
101
102         final protected int getByte() throws IOException {
103             int has = size-byteIndex;
104             int result;
105         if(has == 0) {
106             ReadableByteChannel c = channel;
107             ByteBuffer bb = byteBuffer;            
108             size = c.read(bb);
109             if(size == -1) {
110                                 throw new EOFException("Unexpected end-of-file");
111             }
112             bb.position(0);
113             byteIndex = 0;
114             if(size == 0)
115                 return -1;
116         }
117         result = bytes[byteIndex];
118         if(result < 0)
119             result += 256;
120         ++byteIndex;        
121         return result;
122         }
123
124         public int getDynamicUInt32() throws IOException {
125                 int length = getByte()&0xff; 
126                 if(length >= 0x80) {
127                         if(length >= 0xc0) {
128                                 if(length >= 0xe0) {
129                                         if(length >= 0xf0) {
130                                                 length &= 0x0f;
131                                                 length += ((getByte()&0xff)<<3);
132                                                 length += ((getByte()&0xff)<<11);
133                                                 length += ((getByte()&0xff)<<19);
134                                                 length += 0x10204080;
135                                         }
136                                         else {
137                                                 length &= 0x1f;
138                                                 length += ((getByte()&0xff)<<4);
139                                                 length += ((getByte()&0xff)<<12);
140                                                 length += ((getByte()&0xff)<<20);
141                                                 length += 0x204080;
142                                         }
143                                 }
144                                 else {
145                                         length &= 0x3f;
146                                         length += ((getByte()&0xff)<<5);
147                                         length += ((getByte()&0xff)<<13);
148                                         length += 0x4080;
149                                 }
150                         }
151                         else {
152                                 length &= 0x7f;
153                                 length += ((getByte()&0xff)<<6);
154                                 length += 0x80;
155                         }
156                 }
157                 return length;
158         }
159
160         final protected int safeInt() throws IOException {
161
162                 if(byteIndex >= (size-5)) {
163                         int result = 0;
164                         ReadableByteChannel c = channel;
165                 ByteBuffer bb = byteBuffer;
166                         if(byteIndex == size) {
167                                 size = c.read(bb);
168                                 if(size == -1) throw new EOFException("Unexpected end-of-file");
169                                 bb.position(0);
170                                 byteIndex = 0;
171                         }
172                         result |= ((int)(bytes[byteIndex++]&0xff)<<24);
173                         if(byteIndex == size) {
174                                 size = c.read(bb);
175                                 if(size == -1) throw new EOFException("Unexpected end-of-file");
176                                 bb.position(0);
177                                 byteIndex = 0;
178                         }
179                         result |= ((int)(bytes[byteIndex++]&0xff)<<16);
180                         if(byteIndex == size) {
181                                 size = c.read(bb);
182                                 if(size == -1) throw new EOFException("Unexpected end-of-file");
183                                 bb.position(0);
184                                 byteIndex = 0;
185                         }
186                         result |= ((int)(bytes[byteIndex++]&0xff)<<8);
187                         if(byteIndex == size) {
188                                 size = c.read(bb);
189                                 if(size == -1) throw new EOFException("Unexpected end-of-file");
190                                 bb.position(0);
191                                 byteIndex = 0;
192                         }
193                         result |= ((int)(bytes[byteIndex++]&0xff)<<0);
194                         if(byteIndex == size) {
195                                 size = c.read(bb);
196                                 bb.position(0);
197                                 byteIndex = 0;
198                         }
199                         return result;
200                 } else {
201                         return ((bytes[byteIndex++]&0xff)<<24) | ((bytes[byteIndex++]&0xff)<<16) | ((bytes[byteIndex++]&0xff)<<8) | ((bytes[byteIndex++]&0xff));
202                 }
203                 
204         }
205         
206         final protected int getSize() {
207                 return size;
208         }
209
210         public ByteFileReader(File file, int size) throws IOException {
211             
212         bytes = new byte[size];
213         byteBuffer = ByteBuffer.wrap(bytes);
214
215         this.file = file;
216         
217         FileInputStream fis = new FileInputStream(file); 
218         stream = fis; 
219         channel = fis.getChannel();
220         this.size = channel.read(byteBuffer);
221         byteBuffer.position(0);
222             
223         }
224
225         public ByteFileReader(FileInputStream stream, int size) throws IOException {
226                 this(stream, stream.getChannel(), size);
227         }
228     
229         public ByteFileReader(InputStream stream, ReadableByteChannel channel, int size) throws IOException {
230             
231                 bytes = new byte[size];
232                 byteBuffer = ByteBuffer.wrap(bytes);
233
234                 this.file = null;
235                 this.stream = stream;
236                 this.channel = channel;
237                 this.size = channel.read(byteBuffer);
238                 byteBuffer.position(0);
239                 
240         }
241
242         public void close() throws IOException {
243                 if (stream != null) {
244                         stream.close();
245                         stream = null;
246                 }
247         }
248         
249         public void reset() throws IOException {
250             
251             if(file == null) throw new IllegalStateException("No file - cannot reset");
252         
253         FileInputStream fis = new FileInputStream(file); 
254         stream = fis; 
255         channel = fis.getChannel();
256         this.size = channel.read(byteBuffer);
257         byteBuffer.position(0);
258         
259         }
260
261 }