KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jodd > format > Format


1 package jodd.format;
2
3 import java.util.ArrayList;
4
5 /**
6  * Fast, simple, and yet useful formattings.
7  */

8 public class Format {
9     private int width;
10     private int precision;
11     private String pre;
12     private String post;
13     private boolean leadingZeroes;
14     private boolean showPlus;
15     private boolean alternate;
16     private boolean showSpace;
17     private boolean leftAlign;
18     private char fmt; // one of cdeEfgGiosxXos
19
private boolean countSignInLen;
20
21     /**
22      * Formats a number in a printf format, like C
23      *
24      * @param s the format string following printf format string
25      * The string has a prefix, a format code and a suffix. The prefix and suffix
26      * become part of the formatted output. The format code directs the
27      * formatting of the (single) parameter to be formatted. The code has the
28      * following structure
29      * <ul>
30      * <li> a % (required)
31      * <li> a modifier (optional)
32      * <dl>
33      * <dt> + <dd> forces display of + for positive numbers
34      * <dt> ~ <dd> do not count leading + or - in length
35      * <dt> 0 <dd> show leading zeroes
36      * <dt> - <dd> align left in the field
37      * <dt> space <dd> prepend a space in front of positive numbers
38      * <dt> # <dd> use "alternate" format. Add 0 or 0x for octal or hexadecimal numbers.
39      * Don't suppress trailing zeroes in general floating point format.
40      * </dl>
41      * <li> an integer denoting field width (optional)
42      * <li> a period followed by an integer denoting precision (optional)
43      * <li> a format descriptor (required)
44      * <dl>
45      * <dt>f <dd> floating point number in fixed format
46      * <dt>e, E <dd> floating point number in exponential notation (scientific format).
47      * The E format results in an uppercase E for the exponent (1.14130E+003), the e
48      * format in a lowercase e.
49      * <dt>g, G <dd> floating point number in general format (fixed format for small
50      * numbers, exponential format for large numbers). Trailing zeroes are suppressed.
51      * The G format results in an uppercase E for the exponent (if any), the g format
52      * in a lowercase e.
53      * <dt>d, i <dd> signed long integer and integer in decimal
54      * <dt>u <dd> unsigned integer in decimal
55      * <dt>x <dd> unsigned integer in hexadecimal
56      * <dt>o <dd> unsigned integer in octal
57      * <dt>s <dd> string
58      * <dt>c <dd> character
59      * </dl>
60      * </ul>
61      */

62     public Format(String s) {
63         width = 0;
64         precision = -1;
65         pre = "";
66         post = "";
67         leadingZeroes = false;
68         showPlus = false;
69         alternate = false;
70         showSpace = false;
71         leftAlign = false;
72         countSignInLen = true;
73         fmt = ' ';
74
75         int state = 0;
76         int length = s.length();
77         int parseState = 0;
78
79         // 0 = prefix, 1 = flags, 2 = width, 3 = precision,
80
// 4 = format, 5 = end
81
int i = 0;
82
83         while (parseState == 0) {
84             if (i >= length) {
85                 parseState = 5;
86             } else if (s.charAt(i) == '%') {
87                 if (i < length - 1) {
88                     if (s.charAt(i + 1) == '%') {
89                         pre = pre + '%';
90                         i++;
91                     } else {
92                         parseState = 1;
93                     }
94                 } else {
95                     throw new java.lang.IllegalArgumentException();
96                 }
97             } else {
98                 pre = pre + s.charAt(i);
99             }
100             i++;
101         }
102
103         while (parseState == 1) {
104             if (i >= length) {
105                 parseState = 5;
106             } else if (s.charAt(i) == ' ') {
107                 showSpace = true;
108             } else if (s.charAt(i) == '-') {
109                 leftAlign = true;
110             } else if (s.charAt(i) == '+') {
111                 showPlus = true;
112             } else if (s.charAt(i) == '0') {
113                 leadingZeroes = true;
114             } else if (s.charAt(i) == '#') {
115                 alternate = true;
116             } else if (s.charAt(i) == '~') {
117                 countSignInLen = false;
118             } else {
119                 parseState = 2;
120                 i--;
121             }
122             i++;
123         }
124
125         while (parseState == 2) {
126             if (i >= length) {
127                 parseState = 5;
128             } else if ('0' <= s.charAt(i) && s.charAt(i) <= '9') {
129                 width = width * 10 + s.charAt(i) - '0';
130                 i++;
131             } else if (s.charAt(i) == '.') {
132                 parseState = 3;
133                 precision = 0;
134                 i++;
135             } else {
136                 parseState = 4;
137             }
138         }
139
140         while (parseState == 3) {
141             if (i >= length) {
142                 parseState = 5;
143             } else if ('0' <= s.charAt(i) && s.charAt(i) <= '9') {
144                 precision = precision * 10 + s.charAt(i) - '0';
145                 i++;
146             } else {
147                 parseState = 4;
148             }
149         }
150
151         if (parseState == 4) {
152             if (i >= length) {
153                 parseState = 5;
154             } else {
155                 fmt = s.charAt(i);
156             }
157
158             i++;
159         }
160         if (i < length) {
161             post = s.substring(i, length);
162         }
163     }
164
165
166     /**
167      *
168      * @param d
169      *
170      * @return
171      */

172     private String expFormat(double d) {
173         String f = "";
174         int e = 0;
175         double dd = d;
176         double factor = 1;
177
178         if (d != 0) {
179             while (dd > 10) {
180                 e++;
181                 factor /= 10;
182                 dd = dd / 10;
183             }
184             while (dd < 1) {
185                 e--;
186                 factor *= 10;
187                 dd = dd * 10;
188             }
189         }
190         if ((fmt == 'g' || fmt == 'G') && e >= -4 && e < precision) {
191             return fixedFormat(d);
192         }
193
194         d = d * factor;
195         f = f + fixedFormat(d);
196
197         if (fmt == 'e' || fmt == 'g') {
198             f = f + "e";
199         } else {
200             f = f + "E";
201         }
202
203         String p = "000";
204
205         if (e >= 0) {
206             f = f + "+";
207             p = p + e;
208         } else {
209             f = f + "-";
210             p = p + (-e);
211         }
212
213         return f + p.substring(p.length() - 3, p.length());
214     }
215
216     /**
217      *
218      * @param d
219      *
220      * @return
221      */

222     private String fixedFormat(double d) {
223         boolean removeTrailing = (fmt == 'G' || fmt == 'g') && !alternate;
224
225         // remove trailing zeroes and decimal point
226
if (d > 0x7FFFFFFFFFFFFFFFL) {
227             return expFormat(d);
228         }
229         if (precision == 0) {
230             return (long) (d /*+ 0.5*/) + (removeTrailing ? "" : "."); // no rounding
231
}
232
233         long whole = (long) d;
234         double fr = d - whole; // fractional part
235

236         if (fr >= 1 || fr < 0) {
237             return expFormat(d);
238         }
239
240         double factor = 1;
241         String leadingZeroes = "";
242
243         for (int i = 1; i <= precision && factor <= 0x7FFFFFFFFFFFFFFFL; i++) {
244             factor *= 10;
245             leadingZeroes = leadingZeroes + "0";
246         }
247
248         long l = (long) (factor * fr /*+ 0.5*/); // no rounding
249

250         if (l >= factor) {
251             l = 0;
252             whole++;
253         }
254
255         String z = leadingZeroes + l;
256         z = "." + z.substring(z.length() - precision, z.length());
257
258         if (removeTrailing) {
259             int t = z.length() - 1;
260
261             while (t >= 0 && z.charAt(t) == '0') {
262                 t--;
263             }
264             if (t >= 0 && z.charAt(t) == '.') {
265                 t--;
266             }
267
268             z = z.substring(0, t + 1);
269         }
270
271         return whole + z;
272     }
273
274
275     /**
276      *
277      * @param r
278      *
279      * @return
280      */

281     private String pad(String r) {
282         String p = repeat(' ', width - r.length());
283
284         if (leftAlign) {
285             return pre + r + p + post;
286         } else {
287             return pre + p + r + post;
288         }
289     }
290
291     /**
292      *
293      * @param s
294      * @param base
295      *
296      * @return
297      */

298     private static long parseLong(String s, int base) {
299         int i = 0;
300         int sign = 1;
301         long r = 0;
302
303         while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
304             i++;
305         }
306         if (i < s.length() && s.charAt(i) == '-') {
307             sign = -1;
308             i++;
309         } else if (i < s.length() && s.charAt(i) == '+') {
310             i++;
311         }
312         while (i < s.length()) {
313             char ch = s.charAt(i);
314
315             if ('0' <= ch && ch < '0' + base) {
316                 r = r * base + ch - '0';
317             } else if ('A' <= ch && ch < 'A' + base - 10) {
318                 r = r * base + ch - 'A' + 10;
319             } else if ('a' <= ch && ch < 'a' + base - 10) {
320                 r = r * base + ch - 'a' + 10;
321             } else {
322                 return r * sign;
323             }
324
325             i++;
326         }
327
328         return r * sign;
329     }
330     
331     /**
332      *
333      * @param c
334      * @param n
335      *
336      * @return
337      */

338     private static String repeat(char c, int n) {
339         if (n <= 0) {
340             return ("");
341         }
342
343         StringBuffer s = new StringBuffer(n);
344
345         for (int i = 0; i < n; i++) {
346             s.append(c);
347         }
348
349         return s.toString();
350     }
351
352     /**
353      *
354      * @param s
355      * @param r
356      *
357      * @return
358      */

359     private String sign(int s, String r) {
360         String p = "";
361
362         if (s < 0) {
363             p = "-";
364         } else if (s > 0) {
365             if (showPlus) {
366                 p = "+";
367             } else if (showSpace) {
368                 p = " ";
369             }
370         } else {
371             if (fmt == 'o' && alternate && r.length() > 0 && r.charAt(0) != '0') {
372                 p = "0";
373             } else if (fmt == 'x' && alternate) {
374                 p = "0x";
375             } else if (fmt == 'X' && alternate) {
376                 p = "0X";
377             }
378         }
379
380         int w = 0;
381
382         if (leadingZeroes) {
383             w = width;
384         } else if ((fmt == 'u' || fmt == 'd' || fmt == 'i' || fmt == 'x' || fmt == 'X' || fmt == 'o') && precision > 0) {
385             w = precision;
386         }
387
388         if (countSignInLen) {
389             return p + repeat('0', w - p.length() - r.length()) + r;
390         } else {
391             return p + repeat('0', w - r.length()) + r;
392         }
393     }
394
395     // ---------------------------------------------------------------- form methods
396

397     /**
398      * Formats a character into a string (like sprintf in C)
399      *
400      * @param c the value to format
401      *
402      * @return the formatted string
403      */

404     public String form(char c) {
405         if (fmt != 'c') {
406             throw new java.lang.IllegalArgumentException();
407         }
408
409         String r = "" + c;
410
411         return pad(r);
412     }
413     public String form(Character c) {
414         return form(c.charValue());
415     }
416
417
418     /**
419      * Formats a double into a string (like sprintf in C)
420      *
421      * @param x the number to format
422      *
423      * @return the formatted string
424      */

425     public String form(double x) {
426         String r;
427
428         if (precision < 0) {
429             precision = 6;
430         }
431
432         int s = 1;
433
434         if (x < 0) {
435             x = -x;
436             s = -1;
437         }
438         if (fmt == 'f') {
439             r = fixedFormat(x);
440         } else if (fmt == 'e' || fmt == 'E' || fmt == 'g' || fmt == 'G') {
441             r = expFormat(x);
442         } else {
443             throw new java.lang.IllegalArgumentException();
444         }
445
446         return pad(sign(s, r));
447     }
448     
449     public String form(Double x) {
450         return form(x.doubleValue());
451     }
452     public String form(Float x) {
453         return form(x.doubleValue());
454     }
455
456     /**
457      * Formats a long integer into a string (like sprintf in C)
458      *
459      * @param x the number to format
460      *
461      * @return the formatted string
462      */

463     public String form(long x) {
464         String r;
465         int s = 0;
466
467         if (fmt == 'd') {
468             if (x < 0) {
469                 r = ("" + x).substring(1);
470                 s = -1;
471             } else {
472                 r = "" + x;
473                 s = 1;
474             }
475         } else if (fmt == 'i') {
476             int xx = (int) x;
477             if (xx < 0) {
478                 r = ("" + xx).substring(1);
479                 s = -1;
480             } else {
481                 r = "" + xx;
482                 s = 1;
483             }
484         } else if (fmt == 'u') {
485             long xl = x & 0x00000000FFFFFFFFL;
486             r = "" + xl;
487             s = 1;
488         } else if (fmt == 'o') {
489             r = convert(x, 3, "01234567");
490         } else if (fmt == 'x') {
491             r = convert(x, 4, "0123456789abcdef");
492         } else if (fmt == 'X') {
493             r = convert(x, 4, "0123456789ABCDEF");
494         } else {
495             throw new java.lang.IllegalArgumentException();
496         }
497
498         return pad(sign(s, r));
499     }
500
501     public String form(Long x) {
502         return form(x.longValue());
503     }
504
505     /**
506      * Formats an integer into a string (like sprintf in C)
507      *
508      * @param x the number to format
509      *
510      * @return the formatted string
511      */

512     public String form(int x) {
513         String r;
514         int s = 0;
515
516         if (fmt == 'd' || fmt == 'i') {
517             if (x < 0) {
518                 r = ("" + x).substring(1);
519                 s = -1;
520             } else {
521                 r = "" + x;
522                 s = 1;
523             }
524         } else {
525             long xl = x & 0x00000000FFFFFFFFL;
526             if (fmt == 'u') {
527                 r = "" + xl;
528                 s = 1;
529             } else if (fmt == 'o') {
530                 r = convert(xl, 3, "01234567");
531             } else if (fmt == 'x') {
532                 r = convert(xl, 4, "0123456789abcdef");
533             } else if (fmt == 'X') {
534                 r = convert(xl, 4, "0123456789ABCDEF");
535             } else {
536                 throw new java.lang.IllegalArgumentException();
537             }
538         }
539
540         return pad(sign(s, r));
541     }
542
543     public String form(Integer x) {
544         return form(x.intValue());
545     }
546
547     /**
548      * Formats a string into a larger string (like sprintf in C)
549      *
550      * @param s the value to format
551      *
552      * @return the formatted string
553      */

554     public String form(String s) {
555         if (fmt != 's') {
556             throw new java.lang.IllegalArgumentException();
557         }
558         if (precision >= 0 && precision < s.length()) {
559             s = s.substring(0, precision);
560         }
561
562         return pad(s);
563     }
564
565
566     // ---------------------------------------------------------------- misc conversion
567

568     /**
569      * Converts a string of digits to an double
570      *
571      * @param s a string
572      *
573      * @return double converted from String
574      */

575     public static double atof(String s) {
576         int i = 0;
577         int sign = 1;
578         double r = 0; // integer part
579
double f = 0; // fractional part
580
double p = 1; // exponent of fractional part
581
int state = 0; // 0 = int part, 1 = frac part
582

583         while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
584             i++;
585         }
586         if (i < s.length() && s.charAt(i) == '-') {
587             sign = -1;
588             i++;
589         } else if (i < s.length() && s.charAt(i) == '+') {
590             i++;
591         }
592         while (i < s.length()) {
593             char ch = s.charAt(i);
594
595             if ('0' <= ch && ch <= '9') {
596                 if (state == 0) {
597                     r = r * 10 + ch - '0';
598                 } else if (state == 1) {
599                     p = p / 10;
600                     r = r + p * (ch - '0');
601                 }
602             } else if (ch == '.') {
603                 if (state == 0) {
604                     state = 1;
605                 } else {
606                     return sign * r;
607                 }
608             } else if (ch == 'e' || ch == 'E') {
609                 long e = (int) parseLong(s.substring(i + 1), 10);
610
611                 return sign * r * Math.pow(10, e);
612             } else {
613                 return sign * r;
614             }
615             i++;
616         }
617         return sign * r;
618     }
619
620     /**
621      * Converts a string of digits (decimal, octal or hex) to an integer
622      *
623      * @param s a string
624      *
625      * @return the numeric value of the prefix of s representing a
626      * base 10 integer
627      */

628     public static int atoi(String s) {
629         return (int) atol(s);
630     }
631
632     /**
633      * Converts a string of digits (decimal, octal or hex) to a long integer
634      *
635      * @param s a string
636      *
637      * @return the numeric value of the prefix of s representing a
638      * base 10 integer
639      */

640     public static long atol(String s) {
641         int i = 0;
642
643         while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
644             i++;
645         }
646         if (i < s.length() && s.charAt(i) == '0') {
647             if (i + 1 < s.length() &&
648                     (s.charAt(i + 1) == 'x' || s.charAt(i + 1) == 'X')) {
649                 return parseLong(s.substring(i + 2), 16);
650             } else {
651                 return parseLong(s, 8);
652             }
653         } else {
654             return parseLong(s, 10);
655         }
656     }
657
658     /**
659      * Converts number to string
660      *
661      * @param x value to convert
662      * @param n conversion base
663      * @param d string with characters for conversion.
664      *
665      * @return converted number as string
666      */

667     public static String convert(long x, int n, String d) {
668         if (x == 0) {
669             return "0";
670         }
671
672         String r = "";
673         int m = 1 << n;
674         m--;
675         while (x != 0) {
676             r = d.charAt((int) (x & m)) + r;
677             x = x >>> n;
678         }
679         return r;
680     }
681     
682     // ---------------------------------------------------------------- sprintf
683

684     /**
685      * prints a formatted number following printf conventions
686      *
687      * @param fmt the format string
688      * @param x the character to
689      *
690      * @return formated string
691      */

692     public static String sprintf(String fmt, char x) {
693         return new Format(fmt).form(x);
694     }
695
696     public static String sprintf(String fmt, Character x) {
697         return new Format(fmt).form(x);
698     }
699
700
701     /**
702      * prints a formatted number following printf conventions
703      *
704      * @param fmt the format string
705      * @param x the double to print
706      *
707      * @return formated string
708      */

709     public static String sprintf(String fmt, double x) {
710         return new Format(fmt).form(x);
711     }
712     public static String sprintf(String fmt, Double x) {
713         return new Format(fmt).form(x);
714     }
715     public static String sprintf(String fmt, Float x) {
716         return new Format(fmt).form(x);
717     }
718
719     /**
720      * prints a formatted number following printf conventions
721      *
722      * @param fmt the format string
723      * @param x the long to print
724      *
725      * @return formated string
726      */

727     public static String sprintf(String fmt, long x) {
728         return new Format(fmt).form(x);
729     }
730     public static String sprintf(String fmt, Long x) {
731         return new Format(fmt).form(x);
732     }
733
734     /**
735      * prints a formatted number following printf conventions
736      *
737      * @param fmt the format string
738      * @param x the int to print
739      *
740      * @return formated string
741      */

742     public static String sprintf(String fmt, int x) {
743         return new Format(fmt).form(x);
744     }
745     public static String sprintf(String fmt, Integer x) {
746         return new Format(fmt).form(x);
747     }
748
749     /**
750      * prints a formatted number following printf conventions
751      *
752      * @param fmt
753      * @param x a string that represents the digits to print
754      */

755     public static String sprintf(String fmt, String x) {
756         return new Format(fmt).form(x);
757     }
758
759     // ---------------------------------------------------------------- array sprintf
760

761     /**
762      * Splits input string on '%' and returns an array of substrings that can be
763      * used for multiple scanf. Each substring has a one-char prefix that can
764      * take one of two values:
765      * '+' wich indicates that substring can be simply added to the resulting string
766      * ' ' wich indicates that substring has to be additionally processed.
767      *
768      * @param s Input string
769      *
770      * @return splited input string
771      */

772     private static String[] split(String s) {
773         ArrayList list = new ArrayList();
774
775         int lasti = 0;
776         int i = s.indexOf("%");
777         if (i == -1) {
778             return new String[] {s};
779         }
780         if (i > 0) {
781             list.add("+" + s.substring(0, i));
782             lasti = i;
783             i++;
784             i = s.indexOf("%", i);
785         } else if (i == 0) {
786             i = s.indexOf("%", i + 1);
787         }
788         while (i != -1) {
789             String ss = s.substring(lasti, i);
790             if (ss.equals("%")) {
791                 lasti = i; i++;
792                 i = s.indexOf("%", i);
793                 if (i != -1) {
794                     ss = s.substring(lasti, i);
795                 } else {
796                     ss = s.substring(lasti);
797                 }
798                 list.add("+" + ss);
799             } else {
800                 list.add(" " + ss);
801             }
802             if (i == -1) {
803                 lasti = i;
804                 break;
805             }
806             lasti = i;
807             i++;
808             i = s.indexOf("%", i);
809         }
810         if (lasti != -1) {
811             list.add(" " + s.substring(lasti));
812         }
813
814         String[] ret = new String[list.size()];
815         for (i = 0; i < list.size(); i++) {
816             ret[i] = (String) list.get(i);
817         }
818         return ret;
819     }
820
821     /**
822      * Sprintf multiple strings.
823      *
824      * @param s
825      * @param params
826      *
827      * @return formated string
828      */

829     public static String sprintf(String s, Object[] params) {
830         if ((s == null) || (params == null)) {
831             return s;
832         }
833         StringBuffer result = new StringBuffer("");
834         String[] ss = split(s);
835         int p = 0;
836         for (int i = 0; i < ss.length; i++) {
837             char c = ss[i].charAt(0);
838             String t = ss[i].substring(1);
839             if (c == '+') {
840                 result.append(t);
841             } else {
842                 Object param = params[p];
843                 if (param instanceof Integer) {
844                     result.append(new Format(t).form((Integer) param));
845                 } else if (param instanceof Long) {
846                     result.append(new Format(t).form((Long) param));
847                 } else if (param instanceof Character) {
848                     result.append(new Format(t).form((Character) param));
849                 } else if (param instanceof Double) {
850                     result.append(new Format(t).form((Double) param));
851                 } else if (param instanceof Double) {
852                     result.append(new Format(t).form((Float) param));
853                 } else {
854                     result.append(new Format(t).form(param.toString()));
855                 }
856                 p++;
857             }
858         }
859         return result.toString();
860     }
861
862     public static String sprintf(String s, String[] params) {
863         return sprintf(s, (Object[]) params);
864     }
865
866     public static String sprintf(String s, Integer[] params) {
867         return sprintf(s, (Object[]) params);
868     }
869
870     public static String sprintf(String s, Long[] params) {
871         return sprintf(s, (Object[]) params);
872     }
873
874     public static String sprintf(String s, Double[] params) {
875         return sprintf(s, (Object[]) params);
876     }
877
878     public static String sprintf(String s, Float[] params) {
879         return sprintf(s, (Object[]) params);
880     }
881
882     public static String sprintf(String s, Character[] params) {
883         return sprintf(s, (Object[]) params);
884     }
885
886
887     // ---------------------------------------------------------------- primitives array sprintf
888

889     public static String sprintf(String s, int[] params) {
890         if ((s == null) || (params == null)) {
891             return s;
892         }
893         StringBuffer result = new StringBuffer("");
894         String[] ss = split(s);
895         int p = 0;
896         for (int i = 0; i < ss.length; i++) {
897             char c = ss[i].charAt(0);
898             String t = ss[i].substring(1);
899             if (c == '+') {
900                 result.append(t);
901             } else {
902                 int param = params[p];
903                 result.append(new Format(t).form(param));
904                 p++;
905             }
906         }
907         return result.toString();
908     }
909 }
910
Popular Tags