1 package nom.tam.util;
2
3 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 @Deprecated
59 public class ByteParser {
60
61 private static final int EXPONENT_DENORMALISATION_CORR_LIMIT = -300;
62
63 private static final double EXPONENT_DENORMALISATION_FACTOR = 1.e-300;
64
65 private static final byte[] INFINITY_LOWER = AsciiFuncs.getBytes(ByteFormatter.INFINITY.toLowerCase());
66
67 private static final byte[] INFINITY_UPPER = AsciiFuncs.getBytes(ByteFormatter.INFINITY.toUpperCase());
68
69 private static final int INFINITY_LENGTH = ByteParser.INFINITY_UPPER.length;
70
71 private static final int INFINITY_SHORTCUT_LENGTH = 3;
72
73 private static final byte[] NOT_A_NUMBER_LOWER = AsciiFuncs.getBytes(ByteFormatter.NOT_A_NUMBER.toLowerCase());
74
75 private static final byte[] NOT_A_NUMBER_UPPER = AsciiFuncs.getBytes(ByteFormatter.NOT_A_NUMBER.toUpperCase());
76
77 private static final int NOT_A_NUMBER_LENGTH = ByteParser.NOT_A_NUMBER_UPPER.length;
78
79
80
81
82 private static final int NUMBER_BASE = 10;
83
84
85
86
87 private static final double NUMBER_BASE_DOUBLE = 10.;
88
89
90
91
92 private boolean foundSign;
93
94
95
96
97 private byte[] input;
98
99
100
101
102 private int numberLength;
103
104
105
106
107 private int offset;
108
109
110
111
112
113
114
115 @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "intended exposure of mutable data")
116 public ByteParser(byte[] input) {
117 this.input = input;
118 offset = 0;
119 }
120
121
122
123
124
125 private int checkSign() {
126
127 foundSign = false;
128
129 if (input[offset] == '+') {
130 foundSign = true;
131 offset++;
132 return 1;
133 }
134 if (input[offset] == '-') {
135 foundSign = true;
136 offset++;
137 return -1;
138 }
139
140 return 1;
141 }
142
143
144
145
146
147
148
149
150 private double getBareInteger(int length) {
151
152 int startOffset = offset;
153 double number = 0;
154
155 while (length > 0 && input[offset] >= '0' && input[offset] <= '9') {
156
157 number *= ByteParser.NUMBER_BASE;
158 number += input[offset] - '0';
159 offset++;
160 length--;
161 }
162 numberLength = offset - startOffset;
163 return number;
164 }
165
166
167
168
169
170
171 public boolean getBoolean() throws FormatException {
172 return getBoolean(input.length - offset);
173 }
174
175
176
177
178
179
180
181
182 public boolean getBoolean(int length) throws FormatException {
183
184 int startOffset = offset;
185 length -= skipWhite(length);
186 if (length == 0) {
187 throw new FormatException("Blank boolean field");
188 }
189
190 boolean value = false;
191 if (input[offset] == 'T' || input[offset] == 't') {
192 value = true;
193 } else if (input[offset] != 'F' && input[offset] != 'f') {
194 numberLength = 0;
195 offset = startOffset;
196 throw new FormatException("Invalid boolean value");
197 }
198 offset++;
199 numberLength = offset - startOffset;
200 return value;
201 }
202
203
204
205
206 @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "intended exposure of mutable data")
207 public byte[] getBuffer() {
208 return input;
209 }
210
211
212
213
214
215
216
217
218 public double getDouble() throws FormatException {
219 return getDouble(input.length - offset);
220 }
221
222
223
224
225
226
227
228
229
230 public double getDouble(int length) throws FormatException {
231 int startOffset = offset;
232 boolean error = true;
233 double number;
234
235 length -= skipWhite(length);
236 if (length == 0) {
237 numberLength = offset - startOffset;
238 return 0;
239 }
240 double mantissaSign = checkSign();
241 if (foundSign) {
242 length--;
243 }
244
245 if (isCaseInsensitiv(length, ByteParser.NOT_A_NUMBER_LENGTH, ByteParser.NOT_A_NUMBER_LOWER,
246 ByteParser.NOT_A_NUMBER_UPPER)) {
247 number = Double.NaN;
248 offset += ByteParser.NOT_A_NUMBER_LENGTH;
249
250 } else if (isCaseInsensitiv(length, ByteParser.INFINITY_LENGTH, ByteParser.INFINITY_LOWER,
251 ByteParser.INFINITY_UPPER)) {
252 number = Double.POSITIVE_INFINITY;
253 offset += ByteParser.INFINITY_LENGTH;
254 } else if (isCaseInsensitiv(length, ByteParser.INFINITY_SHORTCUT_LENGTH, ByteParser.INFINITY_LOWER,
255 ByteParser.INFINITY_UPPER)) {
256 number = Double.POSITIVE_INFINITY;
257 offset += ByteParser.INFINITY_SHORTCUT_LENGTH;
258 } else {
259 number = getBareInteger(length);
260 length -= numberLength;
261 if (numberLength > 0) {
262 error = false;
263 }
264
265 if (length > 0 && input[offset] == '.') {
266 offset++;
267 length--;
268 double numerator = getBareInteger(length);
269 if (numerator > 0) {
270 number += numerator / Math.pow(ByteParser.NUMBER_BASE_DOUBLE, numberLength);
271 }
272 length -= numberLength;
273 if (numberLength > 0) {
274 error = false;
275 }
276 }
277
278 if (error) {
279 offset = startOffset;
280 numberLength = 0;
281 throw new FormatException("Invalid real field");
282 }
283
284
285
286
287 if (length > 0
288 && (input[offset] == 'e' || input[offset] == 'E' || input[offset] == 'd' || input[offset] == 'D')) {
289 offset++;
290 length--;
291 if (length > 0) {
292 int sign = checkSign();
293 if (foundSign) {
294 length--;
295 }
296
297 int exponent = (int) getBareInteger(length);
298
299
300
301 if (exponent * sign > ByteParser.EXPONENT_DENORMALISATION_CORR_LIMIT) {
302 number *= Math.pow(ByteParser.NUMBER_BASE_DOUBLE, exponent * sign);
303 } else {
304 number = ByteParser.EXPONENT_DENORMALISATION_FACTOR
305 * (number * Math.pow(ByteParser.NUMBER_BASE_DOUBLE,
306 exponent * sign + ByteParser.EXPONENT_DENORMALISATION_CORR_LIMIT * -1));
307 }
308 }
309 }
310 }
311 numberLength = offset - startOffset;
312 return mantissaSign * number;
313 }
314
315
316
317
318
319
320 public float getFloat() throws FormatException {
321 return (float) getDouble(input.length - offset);
322 }
323
324
325
326
327
328
329
330
331 public float getFloat(int length) throws FormatException {
332 return (float) getDouble(length);
333 }
334
335
336
337
338
339
340 public int getInt() throws FormatException {
341 return getInt(input.length - offset);
342 }
343
344
345
346
347
348
349
350
351
352 public int getInt(int length) throws FormatException {
353 int startOffset = offset;
354
355 length -= skipWhite(length);
356 if (length == 0) {
357 numberLength = offset - startOffset;
358 return 0;
359 }
360
361 int number = 0;
362 boolean error = true;
363
364 int sign = checkSign();
365 if (foundSign) {
366 length--;
367 }
368
369 while (length > 0 && input[offset] >= '0' && input[offset] <= '9') {
370 number = number * ByteParser.NUMBER_BASE + input[offset] - '0';
371 offset++;
372 length--;
373 error = false;
374 }
375
376 if (error) {
377 numberLength = 0;
378 offset = startOffset;
379 throw new FormatException("Invalid Integer");
380 }
381 numberLength = offset - startOffset;
382 return sign * number;
383 }
384
385
386
387
388
389
390
391
392 public long getLong(int length) throws FormatException {
393
394 int startOffset = offset;
395
396
397 length -= skipWhite(length);
398 if (length == 0) {
399 numberLength = offset - startOffset;
400 return 0;
401 }
402
403 long number = 0;
404 boolean error = true;
405
406 long sign = checkSign();
407 if (foundSign) {
408 length--;
409 }
410
411 while (length > 0 && input[offset] >= '0' && input[offset] <= '9') {
412 number = number * ByteParser.NUMBER_BASE + input[offset] - '0';
413 error = false;
414 offset++;
415 length--;
416 }
417
418 if (error) {
419 numberLength = 0;
420 offset = startOffset;
421 throw new FormatException("Invalid long number");
422 }
423 numberLength = offset - startOffset;
424 return sign * number;
425 }
426
427
428
429
430
431 public int getNumberLength() {
432 return numberLength;
433 }
434
435
436
437
438
439
440 public int getOffset() {
441 return offset;
442 }
443
444
445
446
447
448
449 public String getString(int length) {
450
451 String s = AsciiFuncs.asciiString(input, offset, length);
452 offset += length;
453 numberLength = length;
454 return s;
455 }
456
457 private boolean isCaseInsensitiv(int length, int constantLength, byte[] lowerConstant, byte[] upperConstant) {
458 if (length < constantLength) {
459 return false;
460 }
461 for (int i = 0; i < constantLength; i++) {
462 if (input[offset + i] != lowerConstant[i] && input[offset + i] != upperConstant[i]) {
463 return false;
464 }
465 }
466 return true;
467 }
468
469
470
471
472
473
474 @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "intended exposure of mutable data")
475 public void setBuffer(byte[] buf) {
476 input = buf;
477 offset = 0;
478 }
479
480
481
482
483
484
485 public void setOffset(int offset) {
486 this.offset = offset;
487 }
488
489
490
491
492
493
494 public void skip(int nBytes) {
495 offset += nBytes;
496 }
497
498
499
500
501
502
503
504
505 public int skipWhite(int length) {
506 int i;
507 for (i = 0; i < length; i++) {
508 if (input[offset + i] != ' ' && input[offset + i] != '\t' && input[offset + i] != '\n'
509 && input[offset + i] != '\r') {
510 break;
511 }
512 }
513 offset += i;
514 return i;
515 }
516 }