1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.imaging.common;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.PrintWriter;
22 import java.io.RandomAccessFile;
23 import java.nio.ByteOrder;
24 import java.util.logging.Logger;
25
26 import org.apache.commons.imaging.ImagingException;
27 import org.apache.commons.io.IOUtils;
28 import org.apache.commons.io.RandomAccessFiles;
29
30
31
32
33 public final class BinaryFunctions {
34
35 private static final Logger LOGGER = Logger.getLogger(BinaryFunctions.class.getName());
36
37 public static int charsToQuad(final char c1, final char c2, final char c3, final char c4) {
38 return (0xff & c1) << 24 | (0xff & c2) << 16 | (0xff & c3) << 8 | (0xff & c4) << 0;
39 }
40
41 public static boolean compareBytes(final byte[] a, final int aStart, final byte[] b, final int bStart, final int length) {
42 if (a.length < aStart + length) {
43 return false;
44 }
45 if (b.length < bStart + length) {
46 return false;
47 }
48
49 for (int i = 0; i < length; i++) {
50 if (a[aStart + i] != b[bStart + i]) {
51 return false;
52 }
53 }
54
55 return true;
56 }
57
58 public static int findNull(final byte[] src, final int start, final String message) throws ImagingException {
59 for (int i = start; i < src.length; i++) {
60 if (src[i] == 0) {
61 return i;
62 }
63 }
64 throw new ImagingException(message);
65 }
66
67 public static int findNull(final byte[] src, final String message) throws ImagingException {
68 return findNull(src, 0, message);
69 }
70
71 public static byte[] getBytes(final RandomAccessFile raf, final long pos, final int length, final String exception) throws IOException {
72 if (length < 0) {
73 throw new IOException(String.format("%s, invalid length: %d", exception, length));
74 }
75 Allocator.checkByteArray(length);
76 return RandomAccessFiles.read(raf, pos, length);
77
78 }
79
80 public static byte[] head(final byte[] bytes, int count) {
81 if (count > bytes.length) {
82 count = bytes.length;
83 }
84 return slice(bytes, 0, count);
85 }
86
87 public static void logByteBits(final String msg, final byte i) {
88 LOGGER.finest(msg + ": '" + Integer.toBinaryString(0xff & i));
89 }
90
91 public static void logCharQuad(final String msg, final int i) {
92 LOGGER.finest(msg + ": '" + (char) (0xff & i >> 24) + (char) (0xff & i >> 16) + (char) (0xff & i >> 8) + (char) (0xff & i >> 0) + "'");
93
94 }
95
96 public static void printCharQuad(final PrintWriter pw, final String msg, final int i) {
97 pw.println(msg + ": '" + (char) (0xff & i >> 24) + (char) (0xff & i >> 16) + (char) (0xff & i >> 8) + (char) (0xff & i >> 0) + "'");
98
99 }
100
101
102
103
104
105
106
107 public static byte[] quadsToByteArray(final int quad) {
108 final byte[] arr = new byte[4];
109 arr[0] = (byte) (quad >> 24);
110 arr[1] = (byte) (quad >> 16);
111 arr[2] = (byte) (quad >> 8);
112 arr[3] = (byte) quad;
113 return arr;
114 }
115
116 public static int read2Bytes(final String name, final InputStream is, final String exception, final ByteOrder byteOrder) throws IOException {
117 final int byte0 = is.read();
118 final int byte1 = is.read();
119 if ((byte0 | byte1) < 0) {
120 throw new IOException(exception);
121 }
122
123 final int result;
124 if (byteOrder == ByteOrder.BIG_ENDIAN) {
125 result = byte0 << 8 | byte1;
126 } else {
127 result = byte1 << 8 | byte0;
128 }
129
130 return result;
131 }
132
133 public static int read3Bytes(final String name, final InputStream is, final String exception, final ByteOrder byteOrder) throws IOException {
134 final int byte0 = is.read();
135 final int byte1 = is.read();
136 final int byte2 = is.read();
137 if ((byte0 | byte1 | byte2) < 0) {
138 throw new IOException(exception);
139 }
140
141 final int result;
142 if (byteOrder == ByteOrder.BIG_ENDIAN) {
143 result = byte0 << 16 | byte1 << 8 | byte2 << 0;
144 } else {
145 result = byte2 << 16 | byte1 << 8 | byte0 << 0;
146 }
147
148 return result;
149 }
150
151 public static int read4Bytes(final String name, final InputStream is, final String exception, final ByteOrder byteOrder) throws IOException {
152 final int byte0 = is.read();
153 final int byte1 = is.read();
154 final int byte2 = is.read();
155 final int byte3 = is.read();
156 if ((byte0 | byte1 | byte2 | byte3) < 0) {
157 throw new IOException(exception);
158 }
159
160 final int result;
161 if (byteOrder == ByteOrder.BIG_ENDIAN) {
162 result = byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3 << 0;
163 } else {
164 result = byte3 << 24 | byte2 << 16 | byte1 << 8 | byte0 << 0;
165 }
166
167 return result;
168 }
169
170
171
172
173
174
175
176
177
178
179
180 public static long read8Bytes(final String name, final InputStream is, final String exception, final ByteOrder byteOrder) throws IOException {
181
182 final long byte0 = is.read();
183 final long byte1 = is.read();
184 final long byte2 = is.read();
185 final long byte3 = is.read();
186 final long byte4 = is.read();
187 final long byte5 = is.read();
188 final long byte6 = is.read();
189 final long byte7 = is.read();
190
191 if ((byte0 | byte1 | byte2 | byte3 | byte4 | byte5 | byte6 | byte7) < 0) {
192 throw new IOException(exception);
193 }
194
195 final long result;
196 if (byteOrder == ByteOrder.BIG_ENDIAN) {
197 result = byte0 << 56 | byte1 << 48 | byte2 << 40 | byte3 << 32 | byte4 << 24 | byte5 << 16 | byte6 << 8 | byte7 << 0;
198 } else {
199 result = byte7 << 56 | byte6 << 48 | byte5 << 40 | byte4 << 32 | byte3 << 24 | byte2 << 16 | byte1 << 8 | byte0 << 0;
200 }
201
202 return result;
203 }
204
205 public static void readAndVerifyBytes(final InputStream is, final BinaryConstant expected, final String exception) throws ImagingException, IOException {
206 for (int i = 0; i < expected.size(); i++) {
207 final int data = is.read();
208 final byte b = (byte) (0xff & data);
209
210 if (data < 0) {
211 throw new ImagingException("Unexpected EOF.");
212 }
213
214 if (b != expected.get(i)) {
215 throw new ImagingException(exception);
216 }
217 }
218 }
219
220 public static void readAndVerifyBytes(final InputStream is, final byte[] expected, final String exception) throws ImagingException, IOException {
221 for (final byte element : expected) {
222 final int data = is.read();
223 final byte b = (byte) (0xff & data);
224
225 if (data < 0) {
226 throw new ImagingException("Unexpected EOF.");
227 }
228
229 if (b != element) {
230 throw new ImagingException(exception);
231 }
232 }
233 }
234
235 public static byte readByte(final String name, final InputStream is, final String exceptionMessage) throws IOException {
236 final int result = is.read();
237 if (result < 0) {
238 throw new IOException(exceptionMessage);
239 }
240 return (byte) (0xff & result);
241 }
242
243 public static byte[] readBytes(final InputStream is, final int count) throws IOException {
244 return readBytes("", is, count, "Unexpected EOF");
245 }
246
247 public static byte[] readBytes(final String name, final InputStream is, final int length) throws IOException {
248 return readBytes(name, is, length, name + " could not be read.");
249 }
250
251 public static byte[] readBytes(final String name, final InputStream is, final int length, final String exception) throws IOException {
252 try {
253 return IOUtils.toByteArray(is, Allocator.check(length));
254 } catch (final IOException e) {
255 throw new IOException(exception + ", name: " + name + ", length: " + length);
256 }
257 }
258
259 public static byte[] remainingBytes(final String name, final byte[] bytes, final int count) {
260 return slice(bytes, count, bytes.length - count);
261 }
262
263
264
265
266
267
268
269
270
271
272
273
274
275 public static boolean searchQuad(final int quad, final InputStream bis) throws IOException {
276 final byte[] needle = BinaryFunctions.quadsToByteArray(quad);
277 int b = -1;
278 int position = 0;
279 while ((b = bis.read()) != -1) {
280 if (needle[position] == b) {
281 position++;
282 if (position == needle.length) {
283 return true;
284 }
285 } else {
286 position = 0;
287 }
288 }
289 return false;
290 }
291
292 public static long skipBytes(final InputStream is, final long length) throws IOException {
293 return skipBytes(is, length, "Couldn't skip bytes");
294 }
295
296 public static long skipBytes(final InputStream is, final long length, final String exMessage) throws IOException {
297 try {
298 return IOUtils.skip(is, length);
299 } catch (final IOException e) {
300 throw new IOException(exMessage, e);
301 }
302 }
303
304 public static byte[] slice(final byte[] bytes, final int start, final int count) {
305 final byte[] result = Allocator.byteArray(count);
306 System.arraycopy(bytes, start, result, 0, count);
307 return result;
308 }
309
310 public static boolean startsWith(final byte[] buffer, final BinaryConstant search) {
311 if (buffer == null || buffer.length < search.size()) {
312 return false;
313 }
314
315 for (int i = 0; i < search.size(); i++) {
316 if (buffer[i] != search.get(i)) {
317 return false;
318 }
319 }
320
321 return true;
322 }
323
324 public static boolean startsWith(final byte[] buffer, final byte[] search) {
325 if (search == null) {
326 return false;
327 }
328 if (buffer == null) {
329 return false;
330 }
331 if (search.length > buffer.length) {
332 return false;
333 }
334
335 for (int i = 0; i < search.length; i++) {
336 if (search[i] != buffer[i]) {
337 return false;
338 }
339 }
340
341 return true;
342 }
343
344 private BinaryFunctions() {
345 }
346 }