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