1
2
3
4
5
6 package org.codehaus.plexus.util;
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 public final class TypeFormat {
37
38
39
40
41 private static final char[] DIGITS = {
42 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
43 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
44 };
45
46
47
48
49 private TypeFormat() {}
50
51
52
53
54
55
56
57
58
59
60 public static int indexOf(CharSequence pattern, CharSequence chars, int fromIndex) {
61 int patternLength = pattern.length();
62 fromIndex = Math.max(0, fromIndex);
63 if (patternLength != 0) {
64 char firstChar = pattern.charAt(0);
65 int last = chars.length() - patternLength;
66 for (int i = fromIndex; i <= last; i++) {
67 if (chars.charAt(i) == firstChar) {
68 boolean match = true;
69 for (int j = 1; j < patternLength; j++) {
70 if (chars.charAt(i + j) != pattern.charAt(j)) {
71 match = false;
72 break;
73 }
74 }
75 if (match) {
76 return i;
77 }
78 }
79 }
80 return -1;
81 } else {
82 return Math.min(0, fromIndex);
83 }
84 }
85
86
87
88
89
90
91
92 public static boolean parseBoolean(CharSequence chars) {
93 return (chars.length() == 4)
94 && (chars.charAt(0) == 't' || chars.charAt(0) == 'T')
95 && (chars.charAt(1) == 'r' || chars.charAt(1) == 'R')
96 && (chars.charAt(2) == 'u' || chars.charAt(2) == 'U')
97 && (chars.charAt(3) == 'e' || chars.charAt(3) == 'E');
98 }
99
100
101
102
103
104
105
106
107
108 public static short parseShort(CharSequence chars) {
109 return parseShort(chars, 10);
110 }
111
112
113
114
115
116
117
118
119
120
121
122 public static short parseShort(CharSequence chars, int radix) {
123 try {
124 boolean isNegative = (chars.charAt(0) == '-') ? true : false;
125 int result = 0;
126 int limit = (isNegative) ? Short.MIN_VALUE : -Short.MAX_VALUE;
127 int multmin = limit / radix;
128 int length = chars.length();
129 int i = (isNegative || (chars.charAt(0) == '+')) ? 1 : 0;
130 while (true) {
131 int digit = Character.digit(chars.charAt(i), radix);
132 int tmp = result * radix;
133 if ((digit < 0) || (result < multmin) || (tmp < limit + digit)) {
134 throw new NumberFormatException("For input characters: \"" + chars.toString() + "\"");
135 }
136
137 result = tmp - digit;
138 if (++i >= length) {
139 break;
140 }
141 }
142 return (short) (isNegative ? result : -result);
143 } catch (IndexOutOfBoundsException e) {
144 throw new NumberFormatException("For input characters: \"" + chars.toString() + "\"");
145 }
146 }
147
148
149
150
151
152
153
154
155
156 public static int parseInt(CharSequence chars) {
157 return parseInt(chars, 10);
158 }
159
160
161
162
163
164
165
166
167
168
169
170 public static int parseInt(CharSequence chars, int radix) {
171 try {
172 boolean isNegative = (chars.charAt(0) == '-') ? true : false;
173 int result = 0;
174 int limit = (isNegative) ? Integer.MIN_VALUE : -Integer.MAX_VALUE;
175 int multmin = limit / radix;
176 int length = chars.length();
177 int i = (isNegative || (chars.charAt(0) == '+')) ? 1 : 0;
178 while (true) {
179 int digit = Character.digit(chars.charAt(i), radix);
180 int tmp = result * radix;
181 if ((digit < 0) || (result < multmin) || (tmp < limit + digit)) {
182 throw new NumberFormatException("For input characters: \"" + chars.toString() + "\"");
183 }
184
185 result = tmp - digit;
186 if (++i >= length) {
187 break;
188 }
189 }
190 return isNegative ? result : -result;
191 } catch (IndexOutOfBoundsException e) {
192 throw new NumberFormatException("For input characters: \"" + chars.toString() + "\"");
193 }
194 }
195
196
197
198
199
200
201
202
203
204 public static long parseLong(CharSequence chars) {
205 return parseLong(chars, 10);
206 }
207
208
209
210
211
212
213
214
215
216
217
218 public static long parseLong(CharSequence chars, int radix) {
219 try {
220 boolean isNegative = (chars.charAt(0) == '-') ? true : false;
221 long result = 0;
222 long limit = (isNegative) ? Long.MIN_VALUE : -Long.MAX_VALUE;
223 long multmin = limit / radix;
224 int length = chars.length();
225 int i = (isNegative || (chars.charAt(0) == '+')) ? 1 : 0;
226 while (true) {
227 int digit = Character.digit(chars.charAt(i), radix);
228 long tmp = result * radix;
229 if ((digit < 0) || (result < multmin) || (tmp < limit + digit)) {
230 throw new NumberFormatException("For input characters: \"" + chars.toString() + "\"");
231 }
232
233 result = tmp - digit;
234 if (++i >= length) {
235 break;
236 }
237 }
238 return isNegative ? result : -result;
239 } catch (IndexOutOfBoundsException e) {
240 throw new NumberFormatException("For input characters: \"" + chars.toString() + "\"");
241 }
242 }
243
244
245
246
247
248
249
250
251 public static float parseFloat(CharSequence chars) {
252 double d = parseDouble(chars);
253 if ((d >= Float.MIN_VALUE) && (d <= Float.MAX_VALUE)) {
254 return (float) d;
255 } else {
256 throw new NumberFormatException("Float overflow for input characters: \"" + chars.toString() + "\"");
257 }
258 }
259
260
261
262
263
264
265
266
267 public static double parseDouble(CharSequence chars) throws NumberFormatException {
268 try {
269 int length = chars.length();
270 double result = 0.0;
271 int exp = 0;
272
273 boolean isNegative = (chars.charAt(0) == '-') ? true : false;
274 int i = (isNegative || (chars.charAt(0) == '+')) ? 1 : 0;
275
276
277 if ((chars.charAt(i) == 'N') || (chars.charAt(i) == 'I')) {
278 if (chars.toString().equals("NaN")) {
279 return Double.NaN;
280 } else if (chars.subSequence(i, length).toString().equals("Infinity")) {
281 return isNegative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
282 }
283 }
284
285
286 boolean fraction = false;
287 while (true) {
288 char c = chars.charAt(i);
289 if ((c == '.') && (!fraction)) {
290 fraction = true;
291 } else if ((c == 'e') || (c == 'E')) {
292 break;
293 } else if ((c >= '0') && (c <= '9')) {
294 result = result * 10 + (c - '0');
295 if (fraction) {
296 exp--;
297 }
298 } else {
299 throw new NumberFormatException("For input characters: \"" + chars.toString() + "\"");
300 }
301 if (++i >= length) {
302 break;
303 }
304 }
305 result = isNegative ? -result : result;
306
307
308 if (i < length) {
309 i++;
310 boolean negE = (chars.charAt(i) == '-') ? true : false;
311 i = (negE || (chars.charAt(i) == '+')) ? i + 1 : i;
312 int valE = 0;
313 while (true) {
314 char c = chars.charAt(i);
315 if ((c >= '0') && (c <= '9')) {
316 valE = valE * 10 + (c - '0');
317 if (valE > 10000000) {
318 valE = 10000000;
319 }
320 } else {
321 throw new NumberFormatException("For input characters: \"" + chars.toString() + "\"");
322 }
323 if (++i >= length) {
324 break;
325 }
326 }
327 exp += negE ? -valE : valE;
328 }
329
330
331 return multE(result, exp);
332
333 } catch (IndexOutOfBoundsException e) {
334 throw new NumberFormatException("For input characters: \"" + chars.toString() + "\"");
335 }
336 }
337
338
339
340
341
342
343
344
345
346
347 public static StringBuffer format(boolean b, StringBuffer sb) {
348 return b ? sb.append("true") : sb.append("false");
349 }
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365 public static StringBuffer format(short s, StringBuffer sb) {
366 return format((int) s, sb);
367 }
368
369
370
371
372
373
374
375
376
377
378
379 public static StringBuffer format(short s, int radix, StringBuffer sb) {
380 return format((int) s, radix, sb);
381 }
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397 public static StringBuffer format(int i, StringBuffer sb) {
398 if (i <= 0) {
399 if (i == Integer.MIN_VALUE) {
400 return sb.append("-2147483648");
401 } else if (i == 0) {
402 return sb.append('0');
403 }
404 i = -i;
405 sb.append('-');
406 }
407 int j = 1;
408 for (; (j < 10) && (i >= INT_POW_10[j]); j++) {}
409
410 for (j--; j >= 0; j--) {
411 int pow10 = INT_POW_10[j];
412 int digit = i / pow10;
413 i -= digit * pow10;
414 sb.append(DIGITS[digit]);
415 }
416 return sb;
417 }
418
419 private static final int[] INT_POW_10 = new int[10];
420
421 static {
422 int pow = 1;
423 for (int i = 0; i < 10; i++) {
424 INT_POW_10[i] = pow;
425 pow *= 10;
426 }
427 }
428
429
430
431
432
433
434
435
436
437
438
439 public static StringBuffer format(int i, int radix, StringBuffer sb) {
440 if (radix == 10) {
441 return format(i, sb);
442 } else if (radix < 2 || radix > 36) {
443 throw new IllegalArgumentException("radix: " + radix);
444 }
445 if (i < 0) {
446 sb.append('-');
447 } else {
448 i = -i;
449 }
450 format2(i, radix, sb);
451 return sb;
452 }
453
454 private static void format2(int i, int radix, StringBuffer sb) {
455 if (i <= -radix) {
456 format2(i / radix, radix, sb);
457 sb.append(DIGITS[-(i % radix)]);
458 } else {
459 sb.append(DIGITS[-i]);
460 }
461 }
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477 public static StringBuffer format(long l, StringBuffer sb) {
478 if (l <= 0) {
479 if (l == Long.MIN_VALUE) {
480 return sb.append("-9223372036854775808");
481 } else if (l == 0) {
482 return sb.append('0');
483 }
484 l = -l;
485 sb.append('-');
486 }
487 int j = 1;
488 for (; (j < 19) && (l >= LONG_POW_10[j]); j++) {}
489
490 for (j--; j >= 0; j--) {
491 long pow10 = LONG_POW_10[j];
492 int digit = (int) (l / pow10);
493 l -= digit * pow10;
494 sb.append(DIGITS[digit]);
495 }
496 return sb;
497 }
498
499 private static final long[] LONG_POW_10 = new long[19];
500
501 static {
502 long pow = 1;
503 for (int i = 0; i < 19; i++) {
504 LONG_POW_10[i] = pow;
505 pow *= 10;
506 }
507 }
508
509
510
511
512
513
514
515
516
517
518
519 public static StringBuffer format(long l, int radix, StringBuffer sb) {
520 if (radix == 10) {
521 return format(l, sb);
522 } else if (radix < 2 || radix > 36) {
523 throw new IllegalArgumentException("radix: " + radix);
524 }
525 if (l < 0) {
526 sb.append('-');
527 } else {
528 l = -l;
529 }
530 format2(l, radix, sb);
531 return sb;
532 }
533
534 private static void format2(long l, int radix, StringBuffer sb) {
535 if (l <= -radix) {
536 format2(l / radix, radix, sb);
537 sb.append(DIGITS[(int) -(l % radix)]);
538 } else {
539 sb.append(DIGITS[(int) -l]);
540 }
541 }
542
543
544
545
546
547
548
549
550
551
552 public static StringBuffer format(float f, StringBuffer sb) {
553 return format(f, 0.0f, sb);
554 }
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575 public static StringBuffer format(float f, float precision, StringBuffer sb) {
576
577 boolean precisionOnLastDigit;
578 if (precision > 0.0f) {
579 precisionOnLastDigit = true;
580 } else if (precision == 0.0f) {
581 if (f != 0.0f) {
582 precisionOnLastDigit = false;
583 precision = Math.max(Math.abs(f * FLOAT_RELATIVE_ERROR), Float.MIN_VALUE);
584 } else {
585 return sb.append("0.0");
586 }
587 } else {
588 throw new IllegalArgumentException("precision: Negative values not allowed");
589 }
590 return format(f, precision, precisionOnLastDigit, sb);
591 }
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609 public static StringBuffer format(double d, StringBuffer sb) {
610 return format(d, 0.0, sb);
611 }
612
613
614
615
616
617
618
619
620
621
622
623 public static StringBuffer format(double d, int digits, StringBuffer sb) {
624 if ((digits >= 1) && (digits <= 19)) {
625 double precision = Math.abs(d / DOUBLE_POW_10[digits - 1]);
626 return format(d, precision, sb);
627 } else {
628 throw new java.lang.IllegalArgumentException("digits: " + digits + " is not in range [1 .. 19]");
629 }
630 }
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651 public static StringBuffer format(double d, double precision, StringBuffer sb) {
652
653 boolean precisionOnLastDigit = false;
654 if (precision > 0.0) {
655 precisionOnLastDigit = true;
656 } else if (precision == 0.0) {
657 if (d != 0.0) {
658 precision = Math.max(Math.abs(d * DOUBLE_RELATIVE_ERROR), Double.MIN_VALUE);
659 } else {
660 return sb.append("0.0");
661 }
662 } else if (precision < 0.0) {
663 throw new IllegalArgumentException("precision: Negative values not allowed");
664 }
665 return format(d, precision, precisionOnLastDigit, sb);
666 }
667
668
669
670
671
672
673
674
675
676
677
678 private static StringBuffer format(double d, double precision, boolean precisionOnLastDigit, StringBuffer sb) {
679
680 if (Double.isNaN(d)) {
681 return sb.append("NaN");
682 } else if (Double.isInfinite(d)) {
683 return (d >= 0) ? sb.append("Infinity") : sb.append("-Infinity");
684 }
685 if (d < 0) {
686 d = -d;
687 sb.append('-');
688 }
689
690
691 int rank = (int) Math.floor(Math.log(precision) / LOG_10);
692 double digitValue = multE(d, -rank);
693 if (digitValue >= Long.MAX_VALUE) {
694 throw new IllegalArgumentException("Specified precision would result in too many digits");
695 }
696 int digitStart = sb.length();
697 format(Math.round(digitValue), sb);
698 int digitLength = sb.length() - digitStart;
699 int dotPos = digitLength + rank;
700 boolean useScientificNotation = false;
701
702
703 if ((dotPos <= -LEADING_ZEROS.length) || (dotPos > digitLength)) {
704
705 sb.insert(digitStart + 1, '.');
706 useScientificNotation = true;
707 } else if (dotPos > 0) {
708
709 sb.insert(digitStart + dotPos, '.');
710 } else {
711
712 sb.insert(digitStart, LEADING_ZEROS[-dotPos]);
713 }
714
715
716 if (!precisionOnLastDigit) {
717 int newLength = sb.length();
718 do {
719 newLength--;
720 } while (sb.charAt(newLength) == '0');
721 sb.setLength(newLength + 1);
722 }
723
724
725 if (sb.charAt(sb.length() - 1) == '.') {
726 if (precisionOnLastDigit) {
727 sb.setLength(sb.length() - 1);
728 } else {
729 sb.append('0');
730 }
731 }
732
733
734 if (useScientificNotation) {
735 sb.append('E');
736 format(dotPos - 1, sb);
737 }
738
739 return sb;
740 }
741
742 private static final double LOG_10 = Math.log(10);
743
744 private static final float FLOAT_RELATIVE_ERROR = (float) Math.pow(2, -24);
745
746 private static final double DOUBLE_RELATIVE_ERROR = Math.pow(2, -53);
747
748 private static String[] LEADING_ZEROS = {"0.", "0.0", "0.00"};
749
750
751
752
753
754
755
756
757 private static final double multE(double value, int E) {
758 if (E >= 0) {
759 if (E <= 308) {
760
761 return value * DOUBLE_POW_10[E];
762 } else {
763 value *= 1E21;
764 E = Math.min(308, E - 21);
765 return value * DOUBLE_POW_10[E];
766 }
767 } else {
768 if (E >= -308) {
769 return value / DOUBLE_POW_10[-E];
770 } else {
771
772 value /= 1E21;
773 E = Math.max(-308, E + 21);
774 return value / DOUBLE_POW_10[-E];
775 }
776 }
777 }
778
779
780
781 private static final double[] DOUBLE_POW_10 = new double[] {
782 1E000, 1E001, 1E002, 1E003, 1E004, 1E005, 1E006, 1E007, 1E008, 1E009, 1E010, 1E011, 1E012, 1E013, 1E014, 1E015,
783 1E016, 1E017, 1E018, 1E019, 1E020, 1E021, 1E022, 1E023, 1E024, 1E025, 1E026, 1E027, 1E028, 1E029, 1E030, 1E031,
784 1E032, 1E033, 1E034, 1E035, 1E036, 1E037, 1E038, 1E039, 1E040, 1E041, 1E042, 1E043, 1E044, 1E045, 1E046, 1E047,
785 1E048, 1E049, 1E050, 1E051, 1E052, 1E053, 1E054, 1E055, 1E056, 1E057, 1E058, 1E059, 1E060, 1E061, 1E062, 1E063,
786 1E064, 1E065, 1E066, 1E067, 1E068, 1E069, 1E070, 1E071, 1E072, 1E073, 1E074, 1E075, 1E076, 1E077, 1E078, 1E079,
787 1E080, 1E081, 1E082, 1E083, 1E084, 1E085, 1E086, 1E087, 1E088, 1E089, 1E090, 1E091, 1E092, 1E093, 1E094, 1E095,
788 1E096, 1E097, 1E098, 1E099, 1E100, 1E101, 1E102, 1E103, 1E104, 1E105, 1E106, 1E107, 1E108, 1E109, 1E110, 1E111,
789 1E112, 1E113, 1E114, 1E115, 1E116, 1E117, 1E118, 1E119, 1E120, 1E121, 1E122, 1E123, 1E124, 1E125, 1E126, 1E127,
790 1E128, 1E129, 1E130, 1E131, 1E132, 1E133, 1E134, 1E135, 1E136, 1E137, 1E138, 1E139, 1E140, 1E141, 1E142, 1E143,
791 1E144, 1E145, 1E146, 1E147, 1E148, 1E149, 1E150, 1E151, 1E152, 1E153, 1E154, 1E155, 1E156, 1E157, 1E158, 1E159,
792 1E160, 1E161, 1E162, 1E163, 1E164, 1E165, 1E166, 1E167, 1E168, 1E169, 1E170, 1E171, 1E172, 1E173, 1E174, 1E175,
793 1E176, 1E177, 1E178, 1E179, 1E180, 1E181, 1E182, 1E183, 1E184, 1E185, 1E186, 1E187, 1E188, 1E189, 1E190, 1E191,
794 1E192, 1E193, 1E194, 1E195, 1E196, 1E197, 1E198, 1E199, 1E200, 1E201, 1E202, 1E203, 1E204, 1E205, 1E206, 1E207,
795 1E208, 1E209, 1E210, 1E211, 1E212, 1E213, 1E214, 1E215, 1E216, 1E217, 1E218, 1E219, 1E220, 1E221, 1E222, 1E223,
796 1E224, 1E225, 1E226, 1E227, 1E228, 1E229, 1E230, 1E231, 1E232, 1E233, 1E234, 1E235, 1E236, 1E237, 1E238, 1E239,
797 1E240, 1E241, 1E242, 1E243, 1E244, 1E245, 1E246, 1E247, 1E248, 1E249, 1E250, 1E251, 1E252, 1E253, 1E254, 1E255,
798 1E256, 1E257, 1E258, 1E259, 1E260, 1E261, 1E262, 1E263, 1E264, 1E265, 1E266, 1E267, 1E268, 1E269, 1E270, 1E271,
799 1E272, 1E273, 1E274, 1E275, 1E276, 1E277, 1E278, 1E279, 1E280, 1E281, 1E282, 1E283, 1E284, 1E285, 1E286, 1E287,
800 1E288, 1E289, 1E290, 1E291, 1E292, 1E293, 1E294, 1E295, 1E296, 1E297, 1E298, 1E299, 1E300, 1E301, 1E302, 1E303,
801 1E304, 1E305, 1E306, 1E307, 1E308
802 };
803 }