KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > core > misc > Format


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64
65 package com.jcorporate.expresso.core.misc;
66
67 /*
68  * Format.java
69  *
70  * Copyright 1999, 2000, 2001 Jcorporate Ltd.
71  */

72
73 import java.io.PrintStream JavaDoc;
74 import java.io.PrintWriter JavaDoc;
75
76
77 /**
78  * @author Michael Nash
79  */

80 public class Format {
81     private int width;
82     private int precision;
83     private String JavaDoc pre;
84     private String JavaDoc post;
85     private boolean leadingZeroes;
86     private boolean showPlus;
87     private boolean alternate;
88     private boolean showSpace;
89     private boolean leftAlign;
90     private char fmt; // one of cdeEfgGiosxXos
91

92     /**
93      * Formats a number in a printf format, like C
94      *
95      * @param s the format string following printf format string
96      * The string has a prefix, a format code and a suffix. The prefix and suffix
97      * become part of the formatted output. The format code directs the
98      * formatting of the (single) parameter to be formatted. The code has the
99      * following structure
100      * <ul>
101      * <li> a % (required)
102      * <li> a modifier (optional)
103      * <dl>
104      * <dt> + <dd> forces display of + for positive numbers
105      * <dt> 0 <dd> show leading zeroes
106      * <dt> - <dd> align left in the field
107      * <dt> space <dd> prepend a space in front of positive numbers
108      * <dt> # <dd> use "alternate" format. Add 0 or 0x for octal or hexadecimal numbers.
109      * Don't suppress trailing zeroes in general floating point format.
110      * </dl>
111      * <li> an integer denoting field width (optional)
112      * <li> a period followed by an integer denoting precision (optional)
113      * <li> a format descriptor (required)
114      * <dl>
115      * <dt>f <dd> floating point number in fixed format
116      * <dt>e, E <dd> floating point number in exponential notation (scientific format).
117      * The E format results in an uppercase E for the exponent (1.14130E+003), the e
118      * format in a lowercase e.
119      * <dt>g, G <dd> floating point number in general format (fixed format for small
120      * numbers, exponential format for large numbers). Trailing zeroes are suppressed.
121      * The G format results in an uppercase E for the exponent (if any), the g format
122      * in a lowercase e.
123      * <dt>d, i <dd> integer in decimal
124      * <dt>x <dd> integer in hexadecimal
125      * <dt>o <dd> integer in octal
126      * <dt>s <dd> string
127      * <dt>c <dd> character
128      * </dl>
129      * </ul>
130      */

131     public Format(String JavaDoc s) {
132         width = 0;
133         precision = -1;
134         pre = "";
135         post = "";
136         leadingZeroes = false;
137         showPlus = false;
138         alternate = false;
139         showSpace = false;
140         leftAlign = false;
141         fmt = ' ';
142
143         int length = s.length();
144         int parseState = 0;
145
146         // 0 = prefix, 1 = flags, 2 = width, 3 = precision,
147
// 4 = format, 5 = end
148
int i = 0;
149
150         while (parseState == 0) {
151             if (i >= length) {
152                 parseState = 5;
153             } else if (s.charAt(i) == '%') {
154                 if (i < length - 1) {
155                     if (s.charAt(i + 1) == '%') {
156                         pre = pre + '%';
157                         i++;
158                     } else {
159                         parseState = 1;
160                     }
161                 } else {
162                     throw new java.lang.IllegalArgumentException JavaDoc();
163                 }
164             } else {
165                 pre = pre + s.charAt(i);
166             }
167
168             i++;
169         } /* while parseState == 0 */
170
171         while (parseState == 1) {
172             if (i >= length) {
173                 parseState = 5;
174             } else if (s.charAt(i) == ' ') {
175                 showSpace = true;
176             } else if (s.charAt(i) == '-') {
177                 leftAlign = true;
178             } else if (s.charAt(i) == '+') {
179                 showPlus = true;
180             } else if (s.charAt(i) == '0') {
181                 leadingZeroes = true;
182             } else if (s.charAt(i) == '#') {
183                 alternate = true;
184             } else {
185                 parseState = 2;
186                 i--;
187             }
188
189             i++;
190         } /* while parseState == 1 */
191
192         while (parseState == 2) {
193             if (i >= length) {
194                 parseState = 5;
195             } else if ('0' <= s.charAt(i) && s.charAt(i) <= '9') {
196                 width = width * 10 + s.charAt(i) - '0';
197                 i++;
198             } else if (s.charAt(i) == '.') {
199                 parseState = 3;
200                 precision = 0;
201                 i++;
202             } else {
203                 parseState = 4;
204             }
205         } /* while parseState == 2 */
206
207         while (parseState == 3) {
208             if (i >= length) {
209                 parseState = 5;
210             } else if ('0' <= s.charAt(i) && s.charAt(i) <= '9') {
211                 precision = precision * 10 + s.charAt(i) - '0';
212                 i++;
213             } else {
214                 parseState = 4;
215             }
216         } /* while parseState == 3 */
217
218         if (parseState == 4) {
219             if (i >= length) {
220                 parseState = 5;
221             } else {
222                 fmt = s.charAt(i);
223             }
224
225             i++;
226         }
227         if (i < length) {
228             post = s.substring(i, length);
229         }
230     } /* Format(String) */
231
232     /**
233      * Converts a string of digits to an double
234      *
235      * @param s a string
236      * @return
237      */

238     public static double atof(String JavaDoc s) {
239         int i = 0;
240         int sign = 1;
241         double r = 0; // integer part
242
double f = 0; // fractional part
243
double p = 1; // exponent of fractional part
244
int state = 0; // 0 = int part, 1 = frac part
245

246         while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
247             i++;
248         }
249         if (i < s.length() && s.charAt(i) == '-') {
250             sign = -1;
251             i++;
252         } else if (i < s.length() && s.charAt(i) == '+') {
253             i++;
254         }
255         while (i < s.length()) {
256             char ch = s.charAt(i);
257
258             if ('0' <= ch && ch <= '9') {
259                 if (state == 0) {
260                     r = r * 10 + ch - '0';
261                 } else if (state == 1) {
262                     p = p / 10;
263                     r = r + p * (ch - '0');
264                 }
265             } else if (ch == '.') {
266                 if (state == 0) {
267                     state = 1;
268                 } else {
269                     return sign * r;
270                 }
271             } else if (ch == 'e' || ch == 'E') {
272                 long e = (int) parseLong(s.substring(i + 1), 10);
273
274                 return sign * r * Math.pow(10, e);
275             } else {
276                 return sign * r;
277             }
278
279             i++;
280         }
281
282         return sign * r;
283     } /* atof(String) */
284
285     /**
286      * Converts a string of digits (decimal, octal or hex) to an integer
287      *
288      * @param s a string
289      * @return the numeric value of the prefix of s representing a
290      * base 10 integer
291      */

292     public static int atoi(String JavaDoc s) {
293         return (int) atol(s);
294     } /* atoi(String) */
295
296     /**
297      * Converts a string of digits (decimal, octal or hex) to a long integer
298      *
299      * @param s a string
300      * @return the numeric value of the prefix of s representing a
301      * base 10 integer
302      */

303     public static long atol(String JavaDoc s) {
304         int i = 0;
305
306         while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
307             i++;
308         }
309         if (i < s.length() && s.charAt(i) == '0') {
310             if (i + 1 < s.length() &&
311                     (s.charAt(i + 1) == 'x' || s.charAt(i + 1) == 'X')) {
312                 return parseLong(s.substring(i + 2), 16);
313             } else {
314                 return parseLong(s, 8);
315             }
316         } else {
317             return parseLong(s, 10);
318         }
319     } /* atol(String) */
320
321     /**
322      * @param x
323      * @param n
324      * @param m
325      * @param d
326      * @return
327      */

328     private static String JavaDoc convert(long x, int n, int m, String JavaDoc d) {
329         if (x == 0) {
330             return ("0");
331         }
332
333         String JavaDoc r = "";
334
335         while (x != 0) {
336             r = d.charAt((int) (x & m)) + r;
337             x = x >>> n;
338         }
339
340         return r;
341     } /* convert(long, int, int, String) */
342
343     /**
344      * @param d
345      * @return
346      */

347     private String JavaDoc expFormat(double d) {
348         String JavaDoc f = "";
349         int e = 0;
350         double dd = d;
351         double factor = 1;
352
353         if (d != 0) {
354             while (dd > 10) {
355                 e++;
356                 factor /= 10;
357                 dd = dd / 10;
358             }
359             while (dd < 1) {
360                 e--;
361                 factor *= 10;
362                 dd = dd * 10;
363             }
364         }
365         if ((fmt == 'g' || fmt == 'G') && e >= -4 && e < precision) {
366             return fixedFormat(d);
367         }
368
369         d = d * factor;
370         f = f + fixedFormat(d);
371
372         if (fmt == 'e' || fmt == 'g') {
373             f = f + "e";
374         } else {
375             f = f + "E";
376         }
377
378         String JavaDoc p = "000";
379
380         if (e >= 0) {
381             f = f + "+";
382             p = p + e;
383         } else {
384             f = f + "-";
385             p = p + (-e);
386         }
387
388         return f + p.substring(p.length() - 3, p.length());
389     } /* expFormat(double) */
390
391     /**
392      * @param d
393      * @return
394      */

395     private String JavaDoc fixedFormat(double d) {
396         boolean removeTrailing = (fmt == 'G' || fmt == 'g') && !alternate;
397
398         // remove trailing zeroes and decimal point
399
if (d > 0x7FFFFFFFFFFFFFFFL) {
400             return expFormat(d);
401         }
402         if (precision == 0) {
403             return (long) (d + 0.5) + (removeTrailing ? "" : ".");
404         }
405
406         long whole = (long) d;
407         double fr = d - whole; // fractional part
408

409         if (fr >= 1 || fr < 0) {
410             return expFormat(d);
411         }
412
413         double factor = 1;
414         String JavaDoc leadingZeroes = "";
415
416         for (int i = 1; i <= precision && factor <= 0x7FFFFFFFFFFFFFFFL; i++) {
417             factor *= 10;
418             leadingZeroes = leadingZeroes + "0";
419         }
420
421         long l = (long) (factor * fr + 0.5);
422
423         if (l >= factor) { // CSH 10-25-97
424
l = 0;
425             whole++;
426         }
427
428         String JavaDoc z = leadingZeroes + l;
429         z = "." + z.substring(z.length() - precision, z.length());
430
431         if (removeTrailing) {
432             int t = z.length() - 1;
433
434             while (t >= 0 && z.charAt(t) == '0') {
435                 t--;
436             }
437             if (t >= 0 && z.charAt(t) == '.') {
438                 t--;
439             }
440
441             z = z.substring(0, t + 1);
442         }
443
444         return whole + z;
445     } /* fixedFormat(double) */
446
447     /**
448      * Formats a character into a string (like sprintf in C)
449      *
450      * @param c the value to format
451      * @return the formatted string
452      */

453     public String JavaDoc form(char c) {
454         if (fmt != 'c') {
455             throw new java.lang.IllegalArgumentException JavaDoc();
456         }
457
458         String JavaDoc r = "" + c;
459
460         return pad(r);
461     } /* form(char) */
462
463     /**
464      * Formats a double into a string (like sprintf in C)
465      *
466      * @param x the number to format
467      * @return the formatted string
468      */

469     public String JavaDoc form(double x) {
470         String JavaDoc r;
471
472         if (precision < 0) {
473             precision = 6;
474         }
475
476         int s = 1;
477
478         if (x < 0) {
479             x = -x;
480             s = -1;
481         }
482         if (fmt == 'f') {
483             r = fixedFormat(x);
484         } else if (fmt == 'e' || fmt == 'E' || fmt == 'g' || fmt == 'G') {
485             r = expFormat(x);
486         } else {
487             throw new java.lang.IllegalArgumentException JavaDoc();
488         }
489
490         return pad(sign(s, r));
491     } /* form(double) */
492
493     /**
494      * Formats a long integer into a string (like sprintf in C)
495      *
496      * @param x the number to format
497      * @return the formatted string
498      */

499     public String JavaDoc form(long x) {
500         String JavaDoc r;
501         int s = 0;
502
503         if (fmt == 'd' || fmt == 'i') {
504             if (x < 0) {
505                 r = ("" + x).substring(1);
506                 s = -1;
507             } else {
508                 r = "" + x;
509                 s = 1;
510             }
511         } else if (fmt == 'o') {
512             r = convert(x, 3, 7, "01234567");
513         } else if (fmt == 'x') {
514             r = convert(x, 4, 15, "0123456789abcdef");
515         } else if (fmt == 'X') {
516             r = convert(x, 4, 15, "0123456789ABCDEF");
517         } else {
518             throw new java.lang.IllegalArgumentException JavaDoc();
519         }
520
521         return pad(sign(s, r));
522     } /* form(long) */
523
524     /**
525      * Formats a string into a larger string (like sprintf in C)
526      *
527      * @param s the value to format
528      * @return the formatted string
529      */

530     public String JavaDoc form(String JavaDoc s) {
531         if (fmt != 's') {
532             throw new java.lang.IllegalArgumentException JavaDoc();
533         }
534         if (precision >= 0 && precision < s.length()) {
535             s = s.substring(0, precision);
536         }
537
538         return pad(s);
539     } /* form(String) */
540
541     /**
542      * @param r
543      * @return
544      */

545     private String JavaDoc pad(String JavaDoc r) {
546         String JavaDoc p = repeat(' ', width - r.length());
547
548         if (leftAlign) {
549             return pre + r + p + post;
550         } else {
551             return pre + p + r + post;
552         }
553     } /* pad(String) */
554
555     /**
556      * @param s
557      * @param base
558      * @return
559      */

560     private static long parseLong(String JavaDoc s, int base) {
561         int i = 0;
562         int sign = 1;
563         long r = 0;
564
565         while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
566             i++;
567         }
568         if (i < s.length() && s.charAt(i) == '-') {
569             sign = -1;
570             i++;
571         } else if (i < s.length() && s.charAt(i) == '+') {
572             i++;
573         }
574         while (i < s.length()) {
575             char ch = s.charAt(i);
576
577             if ('0' <= ch && ch < '0' + base) {
578                 r = r * base + ch - '0';
579             } else if ('A' <= ch && ch < 'A' + base - 10) {
580                 r = r * base + ch - 'A' + 10;
581             } else if ('a' <= ch && ch < 'a' + base - 10) {
582                 r = r * base + ch - 'a' + 10;
583             } else {
584                 return r * sign;
585             }
586
587             i++;
588         }
589
590         return r * sign;
591     } /* parseLong(String, int) */
592
593     /**
594      * prints a formatted number following printf conventions
595      *
596      * @param s a PrintStream
597      * @param fmt the format string
598      * @param x the character to
599      */

600     public static void print(PrintStream JavaDoc s, String JavaDoc fmt, char x) {
601         s.print(new Format(fmt).form(x));
602     } /* print(PrintStream, String, char) */
603
604     /**
605      * prints a formatted number following printf conventions
606      *
607      * @param s a PrintStream
608      * @param fmt the format string
609      * @param x the double to print
610      */

611     public static void print(PrintStream JavaDoc s, String JavaDoc fmt, double x) {
612         s.print(new Format(fmt).form(x));
613     } /* print(PrintStream, String, double) */
614
615     /**
616      * prints a formatted number following printf conventions
617      *
618      * @param s a PrintStream
619      * @param fmt the format string
620      * @param x the long to print
621      */

622     public static void print(PrintStream JavaDoc s, String JavaDoc fmt, long x) {
623         s.print(new Format(fmt).form(x));
624     } /* print(PrintStream, String, long) */
625
626     /**
627      * prints a formatted number following printf conventions
628      *
629      * @param s a PrintStream, fmt the format string
630      * @param fmt
631      * @param x a string that represents the digits to print
632      */

633     public static void print(PrintStream JavaDoc s, String JavaDoc fmt, String JavaDoc x) {
634         s.print(new Format(fmt).form(x));
635     } /* print(PrintStream, String, String) */
636
637     /**
638      * prints a formatted number following printf conventions
639      *
640      * @param s a PrintStream
641      * @param fmt the format string
642      * @param x the double to print
643      */

644     public static void print(PrintWriter JavaDoc s, String JavaDoc fmt, double x) {
645         s.print(new Format(fmt).form(x));
646     } /* print(PrintWriter, String, double) */
647
648     /**
649      * prints a formatted number following printf conventions
650      *
651      * @param s a PrintStream, fmt the format string
652      * @param fmt
653      * @param x a string that represents the digits to print
654      */

655     public static void print(PrintWriter JavaDoc s, String JavaDoc fmt, String JavaDoc x) {
656         s.print(new Format(fmt).form(x));
657     } /* print(PrintWriter, String, String) */
658
659     /**
660      * @param c
661      * @param n
662      * @return
663      */

664     private static String JavaDoc repeat(char c, int n) {
665         if (n <= 0) {
666             return ("");
667         }
668
669         StringBuffer JavaDoc s = new StringBuffer JavaDoc(n);
670
671         for (int i = 0; i < n; i++) {
672             s.append(c);
673         }
674
675         return s.toString();
676     } /* repeat(char, int) */
677
678     /**
679      * @param s
680      * @param r
681      * @return
682      */

683     private String JavaDoc sign(int s, String JavaDoc r) {
684         String JavaDoc p = ("");
685
686         if (s < 0) {
687             p = "-";
688         } else if (s > 0) {
689             if (showPlus) {
690                 p = "+";
691             } else if (showSpace) {
692                 p = " ";
693             }
694         } else {
695             if (fmt == 'o' && alternate && r.length() > 0 &&
696                     r.charAt(0) != '0') {
697                 p = "0";
698             } else if (fmt == 'x' && alternate) {
699                 p = "0x";
700             } else if (fmt == 'X' && alternate) {
701                 p = "0X";
702             }
703         }
704
705         int w = 0;
706
707         if (leadingZeroes) {
708             w = width;
709         } else if ((fmt == 'd' || fmt == 'i' || fmt == 'x' || fmt == 'X' ||
710                 fmt == 'o') && precision > 0) {
711             w = precision;
712         }
713
714         return p + repeat('0', w - p.length() - r.length()) + r;
715     } /* sign(int, String) */
716
717 } /* Format */
718
Popular Tags