1
2
3
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 package org.dbforms.util.external;
48
49 import java.text.DateFormat;
50 import java.text.DecimalFormatSymbols;
51
52 import java.util.Date;
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 import java.util.Enumeration;
83 import java.util.Locale;
84 import java.util.Vector;
85
86
87
88 /***
89 * PrintfFormat allows the formatting of an array of objects embedded within a
90 * string. Primitive types must be passed using wrapper types. The
91 * formatting is controlled by a control string.
92 * @author Allan Jacobs
93 * @version 1 Release 1: Initial release. Release 2: Asterisk field widths and precisions %n$ and m$ Bug fixes g format fix (2 digits in e form corrupt) rounding in f format implemented round up when digit not printed is 5 formatting of -0.0f round up/down when last digits are 50000...
94 *
95 * <p>
96 * A control string is a Java string that contains a control specification.
97 * The control specification starts at the first percent sign (%) in the
98 * string, provided that this percent sign
99 *
100 * <ol>
101 * <li>
102 * is not escaped protected by a matching % or is not an escape % character,
103 * </li>
104 * <li>
105 * is not at the end of the format string, and
106 * </li>
107 * <li>
108 * precedes a sequence of characters that parses as a valid control
109 * specification.
110 * </li>
111 * </ol>
112 * </p>
113 *
114 * <p>
115 * A control specification usually takes the form:
116 * <pre> % ['-+ #0]* [0..9]* { . [0..9]* }+
117 * { [hlL] }+ [idfgGoxXeEcs]
118 * </pre>
119 * There are variants of this basic form that are discussed below.
120 * </p>
121 *
122 * <p>
123 * The format is composed of zero or more directives defined as follows:
124 *
125 * <ul>
126 * <li>
127 * ordinary characters, which are simply copied to the output stream;
128 * </li>
129 * <li>
130 * escape sequences, which represent non-graphic characters; and
131 * </li>
132 * <li>
133 * conversion specifications, each of which results in the fetching of zero or
134 * more arguments.
135 * </li>
136 * </ul>
137 * </p>
138 *
139 * <p>
140 * The results are undefined if there are insufficient arguments for the
141 * format. Usually an unchecked exception will be thrown. If the format is
142 * exhausted while arguments remain, the excess arguments are evaluated but
143 * are otherwise ignored. In format strings containing the % form of
144 * conversion specifications, each argument in the argument list is used
145 * exactly once.
146 * </p>
147 *
148 * <p>
149 * Conversions can be applied to the <code>n</code>th argument after the format
150 * in the argument list, rather than to the next unused argument. In this
151 * case, the conversion characer % is replaced by the sequence
152 * %<code>n</code>$, where <code>n</code> is a decimal integer giving the
153 * position of the argument in the argument list.
154 * </p>
155 *
156 * <p>
157 * In format strings containing the %<code>n</code>$ form of conversion
158 * specifications, each argument in the argument list is used exactly once.
159 * </p>
160 * <h4>
161 *
162 * <p>
163 * The following table lists escape sequences and associated actions on display
164 * devices capable of the action.
165 * </p>
166 *
167 * <p>
168 * Each conversion specification is introduced by the percent sign character
169 * (%). After the character %, the following appear in sequence:
170 * </p>
171 *
172 * <p>
173 * Zero or more flags (in any order), which modify the meaning of the
174 * conversion specification.
175 * </p>
176 *
177 * <p>
178 * An optional minimum field width. If the converted value has fewer
179 * characters than the field width, it will be padded with spaces by default
180 * on the left; t will be padded on the right, if the left- adjustment flag
181 * (-), described below, is given to the field width. The field width takes
182 * the form of a decimal integer. If the conversion character is s, the field
183 * width is the the minimum number of characters to be printed.
184 * </p>
185 *
186 * <p>
187 * An optional precision that gives the minumum number of digits to appear for
188 * the d, i, o, x or X conversions (the field is padded with leading zeros);
189 * the number of digits to appear after the radix character for the e, E, and
190 * f conversions, the maximum number of significant digits for the g and G
191 * conversions; or the maximum number of characters to be written from a
192 * string is s and S conversions. The precision takes the form of an optional
193 * decimal digit string, where a null digit string is treated as 0. If a
194 * precision appears with a c conversion character the precision is ignored.
195 * </p>
196 *
197 * <p>
198 * An optional h specifies that a following d, i, o, x, or X conversion
199 * character applies to a type short argument (the argument will be promoted
200 * according to the integral promotions and its value converted to type short
201 * before printing).
202 * </p>
203 *
204 * <p>
205 * An optional l (ell) specifies that a following d, i, o, x, or X conversion
206 * character applies to a type long argument.
207 * </p>
208 *
209 * <p>
210 * A field width or precision may be indicated by an asterisk () instead of a
211 * digit string. In this case, an integer argument supplised the field width
212 * precision. The argument that is actually converted is not fetched until
213 * the conversion letter is seen, so the the arguments specifying field width
214 * or precision must appear before the argument (if any) to be converted. If
215 * the precision argument is negative, it will be changed to zero. A negative
216 * field width argument is taken as a - flag, followed by a positive field
217 * width.
218 * </p>
219 *
220 * <p>
221 * In format strings containing the %<code>n</code>$ form of a conversion
222 * specification, a field width or precision may be indicated by the sequence
223 * <code>m</code>$, where m is a decimal integer giving the position in the
224 * argument list (after the format argument) of an integer argument containing
225 * the field width or precision.
226 * </p>
227 *
228 * <p>
229 * The format can contain either numbered argument specifications (that is,
230 * %<code>n</code>$ and <code>m</code>$), or unnumbered argument
231 * specifications (that is % and ), but normally not both. The only exception
232 * to this is that %% can be mixed with the %<code>n</code>$ form. The
233 * results of mixing numbered and unnumbered argument specifications in a
234 * format string are undefined.
235 * </p>
236 *
237 * <p>
238 * The flags and their meanings are:
239 * </p>
240 *
241 * <dl>
242 * <dt>
243 * '
244 * </dt>
245 * <dd>
246 * integer portion of the result of a decimal conversion (%i, %d, %f, %g, or
247 * %G) will be formatted with thousands' grouping characters. For other
248 * conversions the flag is ignored. The non-monetary grouping character is
249 * used.
250 * </dd>
251 * <dt>
252 * -
253 * </dt>
254 * <dd>
255 * result of the conversion is left-justified within the field. (It will be
256 * right-justified if this flag is not specified).
257 * </dd>
258 * <dt>
259 * +
260 * </dt>
261 * <dd>
262 * result of a signed conversion always begins with a sign (+ or -). (It will
263 * begin with a sign only when a negative value is converted if this flag is
264 * not specified.)
265 * </dd>
266 * <dt>
267 * <space>
268 * </dt>
269 * <dd>
270 * If the first character of a signed conversion is not a sign, a space
271 * character will be placed before the result. This means that if the space
272 * character and + flags both appear, the space flag will be ignored.
273 * </dd>
274 * <dt>
275 * #
276 * </dt>
277 * <dd>
278 * value is to be converted to an alternative form. For c, d, i, and s
279 * conversions, the flag has no effect. For o conversion, it increases the
280 * precision to force the first digit of the result to be a zero. For x or X
281 * conversion, a non-zero result has 0x or 0X prefixed to it, respectively.
282 * For e, E, f, g, and G conversions, the result always contains a radix
283 * character, even if no digits follow the radix character (normally, a
284 * decimal point appears in the result of these conversions only if a digit
285 * follows it). For g and G conversions, trailing zeros will not be removed
286 * from the result as they normally are.
287 * </dd>
288 * <dt>
289 * 0
290 * </dt>
291 * <dd>
292 * d, i, o, x, X, e, E, f, g, and G conversions, leading zeros (following any
293 * indication of sign or base) are used to pad to the field width; no space
294 * padding is performed. If the 0 and - flags both appear, the 0 flag is
295 * ignored. For d, i, o, x, and X conversions, if a precision is specified,
296 * the 0 flag will be ignored. For c conversions, the flag is ignored.
297 * </dd>
298 * </dl>
299 *
300 * <p>
301 * Each conversion character results in fetching zero or more arguments. The
302 * results are undefined if there are insufficient arguments for the format.
303 * Usually, an unchecked exception will be thrown. If the format is exhausted
304 * while arguments remain, the excess arguments are ignored.
305 * </p>
306 *
307 * <p>
308 * The conversion characters and their meanings are:
309 * </p>
310 *
311 * <dl>
312 * <dt>
313 * d,i
314 * </dt>
315 * <dd>
316 * The int argument is converted to a signed decimal in the style [-]dddd. The
317 * precision specifies the minimum number of digits to appear; if the value
318 * being converted can be represented in fewer digits, it will be expanded
319 * with leading zeros. The default precision is 1. The result of converting
320 * 0 with an explicit precision of 0 is no characters.
321 * </dd>
322 * <dt>
323 * o
324 * </dt>
325 * <dd>
326 * The int argument is converted to unsigned octal format in the style ddddd.
327 * The precision specifies the minimum number of digits to appear; if the
328 * value being converted can be represented in fewer digits, it will be
329 * expanded with leading zeros. The default precision is 1. The result of
330 * converting 0 with an explicit precision of 0 is no characters.
331 * </dd>
332 * <dt>
333 * x
334 * </dt>
335 * <dd>
336 * The int argument is converted to unsigned hexadecimal format in the style
337 * dddd; the letters abcdef are used. The precision specifies the minimum
338 * numberof digits to appear; if the value being converted can be represented
339 * in fewer digits, it will be expanded with leading zeros. The default
340 * precision is 1. The result of converting 0 with an explicit precision of 0
341 * is no characters.
342 * </dd>
343 * <dt>
344 * X
345 * </dt>
346 * <dd>
347 * Behaves the same as the x conversion character except that letters ABCDEF
348 * are used instead of abcdef.
349 * </dd>
350 * <dt>
351 * f
352 * </dt>
353 * <dd>
354 * The floating point number argument is written in decimal notation in the
355 * style [-]ddd.ddd, where the number of digits after the radix character
356 * (shown here as a decimal point) is equal to the precision specification. A
357 * Locale is used to determine the radix character to use in this format. If
358 * the precision is omitted from the argument, six digits are written after
359 * the radix character; if the precision is explicitly 0 and the # flag is
360 * not specified, no radix character appears. If a radix character appears,
361 * at least 1 digit appears before it. The value is rounded to the
362 * appropriate number of digits.
363 * </dd>
364 * <dt>
365 * e,E
366 * </dt>
367 * <dd>
368 * The floating point number argument is written in the style [-]d.ddde{+-}dd
369 * (the symbols {+-} indicate either a plus or minus sign), where there is one
370 * digit before the radix character (shown here as a decimal point) and the
371 * number of digits after it is equal to the precision. A Locale is used to
372 * determine the radix character to use in this format. When the precision is
373 * missing, six digits are written after the radix character; if the precision
374 * is 0 and the # flag is not specified, no radix character appears. The E
375 * conversion will produce a number with E instead of e introducing the
376 * exponent. The exponent always contains at least two digits. However, if
377 * the value to be written requires an exponent greater than two digits,
378 * additional exponent digits are written as necessary. The value is rounded
379 * to the appropriate number of digits.
380 * </dd>
381 * <dt>
382 * g,G
383 * </dt>
384 * <dd>
385 * The floating point number argument is written in style f or e (or in sytle E
386 * in the case of a G conversion character), with the precision specifying the
387 * number of significant digits. If the precision is zero, it is taken as
388 * one. The style used depends on the value converted: style e (or E) will
389 * be used only if the exponent resulting from the conversion is less than -4
390 * or greater than or equal to the precision. Trailing zeros are removed from
391 * the result. A radix character appears only if it is followed by a digit.
392 * </dd>
393 * <dt>
394 * c,C
395 * </dt>
396 * <dd>
397 * The integer argument is converted to a char and the result is written.
398 * </dd>
399 * <dt>
400 * s,S
401 * </dt>
402 * <dd>
403 * The argument is taken to be a string and bytes from the string are written
404 * until the end of the string or the number of bytes indicated by the
405 * precision specification of the argument is reached. If the precision is
406 * omitted from the argument, it is taken to be infinite, so all characters up
407 * to the end of the string are written.
408 * </dd>
409 * <dt>
410 * %
411 * </dt>
412 * <dd>
413 * Write a % character; no argument is converted.
414 * </dd>
415 * </dl>
416 *
417 * <p>
418 * If a conversion specification does not match one of the above forms, an
419 * IllegalArgumentException is thrown and the instance of PrintfFormat is not
420 * created.
421 * </p>
422 *
423 * <p>
424 * If a floating point value is the internal representation for infinity, the
425 * output is [+]Infinity, where Infinity is either Infinity or Inf, depending
426 * on the desired output string length. Printing of the sign follows the rules
427 * described above.
428 * </p>
429 *
430 * <p>
431 * If a floating point value is the internal representation for "not-a-number,"
432 * the output is [+]NaN. Printing of the sign follows the rules described
433 * above.
434 * </p>
435 *
436 * <p>
437 * In no case does a non-existent or small field width cause truncation of a
438 * field; if the result of a conversion is wider than the field width, the
439 * field is simply expanded to contain the conversion result.
440 * </p>
441 *
442 * <p>
443 * The behavior is like printf. One exception is that the minimum number of
444 * exponent digits is 3 instead of 2 for e and E formats when the optional L
445 * is used before the e, E, g, or G conversion character. The optional L does
446 * not imply conversion to a long long double.
447 * </p>
448 *
449 * <p>
450 * The biggest divergence from the C printf specification is in the use of 16
451 * bit characters. This allows the handling of characters beyond the small
452 * ASCII character set and allows the utility to interoperate correctly with
453 * the rest of the Java runtime environment.
454 * </p>
455 *
456 * <p>
457 * Omissions from the C printf specification are numerous. All the known
458 * omissions are present because Java never uses bytes to represent characters
459 * and does not have pointers:
460 * </p>
461 *
462 * <ul>
463 * <li>
464 * %c is the same as %C.
465 * </li>
466 * <li>
467 * %s is the same as %S.
468 * </li>
469 * <li>
470 * u, p, and n conversion characters.
471 * </li>
472 * <li>
473 * %ws format.
474 * </li>
475 * <li>
476 * h modifier applied to an n conversion character.
477 * </li>
478 * <li>
479 * l (ell) modifier applied to the c, n, or s conversion characters.
480 * </li>
481 * <li>
482 * ll (ell ell) modifier to d, i, o, u, x, or X conversion characters.
483 * </li>
484 * <li>
485 * ll (ell ell) modifier to an n conversion character.
486 * </li>
487 * <li>
488 * c, C, d,i,o,u,x, and X conversion characters apply to Byte, Character,
489 * Short, Integer, Long types.
490 * </li>
491 * <li>
492 * f, e, E, g, and G conversion characters apply to Float and Double types.
493 * </li>
494 * <li>
495 * s and S conversion characters apply to String types.
496 * </li>
497 * <li>
498 * All other reference types can be formatted using the s or S conversion
499 * characters only.
500 * </li>
501 * </ul>
502 *
503 * <p>
504 * Most of this specification is quoted from the Unix man page for the sprintf
505 * utility.
506 * </p>
507 */
508 public class PrintfFormat {
509 /*** Character position. Used by the constructor. */
510 private DecimalFormatSymbols dfs = null;
511 private Locale locale = null;
512
513 /*** Vector of control strings and format literals. */
514 private Vector vFmt = new Vector();
515
516 /*** Character position. Used by the constructor. */
517 private int cPos = 0;
518 private int formatCount = 0;
519
520 /***
521 * Creates a new PrintfFormat object.
522 *
523 * @param locale DOCUMENT ME!
524 */
525 public PrintfFormat(Locale locale) {
526 this();
527 setLocale(locale);
528 }
529
530
531 /***
532 * Creates a new PrintfFormat object.
533 */
534 public PrintfFormat() {
535 setLocale(Locale.getDefault());
536 }
537
538
539 /***
540 * Constructs an array of control specifications possibly preceded,
541 * separated, or followed by ordinary strings. Control strings begin with
542 * unpaired percent signs. A pair of successive percent signs designates a
543 * single percent sign in the format.
544 *
545 * @param fmtArg Control string.
546 *
547 * @exception IllegalArgumentException if the control string is null, zero
548 * length, or otherwise malformed.
549 */
550 public PrintfFormat(String fmtArg) throws IllegalArgumentException {
551 this();
552 setFormat(fmtArg);
553 }
554
555
556 /***
557 * Constructs an array of control specifications possibly preceded,
558 * separated, or followed by ordinary strings. Control strings begin with
559 * unpaired percent signs. A pair of successive percent signs designates a
560 * single percent sign in the format.
561 *
562 * @param locale DOCUMENT ME!
563 * @param fmtArg Control string.
564 *
565 * @exception IllegalArgumentException if the control string is null, zero
566 * length, or otherwise malformed.
567 */
568 public PrintfFormat(Locale locale,
569 String fmtArg) throws IllegalArgumentException {
570 this(locale);
571 setFormat(fmtArg);
572 }
573
574 /***
575 * DOCUMENT ME!
576 *
577 * @param fmtArg DOCUMENT ME!
578 *
579 * @throws IllegalArgumentException DOCUMENT ME!
580 */
581 public void setFormat(String fmtArg) throws IllegalArgumentException {
582 formatCount = 0;
583
584 int ePos = 0;
585 ConversionSpecification sFmt = null;
586 String unCS = this.nonControl(fmtArg, 0);
587 vFmt.clear();
588
589 if (unCS != null) {
590 sFmt = new ConversionSpecification();
591 sFmt.setLiteral(unCS);
592 vFmt.addElement(sFmt);
593 }
594
595 while ((cPos != -1) && (cPos < fmtArg.length())) {
596 for (ePos = cPos + 1; ePos < fmtArg.length(); ePos++) {
597 char c = 0;
598 c = fmtArg.charAt(ePos);
599
600 if (c == 'i') {
601 break;
602 }
603
604 if (c == 'd') {
605 break;
606 }
607
608 if (c == 'f') {
609 break;
610 }
611
612 if (c == 'g') {
613 break;
614 }
615
616 if (c == 'G') {
617 break;
618 }
619
620 if (c == 'o') {
621 break;
622 }
623
624 if (c == 'x') {
625 break;
626 }
627
628 if (c == 'X') {
629 break;
630 }
631
632 if (c == 'e') {
633 break;
634 }
635
636 if (c == 'E') {
637 break;
638 }
639
640 if (c == 'c') {
641 break;
642 }
643
644 if (c == 's') {
645 break;
646 }
647
648 if (c == '%') {
649 break;
650 }
651 }
652
653 ePos = Math.min(ePos + 1, fmtArg.length());
654 sFmt = new ConversionSpecification(fmtArg.substring(cPos, ePos));
655 formatCount++;
656 vFmt.addElement(sFmt);
657 unCS = this.nonControl(fmtArg, ePos);
658
659 if (unCS != null) {
660 sFmt = new ConversionSpecification();
661 sFmt.setLiteral(unCS);
662 vFmt.addElement(sFmt);
663 }
664 }
665 }
666
667
668 /***
669 * DOCUMENT ME!
670 *
671 * @param locale DOCUMENT ME!
672 */
673 public void setLocale(Locale locale) {
674 if (locale != null) {
675 this.locale = locale;
676 dfs = new DecimalFormatSymbols(getLocale());
677 }
678 }
679
680
681 /***
682 * DOCUMENT ME!
683 *
684 * @return DOCUMENT ME!
685 */
686 public Locale getLocale() {
687 return locale;
688 }
689
690
691 /***
692 * Format an array of objects. Byte, Short, Integer, Long, Float, Double,
693 * and Character arguments are treated as wrappers for primitive types.
694 *
695 * @param o The array of objects to format.
696 *
697 * @return The formatted String.
698 */
699 public String sprintf(Object[] o) {
700 Enumeration e = vFmt.elements();
701 ConversionSpecification cs = null;
702 char c = 0;
703 int i = 0;
704 StringBuffer sb = new StringBuffer();
705
706 while (e.hasMoreElements()) {
707 cs = (ConversionSpecification) e.nextElement();
708 c = cs.getConversionCharacter();
709
710 if (c == '\0') {
711 sb.append(cs.getLiteral());
712 } else if (c == '%') {
713 sb.append("%");
714 } else {
715 if (cs.isPositionalSpecification()) {
716 i = cs.getArgumentPosition() - 1;
717
718 if (cs.isPositionalFieldWidth()) {
719 int ifw = cs.getArgumentPositionForFieldWidth() - 1;
720 cs.setFieldWidthWithArg(((Integer) o[ifw]).intValue());
721 }
722
723 if (cs.isPositionalPrecision()) {
724 int ipr = cs.getArgumentPositionForPrecision() - 1;
725 cs.setPrecisionWithArg(((Integer) o[ipr]).intValue());
726 }
727 } else {
728 if (cs.isVariableFieldWidth()) {
729 cs.setFieldWidthWithArg(((Integer) o[i]).intValue());
730 i++;
731 }
732
733 if (cs.isVariablePrecision()) {
734 cs.setPrecisionWithArg(((Integer) o[i]).intValue());
735 i++;
736 }
737 }
738
739 if (o[i] instanceof Byte) {
740 sb.append(cs.internalsprintf(((Byte) o[i]).byteValue()));
741 } else if (o[i] instanceof Short) {
742 sb.append(cs.internalsprintf(((Short) o[i]).shortValue()));
743 } else if (o[i] instanceof Integer) {
744 sb.append(cs.internalsprintf(((Integer) o[i]).intValue()));
745 } else if (o[i] instanceof Long) {
746 sb.append(cs.internalsprintf(((Long) o[i]).longValue()));
747 } else if (o[i] instanceof Float) {
748 sb.append(cs.internalsprintf(((Float) o[i]).floatValue()));
749 } else if (o[i] instanceof Double) {
750 sb.append(cs.internalsprintf(((Double) o[i]).doubleValue()));
751 } else if (o[i] instanceof Character) {
752 sb.append(cs.internalsprintf(((Character) o[i]).charValue()));
753 } else if (o[i] instanceof String) {
754 sb.append(cs.internalsprintf((String) o[i]));
755 } else if (o[i] instanceof Date) {
756 sb.append(cs.internalsprintf((Date) o[i]));
757 } else {
758 sb.append(cs.internalsprintf(o[i]));
759 }
760
761 if (!cs.isPositionalSpecification()) {
762 i++;
763 }
764 }
765 }
766
767 return sb.toString();
768 }
769
770
771 /***
772 * Format nothing. Just use the control string.
773 *
774 * @return the formatted String.
775 */
776 public String sprintf() {
777 Enumeration e = vFmt.elements();
778 ConversionSpecification cs = null;
779 char c = 0;
780 StringBuffer sb = new StringBuffer();
781
782 while (e.hasMoreElements()) {
783 cs = (ConversionSpecification) e.nextElement();
784 c = cs.getConversionCharacter();
785
786 if (c == '\0') {
787 sb.append(cs.getLiteral());
788 } else if (c == '%') {
789 sb.append("%");
790 }
791 }
792
793 return sb.toString();
794 }
795
796
797 /***
798 * Format an int.
799 *
800 * @param x The int to format.
801 *
802 * @return The formatted String.
803 *
804 * @exception IllegalArgumentException if the conversion character is f, e,
805 * E, g, G, s, or S.
806 */
807 public String sprintf(int x) throws IllegalArgumentException {
808 Enumeration e = vFmt.elements();
809 ConversionSpecification cs = null;
810 char c = 0;
811 StringBuffer sb = new StringBuffer();
812
813 while (e.hasMoreElements()) {
814 cs = (ConversionSpecification) e.nextElement();
815 c = cs.getConversionCharacter();
816
817 if (c == '\0') {
818 sb.append(cs.getLiteral());
819 } else if (c == '%') {
820 sb.append("%");
821 } else {
822 sb.append(cs.internalsprintf(x));
823 }
824 }
825
826 return sb.toString();
827 }
828
829
830 /***
831 * Format an long.
832 *
833 * @param x The long to format.
834 *
835 * @return The formatted String.
836 *
837 * @exception IllegalArgumentException if the conversion character is f, e,
838 * E, g, G, s, or S.
839 */
840 public String sprintf(long x) throws IllegalArgumentException {
841 Enumeration e = vFmt.elements();
842 ConversionSpecification cs = null;
843 char c = 0;
844 StringBuffer sb = new StringBuffer();
845
846 while (e.hasMoreElements()) {
847 cs = (ConversionSpecification) e.nextElement();
848 c = cs.getConversionCharacter();
849
850 if (c == '\0') {
851 sb.append(cs.getLiteral());
852 } else if (c == '%') {
853 sb.append("%");
854 } else {
855 sb.append(cs.internalsprintf(x));
856 }
857 }
858
859 return sb.toString();
860 }
861
862
863 /***
864 * Format a double.
865 *
866 * @param x The double to format.
867 *
868 * @return The formatted String.
869 *
870 * @exception IllegalArgumentException if the conversion character is c, C,
871 * s, S, d, d, x, X, or o.
872 */
873 public String sprintf(double x) throws IllegalArgumentException {
874 Enumeration e = vFmt.elements();
875 ConversionSpecification cs = null;
876 char c = 0;
877 StringBuffer sb = new StringBuffer();
878
879 while (e.hasMoreElements()) {
880 cs = (ConversionSpecification) e.nextElement();
881 c = cs.getConversionCharacter();
882
883 if (c == '\0') {
884 sb.append(cs.getLiteral());
885 } else if (c == '%') {
886 sb.append("%");
887 } else {
888 sb.append(cs.internalsprintf(x));
889 }
890 }
891
892 return sb.toString();
893 }
894
895
896 /***
897 * Format a String.
898 *
899 * @param x The String to format.
900 *
901 * @return The formatted String.
902 *
903 * @exception IllegalArgumentException if the conversion character is
904 * neither s nor S.
905 */
906 public String sprintf(String x) throws IllegalArgumentException {
907 Enumeration e = vFmt.elements();
908 ConversionSpecification cs = null;
909 char c = 0;
910 StringBuffer sb = new StringBuffer();
911
912 while (e.hasMoreElements()) {
913 cs = (ConversionSpecification) e.nextElement();
914 c = cs.getConversionCharacter();
915
916 if (c == '\0') {
917 sb.append(cs.getLiteral());
918 } else if (c == '%') {
919 sb.append("%");
920 } else {
921 sb.append(cs.internalsprintf(x));
922 }
923 }
924
925 return sb.toString();
926 }
927
928
929 /***
930 * Format an Object. Convert wrapper types to their primitive equivalents
931 * and call the appropriate internal formatting method. Convert Strings
932 * using an internal formatting method for Strings. Otherwise use the
933 * default formatter (use toString).
934 *
935 * @param x the Object to format.
936 *
937 * @return the formatted String.
938 *
939 * @exception IllegalArgumentException if the conversion character is
940 * inappropriate for formatting an unwrapped value.
941 */
942 public String sprintf(Object x) throws IllegalArgumentException {
943 Enumeration e = vFmt.elements();
944 ConversionSpecification cs = null;
945 char c = 0;
946 StringBuffer sb = new StringBuffer();
947
948 while (e.hasMoreElements()) {
949 cs = (ConversionSpecification) e.nextElement();
950 c = cs.getConversionCharacter();
951
952 if (c == '\0') {
953 sb.append(cs.getLiteral());
954 } else if (c == '%') {
955 sb.append("%");
956 } else {
957 if (x instanceof Byte) {
958 sb.append(cs.internalsprintf(((Byte) x).byteValue()));
959 } else if (x instanceof Short) {
960 sb.append(cs.internalsprintf(((Short) x).shortValue()));
961 } else if (x instanceof Integer) {
962 sb.append(cs.internalsprintf(((Integer) x).intValue()));
963 } else if (x instanceof Long) {
964 sb.append(cs.internalsprintf(((Long) x).longValue()));
965 } else if (x instanceof Float) {
966 sb.append(cs.internalsprintf(((Float) x).floatValue()));
967 } else if (x instanceof Double) {
968 sb.append(cs.internalsprintf(((Double) x).doubleValue()));
969 } else if (x instanceof Character) {
970 sb.append(cs.internalsprintf(((Character) x).charValue()));
971 } else if (x instanceof String) {
972 sb.append(cs.internalsprintf((String) x));
973 } else {
974 sb.append(cs.internalsprintf(x));
975 }
976 }
977 }
978
979 return sb.toString();
980 }
981
982
983 /***
984 * DOCUMENT ME!
985 *
986 * @return DOCUMENT ME!
987 */
988 protected int getFormatCount() {
989 return formatCount;
990 }
991
992
993 /***
994 * Return a substring starting at <code>start</code> and ending at either
995 * the end of the String <code>s</code>, the next unpaired percent sign, or
996 * at the end of the String if the last character is a percent sign.
997 *
998 * @param s Control string.
999 * @param start Position in the string <code>s</code> to begin looking for
1000 * the start of a control string.
1001 *
1002 * @return the substring from the start position to the beginning of the
1003 * control string.
1004 */
1005 private String nonControl(String s,
1006 int start) {
1007 cPos = s.indexOf("%", start);
1008
1009 if (cPos == -1) {
1010 cPos = s.length();
1011 }
1012
1013 return s.substring(start, cPos);
1014 }
1015
1016 /***
1017 * <p>
1018 * ConversionSpecification allows the formatting of a single primitive or
1019 * object embedded within a string. The formatting is controlled by a
1020 * format string. Only one Java primitive or object can be formatted at a
1021 * time.
1022 * </p>
1023 *
1024 * <p>
1025 * A format string is a Java string that contains a control string. The
1026 * control string starts at the first percent sign (%) in the string,
1027 * provided that this percent sign
1028 *
1029 * <ol>
1030 * <li>
1031 * is not escaped protected by a matching % or is not an escape % character,
1032 * </li>
1033 * <li>
1034 * is not at the end of the format string, and
1035 * </li>
1036 * <li>
1037 * precedes a sequence of characters that parses as a valid control string.
1038 * </li>
1039 * </ol>
1040 * </p>
1041 *
1042 * <p>
1043 * A control string takes the form:
1044 * <pre> % ['-+ #0]* [0..9]* { . [0..9]* }+
1045 * { [hlL] }+ [idfgGoxXeEcs]
1046 * </pre>
1047 * </p>
1048 *
1049 * <p>
1050 * The behavior is like printf. One (hopefully the only) exception is that
1051 * the minimum number of exponent digits is 3 instead of 2 for e and E
1052 * formats when the optional L is used before the e, E, g, or G conversion
1053 * character. The optional L does not imply conversion to a long long
1054 * double.
1055 * </p>
1056 */
1057 private class ConversionSpecification {
1058 /*** Default precision. */
1059 private static final int DEFAULTDIGITS = 6;
1060
1061 /*** Literal or control format string. */
1062 private String fmt;
1063
1064 /***
1065 * For an o conversion, increase the precision to force the first digit
1066 * of the result to be a zero. For x (or X) conversions, a non-zero
1067 * result will have 0x (or 0X) prepended to it. For e, E, f, g, or G
1068 * conversions, the result will always contain a radix character, even
1069 * if no digits follow the point. For g and G conversions, trailing
1070 * zeros will not be removed from the result.
1071 */
1072 private boolean alternateForm = false;
1073
1074 /*** Flag indicating whether or not the field width has been set. */
1075 private boolean fieldWidthSet = false;
1076
1077 /***
1078 * The result of a signed conversion will always begin with a sign (+ or
1079 * -).
1080 */
1081 private boolean leadingSign = false;
1082
1083 /*** Flag indicating that left padding with spaces is specified. */
1084 private boolean leadingSpace = false;
1085
1086 /*** Flag indicating that left padding with zeroes is specified. */
1087 private boolean leadingZeros = false;
1088
1089 /***
1090 * The result of the conversion will be left-justified within the field.
1091 */
1092 private boolean leftJustify = false;
1093
1094 /***
1095 * Flag specifying that a following e, E, f, g, or G conversion character
1096 * applies to a type double argument. This is a noop in Java.
1097 */
1098 private boolean optionalL = false;
1099
1100 /***
1101 * Flag specifying that a following d, i, o, u, x, or X conversion
1102 * character applies to a type short int.
1103 */
1104 private boolean optionalh = false;
1105
1106 /***
1107 * Flag specifying that a following d, i, o, u, x, or X conversion
1108 * character applies to a type lont int argument.
1109 */
1110 private boolean optionall = false;
1111 private boolean positionalFieldWidth = false;
1112 private boolean positionalPrecision = false;
1113
1114
1115
1116 private boolean positionalSpecification = false;
1117
1118 /*** Flag indicating whether or not the precision has been set. */
1119 private boolean precisionSet = false;
1120
1121 /***
1122 * The integer portion of the result of a decimal conversion (i, d, u, f,
1123 * g, or G) will be formatted with thousands' grouping characters. For
1124 * other conversions the flag is ignored.
1125 */
1126 private boolean thousands = false;
1127
1128 /*** Flag indicating that the field width is . */
1129 private boolean variableFieldWidth = false;
1130
1131 /*** Flag indicating that the precision is . */
1132 private boolean variablePrecision = false;
1133
1134 /*** Control string type. */
1135 private char conversionCharacter = '\0';
1136 private int argumentPosition = 0;
1137 private int argumentPositionForFieldWidth = 0;
1138 private int argumentPositionForPrecision = 0;
1139
1140 /***
1141 * If the converted value has fewer bytes than the field width, it will
1142 * be padded with spaces or zeroes.
1143 */
1144 private int fieldWidth = 0;
1145
1146 /*** Position within the control string. Used by the constructor. */
1147 private int pos = 0;
1148
1149 /***
1150 * The minimum number of digits to appear for the d, i, o, u, x, or X
1151 * conversions. The number of digits to appear after the radix
1152 * character for the e, E, and f conversions. The maximum number of
1153 * significant digits for the g and G conversions. The maximum number
1154 * of bytes to be printed from a string in s and S conversions.
1155 */
1156 private int precision = 0;
1157
1158 /***
1159 * Constructor. Used to prepare an instance to hold a literal, not a
1160 * control string.
1161 */
1162 ConversionSpecification() {
1163 }
1164
1165
1166 /***
1167 * Constructor for a conversion specification. The argument must begin
1168 * with a % and end with the conversion character for the conversion
1169 * specification.
1170 *
1171 * @param fmtArg String specifying the conversion specification.
1172 *
1173 * @exception IllegalArgumentException if the input string is null, zero
1174 * length, or otherwise malformed.
1175 */
1176 ConversionSpecification(String fmtArg) throws IllegalArgumentException {
1177 if (fmtArg == null) {
1178 throw new NullPointerException();
1179 }
1180
1181 if (fmtArg.length() == 0) {
1182 throw new IllegalArgumentException("Control strings must have positive"
1183 + " lengths.");
1184 }
1185
1186 if (fmtArg.charAt(0) == '%') {
1187 fmt = fmtArg;
1188 pos = 1;
1189 setArgPosition();
1190 setFlagCharacters();
1191 setFieldWidth();
1192 setPrecision();
1193 setOptionalHL();
1194
1195 if (setConversionCharacter()) {
1196 if (pos == fmtArg.length()) {
1197 if (leadingZeros && leftJustify) {
1198 leadingZeros = false;
1199 }
1200
1201 if (precisionSet && leadingZeros) {
1202 if ((conversionCharacter == 'd')
1203 || (conversionCharacter == 'i')
1204 || (conversionCharacter == 'o')
1205 || (conversionCharacter == 'x')) {
1206 leadingZeros = false;
1207 }
1208 }
1209 } else {
1210 throw new IllegalArgumentException("Malformed conversion specification="
1211 + fmtArg);
1212 }
1213 } else {
1214 throw new IllegalArgumentException("Malformed conversion specification="
1215 + fmtArg);
1216 }
1217 } else {
1218 throw new IllegalArgumentException("Control strings must begin with %.");
1219 }
1220 }
1221
1222 int getArgumentPosition() {
1223 return argumentPosition;
1224 }
1225
1226
1227 int getArgumentPositionForFieldWidth() {
1228 return argumentPositionForFieldWidth;
1229 }
1230
1231
1232 int getArgumentPositionForPrecision() {
1233 return argumentPositionForPrecision;
1234 }
1235
1236
1237 /***
1238 * Get the conversion character that tells what type of control character
1239 * this instance has.
1240 *
1241 * @return the conversion character.
1242 */
1243 char getConversionCharacter() {
1244 return conversionCharacter;
1245 }
1246
1247
1248 /***
1249 * Set the field width with an argument. A negative field width is taken
1250 * as a - flag followed by a positive field width.
1251 *
1252 * @param fw the field width.
1253 */
1254 void setFieldWidthWithArg(int fw) {
1255 if (fw < 0) {
1256 leftJustify = true;
1257 }
1258
1259 fieldWidthSet = true;
1260 fieldWidth = Math.abs(fw);
1261 }
1262
1263
1264 /***
1265 * Set the String for this instance.
1266 *
1267 * @param s the String to store.
1268 */
1269 void setLiteral(String s) {
1270 fmt = s;
1271 }
1272
1273
1274 /***
1275 * Get the String for this instance. Translate any escape sequences.
1276 *
1277 * @return s the stored String.
1278 */
1279 String getLiteral() {
1280 StringBuffer sb = new StringBuffer();
1281 int i = 0;
1282
1283 while (i < fmt.length()) {
1284 if (fmt.charAt(i) == '//') {
1285 i++;
1286
1287 if (i < fmt.length()) {
1288 char c = fmt.charAt(i);
1289
1290 switch (c) {
1291 case 'a':
1292 sb.append((char) 0x07);
1293
1294 break;
1295
1296 case 'b':
1297 sb.append('\b');
1298
1299 break;
1300
1301 case 'f':
1302 sb.append('\f');
1303
1304 break;
1305
1306 case 'n':
1307 sb.append(System.getProperty("line.separator"));
1308
1309 break;
1310
1311 case 'r':
1312 sb.append('\r');
1313
1314 break;
1315
1316 case 't':
1317 sb.append('\t');
1318
1319 break;
1320
1321 case 'v':
1322 sb.append((char) 0x0b);
1323
1324 break;
1325
1326 case '//':
1327 sb.append('//');
1328
1329 break;
1330 }
1331
1332 i++;
1333 } else {
1334 sb.append('//');
1335 }
1336 } else {
1337 i++;
1338 }
1339 }
1340
1341 return fmt;
1342 }
1343
1344
1345 boolean isPositionalFieldWidth() {
1346 return positionalFieldWidth;
1347 }
1348
1349
1350 boolean isPositionalPrecision() {
1351 return positionalPrecision;
1352 }
1353
1354
1355 boolean isPositionalSpecification() {
1356 return positionalSpecification;
1357 }
1358
1359
1360 /***
1361 * Set the precision with an argument. A negative precision will be
1362 * changed to zero.
1363 *
1364 * @param pr the precision.
1365 */
1366 void setPrecisionWithArg(int pr) {
1367 precisionSet = true;
1368 precision = Math.max(pr, 0);
1369 }
1370
1371
1372 /***
1373 * Check whether the specifier has a variable field width that is going
1374 * to be set by an argument.
1375 *
1376 * @return <code>true</code> if the conversion uses an field width;
1377 * otherwise <code>false</code>.
1378 */
1379 boolean isVariableFieldWidth() {
1380 return variableFieldWidth;
1381 }
1382
1383
1384 /***
1385 * Check whether the specifier has a variable precision that is going to
1386 * be set by an argument.
1387 *
1388 * @return <code>true</code> if the conversion uses an precision;
1389 * otherwise <code>false</code>.
1390 */
1391 boolean isVariablePrecision() {
1392 return variablePrecision;
1393 }
1394
1395
1396 /***
1397 * Format an Date argument using this conversion specification.
1398 *
1399 * @param s the Object to format.
1400 *
1401 * @return the formatted String.
1402 *
1403 * @exception IllegalArgumentException if the conversion character is
1404 * neither s nor S.
1405 */
1406 String internalsprintf(Date s) {
1407 if (s == null) {
1408 return "";
1409 }
1410
1411 String s2 = "";
1412
1413 if ((conversionCharacter == 's') || (conversionCharacter == 'S')) {
1414 DateFormat f = DateFormat.getDateInstance(DateFormat.MEDIUM,
1415 getLocale());
1416 String ss = f.format(s);
1417 s2 = printSFormat(ss);
1418 } else {
1419 throw new IllegalArgumentException("Cannot format a String with a format using"
1420 + " a " + conversionCharacter
1421 + " conversion character.");
1422 }
1423
1424 return s2;
1425 }
1426
1427
1428 /***
1429 * Format an Object argument using this conversion specification.
1430 *
1431 * @param s the Object to format.
1432 *
1433 * @return the formatted String.
1434 *
1435 * @exception IllegalArgumentException if the conversion character is
1436 * neither s nor S.
1437 */
1438 String internalsprintf(Object s) {
1439 if (s == null) {
1440 return "";
1441 }
1442
1443 String s2 = "";
1444
1445 if ((conversionCharacter == 's') || (conversionCharacter == 'S')) {
1446 s2 = printSFormat(s.toString());
1447 } else {
1448 throw new IllegalArgumentException("Cannot format a String with a format using"
1449 + " a " + conversionCharacter
1450 + " conversion character.");
1451 }
1452
1453 return s2;
1454 }
1455
1456
1457 /***
1458 * Format an int argument using this conversion specification.
1459 *
1460 * @param s the int to format.
1461 *
1462 * @return the formatted String.
1463 *
1464 * @exception IllegalArgumentException if the conversion character is f,
1465 * e, E, g, or G.
1466 */
1467 String internalsprintf(int s) throws IllegalArgumentException {
1468 String s2 = "";
1469
1470 switch (conversionCharacter) {
1471 case 'd':
1472 case 'i':
1473
1474 if (optionalh) {
1475 s2 = printDFormat((short) s);
1476 } else if (optionall) {
1477 s2 = printDFormat((long) s);
1478 } else {
1479 s2 = printDFormat(s);
1480 }
1481
1482 break;
1483
1484 case 'x':
1485 case 'X':
1486
1487 if (optionalh) {
1488 s2 = printXFormat((short) s);
1489 } else if (optionall) {
1490 s2 = printXFormat((long) s);
1491 } else {
1492 s2 = printXFormat(s);
1493 }
1494
1495 break;
1496
1497 case 'o':
1498
1499 if (optionalh) {
1500 s2 = printOFormat((short) s);
1501 } else if (optionall) {
1502 s2 = printOFormat((long) s);
1503 } else {
1504 s2 = printOFormat(s);
1505 }
1506
1507 break;
1508
1509 case 'c':
1510 case 'C':
1511 s2 = printCFormat((char) s);
1512
1513 break;
1514
1515 default:
1516 throw new IllegalArgumentException("Cannot format a int with a format using a "
1517 + conversionCharacter
1518 + " conversion character.");
1519 }
1520
1521 return s2;
1522 }
1523
1524
1525 /***
1526 * Format a long argument using this conversion specification.
1527 *
1528 * @param s the long to format.
1529 *
1530 * @return the formatted String.
1531 *
1532 * @exception IllegalArgumentException if the conversion character is f,
1533 * e, E, g, or G.
1534 */
1535 String internalsprintf(long s) throws IllegalArgumentException {
1536 String s2 = "";
1537
1538 switch (conversionCharacter) {
1539 case 'd':
1540 case 'i':
1541
1542 if (optionalh) {
1543 s2 = printDFormat((short) s);
1544 } else if (optionall) {
1545 s2 = printDFormat(s);
1546 } else {
1547 s2 = printDFormat((int) s);
1548 }
1549
1550 break;
1551
1552 case 'x':
1553 case 'X':
1554
1555 if (optionalh) {
1556 s2 = printXFormat((short) s);
1557 } else if (optionall) {
1558 s2 = printXFormat(s);
1559 } else {
1560 s2 = printXFormat((int) s);
1561 }
1562
1563 break;
1564
1565 case 'o':
1566
1567 if (optionalh) {
1568 s2 = printOFormat((short) s);
1569 } else if (optionall) {
1570 s2 = printOFormat(s);
1571 } else {
1572 s2 = printOFormat((int) s);
1573 }
1574
1575 break;
1576
1577 case 'c':
1578 case 'C':
1579 s2 = printCFormat((char) s);
1580
1581 break;
1582
1583 default:
1584 throw new IllegalArgumentException("Cannot format a long with a format using a "
1585 + conversionCharacter
1586 + " conversion character.");
1587 }
1588
1589 return s2;
1590 }
1591
1592
1593 /***
1594 * Format a double argument using this conversion specification.
1595 *
1596 * @param s the double to format.
1597 *
1598 * @return the formatted String.
1599 *
1600 * @exception IllegalArgumentException if the conversion character is c,
1601 * C, s, S, i, d, x, X, or o.
1602 */
1603 String internalsprintf(double s) throws IllegalArgumentException {
1604 String s2 = "";
1605
1606 switch (conversionCharacter) {
1607 case 'f':
1608 s2 = printFFormat(s);
1609
1610 break;
1611
1612 case 'E':
1613 case 'e':
1614 s2 = printEFormat(s);
1615
1616 break;
1617
1618 case 'G':
1619 case 'g':
1620 s2 = printGFormat(s);
1621
1622 break;
1623
1624 default:
1625 throw new IllegalArgumentException("Cannot "
1626 + "format a double with a format using a "
1627 + conversionCharacter
1628 + " conversion character.");
1629 }
1630
1631 return s2;
1632 }
1633
1634
1635 /***
1636 * Format a String argument using this conversion specification.
1637 *
1638 * @param s the String to format.
1639 *
1640 * @return the formatted String.
1641 *
1642 * @exception IllegalArgumentException if the conversion character is
1643 * neither s nor S.
1644 */
1645 String internalsprintf(String s) throws IllegalArgumentException {
1646 String s2 = "";
1647
1648 if ((conversionCharacter == 's') || (conversionCharacter == 'S')) {
1649 s2 = printSFormat(s);
1650 } else {
1651 throw new IllegalArgumentException("Cannot "
1652 + "format a String with a format using a "
1653 + conversionCharacter
1654 + " conversion character.");
1655 }
1656
1657 return s2;
1658 }
1659
1660
1661 /***
1662 * Store the digits <code>n</code> in %n$ forms.
1663 */
1664 private void setArgPosition() {
1665 int xPos;
1666
1667 for (xPos = pos; xPos < fmt.length(); xPos++) {
1668 if (!Character.isDigit(fmt.charAt(xPos))) {
1669 break;
1670 }
1671 }
1672
1673 if ((xPos > pos) && (xPos < fmt.length())) {
1674 if (fmt.charAt(xPos) == '$') {
1675 positionalSpecification = true;
1676 argumentPosition = Integer.parseInt(fmt.substring(pos,
1677 xPos));
1678 pos = xPos + 1;
1679 }
1680 }
1681 }
1682
1683
1684 /***
1685 * Check for a conversion character. If it is there, store it.
1686 *
1687 * @return <code>true</code> if the conversion character is there, and
1688 * <code>false</code> otherwise.
1689 */
1690 private boolean setConversionCharacter() {
1691
1692 boolean ret = false;
1693 conversionCharacter = '\0';
1694
1695 if (pos < fmt.length()) {
1696 char c = fmt.charAt(pos);
1697
1698 if ((c == 'i')
1699 || (c == 'd')
1700 || (c == 'f')
1701 || (c == 'g')
1702 || (c == 'G')
1703 || (c == 'o')
1704 || (c == 'x')
1705 || (c == 'X')
1706 || (c == 'e')
1707 || (c == 'E')
1708 || (c == 'c')
1709 || (c == 's')
1710 || (c == '%')) {
1711 conversionCharacter = c;
1712 pos++;
1713 ret = true;
1714 }
1715 }
1716
1717 return ret;
1718 }
1719
1720
1721 /***
1722 * Set the field width.
1723 */
1724 private void setFieldWidth() {
1725 int firstPos = pos;
1726 fieldWidth = 0;
1727 fieldWidthSet = false;
1728
1729 if ((pos < fmt.length()) && (fmt.charAt(pos) == '*')) {
1730 pos++;
1731
1732 if (!setFieldWidthArgPosition()) {
1733 variableFieldWidth = true;
1734 fieldWidthSet = true;
1735 }
1736 } else {
1737 while (pos < fmt.length()) {
1738 char c = fmt.charAt(pos);
1739
1740 if (Character.isDigit(c)) {
1741 pos++;
1742 } else {
1743 break;
1744 }
1745 }
1746
1747 if ((firstPos < pos) && (firstPos < fmt.length())) {
1748 String sz = fmt.substring(firstPos, pos);
1749 fieldWidth = Integer.parseInt(sz);
1750 fieldWidthSet = true;
1751 }
1752 }
1753 }
1754
1755
1756 /***
1757 * Store the digits <code>n</code> in n$ forms.
1758 *
1759 * @return DOCUMENT ME!
1760 */
1761 private boolean setFieldWidthArgPosition() {
1762 boolean ret = false;
1763 int xPos;
1764
1765 for (xPos = pos; xPos < fmt.length(); xPos++) {
1766 if (!Character.isDigit(fmt.charAt(xPos))) {
1767 break;
1768 }
1769 }
1770
1771 if ((xPos > pos) && (xPos < fmt.length())) {
1772 if (fmt.charAt(xPos) == '$') {
1773 positionalFieldWidth = true;
1774 argumentPositionForFieldWidth = Integer.parseInt(fmt.substring(pos,
1775 xPos));
1776 pos = xPos + 1;
1777 ret = true;
1778 }
1779 }
1780
1781 return ret;
1782 }
1783
1784
1785 /***
1786 * Set flag characters, one of '-+#0 or a space.
1787 */
1788 private void setFlagCharacters() {
1789
1790 thousands = false;
1791 leftJustify = false;
1792 leadingSign = false;
1793 leadingSpace = false;
1794 alternateForm = false;
1795 leadingZeros = false;
1796
1797 for (; pos < fmt.length(); pos++) {
1798 char c = fmt.charAt(pos);
1799
1800 if (c == '\'') {
1801 thousands = true;
1802 } else if (c == '-') {
1803 leftJustify = true;
1804 leadingZeros = false;
1805 } else if (c == '+') {
1806 leadingSign = true;
1807 leadingSpace = false;
1808 } else if (c == ' ') {
1809 if (!leadingSign) {
1810 leadingSpace = true;
1811 }
1812 } else if (c == '#') {
1813 alternateForm = true;
1814 } else if (c == '0') {
1815 if (!leftJustify) {
1816 leadingZeros = true;
1817 }
1818 } else {
1819 break;
1820 }
1821 }
1822 }
1823
1824
1825 /***
1826 * Check for an h, l, or L in a format. An L is used to control the
1827 * minimum number of digits in an exponent when using floating point
1828 * formats. An l or h is used to control conversion of the input to a
1829 * long or short, respectively, before formatting. If any of these is
1830 * present, store them.
1831 */
1832 private void setOptionalHL() {
1833 optionalh = false;
1834 optionall = false;
1835 optionalL = false;
1836
1837 if (pos < fmt.length()) {
1838 char c = fmt.charAt(pos);
1839
1840 if (c == 'h') {
1841 optionalh = true;
1842 pos++;
1843 } else if (c == 'l') {
1844 optionall = true;
1845 pos++;
1846 } else if (c == 'L') {
1847 optionalL = true;
1848 pos++;
1849 }
1850 }
1851 }
1852
1853
1854 /***
1855 * Set the precision.
1856 */
1857 private void setPrecision() {
1858 int firstPos = pos;
1859 precisionSet = false;
1860
1861 if ((pos < fmt.length()) && (fmt.charAt(pos) == '.')) {
1862 pos++;
1863
1864 if ((pos < fmt.length()) && (fmt.charAt(pos) == '*')) {
1865 pos++;
1866
1867 if (!setPrecisionArgPosition()) {
1868 variablePrecision = true;
1869 precisionSet = true;
1870 }
1871
1872 return;
1873 } else {
1874 while (pos < fmt.length()) {
1875 char c = fmt.charAt(pos);
1876
1877 if (Character.isDigit(c)) {
1878 pos++;
1879 } else {
1880 break;
1881 }
1882 }
1883
1884 if (pos > (firstPos + 1)) {
1885 String sz = fmt.substring(firstPos + 1, pos);
1886 precision = Integer.parseInt(sz);
1887 precisionSet = true;
1888 }
1889 }
1890 }
1891 }
1892
1893
1894 /***
1895 * Store the digits <code>n</code> in n$ forms.
1896 *
1897 * @return DOCUMENT ME!
1898 */
1899 private boolean setPrecisionArgPosition() {
1900 boolean ret = false;
1901 int xPos;
1902
1903 for (xPos = pos; xPos < fmt.length(); xPos++) {
1904 if (!Character.isDigit(fmt.charAt(xPos))) {
1905 break;
1906 }
1907 }
1908
1909 if ((xPos > pos) && (xPos < fmt.length())) {
1910 if (fmt.charAt(xPos) == '$') {
1911 positionalPrecision = true;
1912 argumentPositionForPrecision = Integer.parseInt(fmt.substring(pos,
1913 xPos));
1914 pos = xPos + 1;
1915 ret = true;
1916 }
1917 }
1918
1919 return ret;
1920 }
1921
1922
1923 /***
1924 * Apply zero or blank, left or right padding.
1925 *
1926 * @param ca4 array of characters before padding is finished
1927 * @param noDigits NaN or signed Inf
1928 *
1929 * @return a padded array of characters
1930 */
1931 private char[] applyFloatPadding(char[] ca4,
1932 boolean noDigits) {
1933 char[] ca5 = ca4;
1934
1935 if (fieldWidthSet) {
1936 int i;
1937 int j;
1938 int nBlanks;
1939
1940 if (leftJustify) {
1941 nBlanks = fieldWidth - ca4.length;
1942
1943 if (nBlanks > 0) {
1944 ca5 = new char[ca4.length + nBlanks];
1945
1946 for (i = 0; i < ca4.length; i++)
1947 ca5[i] = ca4[i];
1948
1949 for (j = 0; j < nBlanks; j++, i++)
1950 ca5[i] = ' ';
1951 }
1952 } else if (!leadingZeros || noDigits) {
1953 nBlanks = fieldWidth - ca4.length;
1954
1955 if (nBlanks > 0) {
1956 ca5 = new char[ca4.length + nBlanks];
1957
1958 for (i = 0; i < nBlanks; i++)
1959 ca5[i] = ' ';
1960
1961 for (j = 0; j < ca4.length; i++, j++)
1962 ca5[i] = ca4[j];
1963 }
1964 } else if (leadingZeros) {
1965 nBlanks = fieldWidth - ca4.length;
1966
1967 if (nBlanks > 0) {
1968 ca5 = new char[ca4.length + nBlanks];
1969 i = 0;
1970 j = 0;
1971
1972 if (ca4[0] == '-') {
1973 ca5[0] = '-';
1974 i++;
1975 j++;
1976 }
1977
1978 for (int k = 0; k < nBlanks; i++, k++)
1979 ca5[i] = '0';
1980
1981 for (; j < ca4.length; i++, j++)
1982 ca5[i] = ca4[j];
1983 }
1984 }
1985 }
1986
1987 return ca5;
1988 }
1989
1990
1991 /***
1992 * Check to see if the digits that are going to be truncated because of
1993 * the precision should force a round in the preceding digits.
1994 *
1995 * @param ca1 the array of digits
1996 * @param icarry the index of the first digit that is to be truncated
1997 * from the print
1998 *
1999 * @return <code>true</code> if the truncation forces a round that will
2000 * change the print
2001 */
2002 private boolean checkForCarry(char[] ca1,
2003 int icarry) {
2004 boolean carry = false;
2005
2006 if (icarry < ca1.length) {
2007 if ((ca1[icarry] == '6')
2008 || (ca1[icarry] == '7')
2009 || (ca1[icarry] == '8')
2010 || (ca1[icarry] == '9')) {
2011 carry = true;
2012 } else if (ca1[icarry] == '5') {
2013 int ii = icarry + 1;
2014
2015 for (; ii < ca1.length; ii++)
2016 if (ca1[ii] != '0') {
2017 break;
2018 }
2019
2020 carry = ii < ca1.length;
2021
2022 if (!carry && (icarry > 0)) {
2023 carry = ((ca1[icarry - 1] == '1') || (ca1[icarry - 1] == '3')
2024 || (ca1[icarry - 1] == '5')
2025 || (ca1[icarry - 1] == '7')
2026 || (ca1[icarry - 1] == '9'));
2027 }
2028 }
2029 }
2030
2031 return carry;
2032 }
2033
2034
2035 /***
2036 * For e format, the flag character '-', means that the output should be
2037 * left justified within the field. The default is to pad with blanks
2038 * on the left. '+' character means that the conversion will always
2039 * begin with a sign (+ or -). The blank flag character means that a
2040 * non-negative input will be preceded with a blank. If both a '+' and
2041 * a ' ' are specified, the blank flag is ignored. The '0' flag
2042 * character implies that padding to the field width will be done with
2043 * zeros instead of blanks. The field width is treated as the minimum
2044 * number of characters to be printed. The default is to add no
2045 * padding. Padding is with blanks by default. The precision, if set,
2046 * is the minimum number of digits to appear after the radix character.
2047 * Padding is with trailing 0s. The behavior is like printf. One
2048 * (hopefully the only) exception is that the minimum number of exponent
2049 * digits is 3 instead of 2 for e and E formats when the optional L is
2050 * used before the e, E, g, or G conversion character. The optional L
2051 * does not imply conversion to a long long double.
2052 *
2053 * @param x DOCUMENT ME!
2054 * @param eChar DOCUMENT ME!
2055 *
2056 * @return DOCUMENT ME!
2057 */
2058 private char[] eFormatDigits(double x,
2059 char eChar) {
2060 char[] ca1;
2061 char[] ca2;
2062 char[] ca3;
2063
2064
2065 String sx;
2066
2067
2068 int i;
2069 int j;
2070 int k;
2071 int p;
2072 int expon = 0;
2073 int ePos;
2074 int rPos;
2075 int eSize;
2076 boolean minusSign = false;
2077
2078 if (x > 0.0) {
2079 sx = Double.toString(x);
2080 } else if (x < 0.0) {
2081 sx = Double.toString(-x);
2082 minusSign = true;
2083 } else {
2084 sx = Double.toString(x);
2085
2086 if (sx.charAt(0) == '-') {
2087 minusSign = true;
2088 sx = sx.substring(1);
2089 }
2090 }
2091
2092 ePos = sx.indexOf('E');
2093
2094 if (ePos == -1) {
2095 ePos = sx.indexOf('e');
2096 }
2097
2098 rPos = sx.indexOf('.');
2099
2100 if (ePos != -1) {
2101 int ie = ePos + 1;
2102 expon = 0;
2103
2104 if (sx.charAt(ie) == '-') {
2105 for (++ie; ie < sx.length(); ie++)
2106 if (sx.charAt(ie) != '0') {
2107 break;
2108 }
2109
2110 if (ie < sx.length()) {
2111 expon = -Integer.parseInt(sx.substring(ie));
2112 }
2113 } else {
2114 if (sx.charAt(ie) == '+') {
2115 ++ie;
2116 }
2117
2118 for (; ie < sx.length(); ie++)
2119 if (sx.charAt(ie) != '0') {
2120 break;
2121 }
2122
2123 if (ie < sx.length()) {
2124 expon = Integer.parseInt(sx.substring(ie));
2125 }
2126 }
2127 }
2128
2129 if (rPos != -1) {
2130 expon += (rPos - 1);
2131 }
2132
2133 if (precisionSet) {
2134 p = precision;
2135 } else {
2136 p = DEFAULTDIGITS - 1;
2137 }
2138
2139 if ((rPos != -1) && (ePos != -1)) {
2140 ca1 = (sx.substring(0, rPos) + sx.substring(rPos + 1, ePos))
2141 .toCharArray();
2142 } else if (rPos != -1) {
2143 ca1 = (sx.substring(0, rPos) + sx.substring(rPos + 1)).toCharArray();
2144 } else if (ePos != -1) {
2145 ca1 = sx.substring(0, ePos)
2146 .toCharArray();
2147 } else {
2148 ca1 = sx.toCharArray();
2149 }
2150
2151 boolean carry = false;
2152 int i0 = 0;
2153
2154 if (ca1[0] != '0') {
2155 i0 = 0;
2156 } else {
2157 for (i0 = 0; i0 < ca1.length; i0++)
2158 if (ca1[i0] != '0') {
2159 break;
2160 }
2161 }
2162
2163 if ((i0 + p) < (ca1.length - 1)) {
2164 carry = checkForCarry(ca1, i0 + p + 1);
2165
2166 if (carry) {
2167 carry = startSymbolicCarry(ca1, i0 + p, i0);
2168 }
2169
2170 if (carry) {
2171 ca2 = new char[i0 + p + 1];
2172 ca2[i0] = '1';
2173
2174 for (j = 0; j < i0; j++)
2175 ca2[j] = '0';
2176
2177 for (i = i0, j = i0 + 1; j < (p + 1); i++, j++)
2178 ca2[j] = ca1[i];
2179
2180 expon++;
2181 ca1 = ca2;
2182 }
2183 }
2184
2185 if ((Math.abs(expon) < 100) && !optionalL) {
2186 eSize = 4;
2187 } else {
2188 eSize = 5;
2189 }
2190
2191 if (alternateForm || !precisionSet || (precision != 0)) {
2192 ca2 = new char[2 + p + eSize];
2193 } else {
2194 ca2 = new char[1 + eSize];
2195 }
2196
2197 if (ca1[0] != '0') {
2198 ca2[0] = ca1[0];
2199 j = 1;
2200 } else {
2201 for (j = 1; j < ((ePos == -1) ? ca1.length
2202 : ePos); j++)
2203 if (ca1[j] != '0') {
2204 break;
2205 }
2206
2207 if (((ePos != -1) && (j < ePos))
2208 || ((ePos == -1) && (j < ca1.length))) {
2209 ca2[0] = ca1[j];
2210 expon -= j;
2211 j++;
2212 } else {
2213 ca2[0] = '0';
2214 j = 2;
2215 }
2216 }
2217
2218 if (alternateForm || !precisionSet || (precision != 0)) {
2219 ca2[1] = '.';
2220 i = 2;
2221 } else {
2222 i = 1;
2223 }
2224
2225 for (k = 0; (k < p) && (j < ca1.length); j++, i++, k++)
2226 ca2[i] = ca1[j];
2227
2228 for (; i < (ca2.length - eSize); i++)
2229 ca2[i] = '0';
2230
2231 ca2[i++] = eChar;
2232
2233 if (expon < 0) {
2234 ca2[i++] = '-';
2235 } else {
2236 ca2[i++] = '+';
2237 }
2238
2239 expon = Math.abs(expon);
2240
2241 if (expon >= 100) {
2242 switch (expon / 100) {
2243 case 1:
2244 ca2[i] = '1';
2245
2246 break;
2247
2248 case 2:
2249 ca2[i] = '2';
2250
2251 break;
2252
2253 case 3:
2254 ca2[i] = '3';
2255
2256 break;
2257
2258 case 4:
2259 ca2[i] = '4';
2260
2261 break;
2262
2263 case 5:
2264 ca2[i] = '5';
2265
2266 break;
2267
2268 case 6:
2269 ca2[i] = '6';
2270
2271 break;
2272
2273 case 7:
2274 ca2[i] = '7';
2275
2276 break;
2277
2278 case 8:
2279 ca2[i] = '8';
2280
2281 break;
2282
2283 case 9:
2284 ca2[i] = '9';
2285
2286 break;
2287 }
2288
2289 i++;
2290 }
2291
2292 switch ((expon % 100) / 10) {
2293 case 0:
2294 ca2[i] = '0';
2295
2296 break;
2297
2298 case 1:
2299 ca2[i] = '1';
2300
2301 break;
2302
2303 case 2:
2304 ca2[i] = '2';
2305
2306 break;
2307
2308 case 3:
2309 ca2[i] = '3';
2310
2311 break;
2312
2313 case 4:
2314 ca2[i] = '4';
2315
2316 break;
2317
2318 case 5:
2319 ca2[i] = '5';
2320
2321 break;
2322
2323 case 6:
2324 ca2[i] = '6';
2325
2326 break;
2327
2328 case 7:
2329 ca2[i] = '7';
2330
2331 break;
2332
2333 case 8:
2334 ca2[i] = '8';
2335
2336 break;
2337
2338 case 9:
2339 ca2[i] = '9';
2340
2341 break;
2342 }
2343
2344 i++;
2345
2346 switch (expon % 10) {
2347 case 0:
2348 ca2[i] = '0';
2349
2350 break;
2351
2352 case 1:
2353 ca2[i] = '1';
2354
2355 break;
2356
2357 case 2:
2358 ca2[i] = '2';
2359
2360 break;
2361
2362 case 3:
2363 ca2[i] = '3';
2364
2365 break;
2366
2367 case 4:
2368 ca2[i] = '4';
2369
2370 break;
2371
2372 case 5:
2373 ca2[i] = '5';
2374
2375 break;
2376
2377 case 6:
2378 ca2[i] = '6';
2379
2380 break;
2381
2382 case 7:
2383 ca2[i] = '7';
2384
2385 break;
2386
2387 case 8:
2388 ca2[i] = '8';
2389
2390 break;
2391
2392 case 9:
2393 ca2[i] = '9';
2394
2395 break;
2396 }
2397
2398 int nZeros = 0;
2399
2400 if (!leftJustify && leadingZeros) {
2401 int xThousands = 0;
2402
2403 if (thousands) {
2404 int xlead = 0;
2405
2406 if ((ca2[0] == '+') || (ca2[0] == '-') || (ca2[0] == ' ')) {
2407 xlead = 1;
2408 }
2409
2410 int xdp = xlead;
2411
2412 for (; xdp < ca2.length; xdp++)
2413 if (ca2[xdp] == '.') {
2414 break;
2415 }
2416
2417 xThousands = (xdp - xlead) / 3;
2418 }
2419
2420 if (fieldWidthSet) {
2421 nZeros = fieldWidth - ca2.length;
2422 }
2423
2424 if ((!minusSign && (leadingSign || leadingSpace)) || minusSign) {
2425 nZeros--;
2426 }
2427
2428 nZeros -= xThousands;
2429
2430 if (nZeros < 0) {
2431 nZeros = 0;
2432 }
2433 }
2434
2435 j = 0;
2436
2437 if ((!minusSign && (leadingSign || leadingSpace)) || minusSign) {
2438 ca3 = new char[ca2.length + nZeros + 1];
2439 j++;
2440 } else {
2441 ca3 = new char[ca2.length + nZeros];
2442 }
2443
2444 if (!minusSign) {
2445 if (leadingSign) {
2446 ca3[0] = '+';
2447 }
2448
2449 if (leadingSpace) {
2450 ca3[0] = ' ';
2451 }
2452 } else {
2453 ca3[0] = '-';
2454 }
2455
2456 for (k = 0; k < nZeros; j++, k++)
2457 ca3[j] = '0';
2458
2459 for (i = 0; (i < ca2.length) && (j < ca3.length); i++, j++)
2460 ca3[j] = ca2[i];
2461
2462 int lead = 0;
2463
2464 if ((ca3[0] == '+') || (ca3[0] == '-') || (ca3[0] == ' ')) {
2465 lead = 1;
2466 }
2467
2468 int dp = lead;
2469
2470 for (; dp < ca3.length; dp++)
2471 if (ca3[dp] == '.') {
2472 break;
2473 }
2474
2475 int nThousands = dp / 3;
2476
2477
2478 if (dp < ca3.length) {
2479 ca3[dp] = dfs.getDecimalSeparator();
2480 }
2481
2482 char[] ca4 = ca3;
2483
2484 if (thousands && (nThousands > 0)) {
2485 ca4 = new char[ca3.length + nThousands + lead];
2486 ca4[0] = ca3[0];
2487
2488 for (i = lead, k = lead; i < dp; i++) {
2489 if ((i > 0) && (((dp - i) % 3) == 0)) {
2490
2491 ca4[k] = dfs.getGroupingSeparator();
2492 ca4[k + 1] = ca3[i];
2493 k += 2;
2494 } else {
2495 ca4[k] = ca3[i];
2496 k++;
2497 }
2498 }
2499
2500 for (; i < ca3.length; i++, k++)
2501 ca4[k] = ca3[i];
2502 }
2503
2504 return ca4;
2505 }
2506
2507
2508 /***
2509 * An intermediate routine on the way to creating an e format String.
2510 * The method decides whether the input double value is an infinity,
2511 * not-a-number, or a finite double and formats each type of input
2512 * appropriately.
2513 *
2514 * @param x the double value to be formatted.
2515 * @param eChar an 'e' or 'E' to use in the converted double value.
2516 *
2517 * @return the converted double value.
2518 */
2519 private String eFormatString(double x,
2520 char eChar) {
2521 char[] ca4;
2522 char[] ca5;
2523
2524 if (Double.isInfinite(x)) {
2525 if (x == Double.POSITIVE_INFINITY) {
2526 if (leadingSign) {
2527 ca4 = "+Inf".toCharArray();
2528 } else if (leadingSpace) {
2529 ca4 = " Inf".toCharArray();
2530 } else {
2531 ca4 = "Inf".toCharArray();
2532 }
2533 } else {
2534 ca4 = "-Inf".toCharArray();
2535 }
2536 } else if (Double.isNaN(x)) {
2537 if (leadingSign) {
2538 ca4 = "+NaN".toCharArray();
2539 } else if (leadingSpace) {
2540 ca4 = " NaN".toCharArray();
2541 } else {
2542 ca4 = "NaN".toCharArray();
2543 }
2544 } else {
2545 ca4 = eFormatDigits(x, eChar);
2546 }
2547
2548 ca5 = applyFloatPadding(ca4, false);
2549
2550 return new String(ca5);
2551 }
2552
2553
2554 /***
2555 * For f format, the flag character '-', means that the output should be
2556 * left justified within the field. The default is to pad with blanks
2557 * on the left. '+' character means that the conversion will always
2558 * begin with a sign (+ or -). The blank flag character means that a
2559 * non-negative input will be preceded with a blank. If both a '+' and
2560 * a ' ' are specified, the blank flag is ignored. The '0' flag
2561 * character implies that padding to the field width will be done with
2562 * zeros instead of blanks. The field width is treated as the minimum
2563 * number of characters to be printed. The default is to add no
2564 * padding. Padding is with blanks by default. The precision, if set,
2565 * is the number of digits to appear after the radix character. Padding
2566 * is with trailing 0s.
2567 *
2568 * @param x DOCUMENT ME!
2569 *
2570 * @return DOCUMENT ME!
2571 */
2572 private char[] fFormatDigits(double x) {
2573
2574 String sx;
2575
2576
2577 int i;
2578 int j;
2579 int k;
2580 int n1In;
2581 int n2In;
2582 int expon = 0;
2583 boolean minusSign = false;
2584
2585 if (x > 0.0) {
2586 sx = Double.toString(x);
2587 } else if (x < 0.0) {
2588 sx = Double.toString(-x);
2589 minusSign = true;
2590 } else {
2591 sx = Double.toString(x);
2592
2593 if (sx.charAt(0) == '-') {
2594 minusSign = true;
2595 sx = sx.substring(1);
2596 }
2597 }
2598
2599 int ePos = sx.indexOf('E');
2600 int rPos = sx.indexOf('.');
2601
2602 if (rPos != -1) {
2603 n1In = rPos;
2604 } else if (ePos != -1) {
2605 n1In = ePos;
2606 } else {
2607 n1In = sx.length();
2608 }
2609
2610 if (rPos != -1) {
2611 if (ePos != -1) {
2612 n2In = ePos - rPos - 1;
2613 } else {
2614 n2In = sx.length() - rPos - 1;
2615 }
2616 } else {
2617 n2In = 0;
2618 }
2619
2620 if (ePos != -1) {
2621 int ie = ePos + 1;
2622 expon = 0;
2623
2624 if (sx.charAt(ie) == '-') {
2625 for (++ie; ie < sx.length(); ie++)
2626 if (sx.charAt(ie) != '0') {
2627 break;
2628 }
2629
2630 if (ie < sx.length()) {
2631 expon = -Integer.parseInt(sx.substring(ie));
2632 }
2633 } else {
2634 if (sx.charAt(ie) == '+') {
2635 ++ie;
2636 }
2637
2638 for (; ie < sx.length(); ie++)
2639 if (sx.charAt(ie) != '0') {
2640 break;
2641 }
2642
2643 if (ie < sx.length()) {
2644 expon = Integer.parseInt(sx.substring(ie));
2645 }
2646 }
2647 }
2648
2649 int p;
2650
2651 if (precisionSet) {
2652 p = precision;
2653 } else {
2654 p = DEFAULTDIGITS - 1;
2655 }
2656
2657 char[] ca1 = sx.toCharArray();
2658 char[] ca2 = new char[n1In + n2In];
2659 char[] ca3;
2660 char[] ca4;
2661 char[] ca5;
2662
2663 for (j = 0; j < n1In; j++)
2664 ca2[j] = ca1[j];
2665
2666 i = j + 1;
2667
2668 for (k = 0; k < n2In; j++, i++, k++)
2669 ca2[j] = ca1[i];
2670
2671 if ((n1In + expon) <= 0) {
2672 ca3 = new char[-expon + n2In];
2673
2674 for (j = 0, k = 0; k < (-n1In - expon); k++, j++)
2675 ca3[j] = '0';
2676
2677 for (i = 0; i < (n1In + n2In); i++, j++)
2678 ca3[j] = ca2[i];
2679 } else {
2680 ca3 = ca2;
2681 }
2682
2683 boolean carry = false;
2684
2685 if (p < (-expon + n2In)) {
2686 if (expon < 0) {
2687 i = p;
2688 } else {
2689 i = p + n1In;
2690 }
2691
2692 carry = checkForCarry(ca3, i);
2693
2694 if (carry) {
2695 carry = startSymbolicCarry(ca3, i - 1, 0);
2696 }
2697 }
2698
2699 if ((n1In + expon) <= 0) {
2700 ca4 = new char[2 + p];
2701
2702 if (!carry) {
2703 ca4[0] = '0';
2704 } else {
2705 ca4[0] = '1';
2706 }
2707
2708 if (alternateForm || !precisionSet || (precision != 0)) {
2709 ca4[1] = '.';
2710
2711 for (i = 0, j = 2; i < Math.min(p, ca3.length); i++, j++)
2712 ca4[j] = ca3[i];
2713
2714 for (; j < ca4.length; j++)
2715 ca4[j] = '0';
2716 }
2717 } else {
2718 if (!carry) {
2719 if (alternateForm || !precisionSet || (precision != 0)) {
2720 ca4 = new char[n1In + expon + p + 1];
2721 } else {
2722 ca4 = new char[n1In + expon];
2723 }
2724
2725 j = 0;
2726 } else {
2727 if (alternateForm || !precisionSet || (precision != 0)) {
2728 ca4 = new char[n1In + expon + p + 2];
2729 } else {
2730 ca4 = new char[n1In + expon + 1];
2731 }
2732
2733 ca4[0] = '1';
2734 j = 1;
2735 }
2736
2737 for (i = 0; i < Math.min(n1In + expon, ca3.length); i++, j++)
2738 ca4[j] = ca3[i];
2739
2740 for (; i < (n1In + expon); i++, j++)
2741 ca4[j] = '0';
2742
2743 if (alternateForm || !precisionSet || (precision != 0)) {
2744 ca4[j] = '.';
2745 j++;
2746
2747 for (k = 0; (i < ca3.length) && (k < p); i++, j++, k++)
2748 ca4[j] = ca3[i];
2749
2750 for (; j < ca4.length; j++)
2751 ca4[j] = '0';
2752 }
2753 }
2754
2755 int nZeros = 0;
2756
2757 if (!leftJustify && leadingZeros) {
2758 int xThousands = 0;
2759
2760 if (thousands) {
2761 int xlead = 0;
2762
2763 if ((ca4[0] == '+') || (ca4[0] == '-') || (ca4[0] == ' ')) {
2764 xlead = 1;
2765 }
2766
2767 int xdp = xlead;
2768
2769 for (; xdp < ca4.length; xdp++)
2770 if (ca4[xdp] == '.') {
2771 break;
2772 }
2773
2774 xThousands = (xdp - xlead) / 3;
2775 }
2776
2777 if (fieldWidthSet) {
2778 nZeros = fieldWidth - ca4.length;
2779 }
2780
2781 if ((!minusSign && (leadingSign || leadingSpace)) || minusSign) {
2782 nZeros--;
2783 }
2784
2785 nZeros -= xThousands;
2786
2787 if (nZeros < 0) {
2788 nZeros = 0;
2789 }
2790 }
2791
2792 j = 0;
2793
2794 if ((!minusSign && (leadingSign || leadingSpace)) || minusSign) {
2795 ca5 = new char[ca4.length + nZeros + 1];
2796 j++;
2797 } else {
2798 ca5 = new char[ca4.length + nZeros];
2799 }
2800
2801 if (!minusSign) {
2802 if (leadingSign) {
2803 ca5[0] = '+';
2804 }
2805
2806 if (leadingSpace) {
2807 ca5[0] = ' ';
2808 }
2809 } else {
2810 ca5[0] = '-';
2811 }
2812
2813 for (i = 0; i < nZeros; i++, j++)
2814 ca5[j] = '0';
2815
2816 for (i = 0; i < ca4.length; i++, j++)
2817 ca5[j] = ca4[i];
2818
2819 int lead = 0;
2820
2821 if ((ca5[0] == '+') || (ca5[0] == '-') || (ca5[0] == ' ')) {
2822 lead = 1;
2823 }
2824
2825 int dp = lead;
2826
2827 for (; dp < ca5.length; dp++)
2828 if (ca5[dp] == '.') {
2829 break;
2830 }
2831
2832 int nThousands = (dp - lead) / 3;
2833
2834
2835 if (dp < ca5.length) {
2836 ca5[dp] = dfs.getDecimalSeparator();
2837 }
2838
2839 char[] ca6 = ca5;
2840
2841 if (thousands && (nThousands > 0)) {
2842 ca6 = new char[ca5.length + nThousands + lead];
2843 ca6[0] = ca5[0];
2844
2845 for (i = lead, k = lead; i < dp; i++) {
2846 if ((i > 0) && (((dp - i) % 3) == 0)) {
2847
2848 ca6[k] = dfs.getGroupingSeparator();
2849 ca6[k + 1] = ca5[i];
2850 k += 2;
2851 } else {
2852 ca6[k] = ca5[i];
2853 k++;
2854 }
2855 }
2856
2857 for (; i < ca5.length; i++, k++) {
2858 ca6[k] = ca5[i];
2859 }
2860 }
2861
2862 return ca6;
2863 }
2864
2865
2866 /***
2867 * An intermediate routine on the way to creating an f format String.
2868 * The method decides whether the input double value is an infinity,
2869 * not-a-number, or a finite double and formats each type of input
2870 * appropriately.
2871 *
2872 * @param x the double value to be formatted.
2873 *
2874 * @return the converted double value.
2875 */
2876 private String fFormatString(double x) {
2877 char[] ca6;
2878 char[] ca7;
2879
2880 if (Double.isInfinite(x)) {
2881 if (x == Double.POSITIVE_INFINITY) {
2882 if (leadingSign) {
2883 ca6 = "+Inf".toCharArray();
2884 } else if (leadingSpace) {
2885 ca6 = " Inf".toCharArray();
2886 } else {
2887 ca6 = "Inf".toCharArray();
2888 }
2889 } else {
2890 ca6 = "-Inf".toCharArray();
2891 }
2892 } else if (Double.isNaN(x)) {
2893 if (leadingSign) {
2894 ca6 = "+NaN".toCharArray();
2895 } else if (leadingSpace) {
2896 ca6 = " NaN".toCharArray();
2897 } else {
2898 ca6 = "NaN".toCharArray();
2899 }
2900 } else {
2901 ca6 = fFormatDigits(x);
2902 }
2903
2904 ca7 = applyFloatPadding(ca6, false);
2905
2906 return new String(ca7);
2907 }
2908
2909
2910 /***
2911 * Format method for the c conversion character and char argument. The
2912 * only flag character that affects c format is the '-', meaning that
2913 * the output should be left justified within the field. The default is
2914 * to pad with blanks on the left. The field width is treated as the
2915 * minimum number of characters to be printed. Padding is with blanks
2916 * by default. The default width is 1. The precision, if set, is
2917 * ignored.
2918 *
2919 * @param x the char to format.
2920 *
2921 * @return the formatted String.
2922 */
2923 private String printCFormat(char x) {
2924 int nPrint = 1;
2925 int width = fieldWidth;
2926
2927 if (!fieldWidthSet) {
2928 width = nPrint;
2929 }
2930
2931 char[] ca = new char[width];
2932 int i = 0;
2933
2934 if (leftJustify) {
2935 ca[0] = x;
2936
2937 for (i = 1; i <= (width - nPrint); i++)
2938 ca[i] = ' ';
2939 } else {
2940 for (i = 0; i < (width - nPrint); i++)
2941 ca[i] = ' ';
2942
2943 ca[i] = x;
2944 }
2945
2946 return new String(ca);
2947 }
2948
2949
2950 /***
2951 * Format method for the d conversion specifer and short argument. For d
2952 * format, the flag character '-', means that the output should be left
2953 * justified within the field. The default is to pad with blanks on the
2954 * left. A '+' character means that the conversion will always begin
2955 * with a sign (+ or -). The blank flag character means that a
2956 * non-negative input will be preceded with a blank. If both a '+' and
2957 * a ' ' are specified, the blank flag is ignored. The '0' flag
2958 * character implies that padding to the field width will be done with
2959 * zeros instead of blanks. The field width is treated as the minimum
2960 * number of characters to be printed. The default is to add no
2961 * padding. Padding is with blanks by default. The precision, if set,
2962 * is the minimum number of digits to appear. Padding is with leading
2963 * 0s.
2964 *
2965 * @param x the short to format.
2966 *
2967 * @return the formatted String.
2968 */
2969 private String printDFormat(short x) {
2970 return printDFormat(Short.toString(x));
2971 }
2972
2973
2974 /***
2975 * Format method for the d conversion character and long argument. For d
2976 * format, the flag character '-', means that the output should be left
2977 * justified within the field. The default is to pad with blanks on the
2978 * left. A '+' character means that the conversion will always begin
2979 * with a sign (+ or -). The blank flag character means that a
2980 * non-negative input will be preceded with a blank. If both a '+' and
2981 * a ' ' are specified, the blank flag is ignored. The '0' flag
2982 * character implies that padding to the field width will be done with
2983 * zeros instead of blanks. The field width is treated as the minimum
2984 * number of characters to be printed. The default is to add no
2985 * padding. Padding is with blanks by default. The precision, if set,
2986 * is the minimum number of digits to appear. Padding is with leading
2987 * 0s.
2988 *
2989 * @param x the long to format.
2990 *
2991 * @return the formatted String.
2992 */
2993 private String printDFormat(long x) {
2994 return printDFormat(Long.toString(x));
2995 }
2996
2997
2998 /***
2999 * Format method for the d conversion character and int argument. For d
3000 * format, the flag character '-', means that the output should be left
3001 * justified within the field. The default is to pad with blanks on the
3002 * left. A '+' character means that the conversion will always begin
3003 * with a sign (+ or -). The blank flag character means that a
3004 * non-negative input will be preceded with a blank. If both a '+' and
3005 * a ' ' are specified, the blank flag is ignored. The '0' flag
3006 * character implies that padding to the field width will be done with
3007 * zeros instead of blanks. The field width is treated as the minimum
3008 * number of characters to be printed. The default is to add no
3009 * padding. Padding is with blanks by default. The precision, if set,
3010 * is the minimum number of digits to appear. Padding is with leading
3011 * 0s.
3012 *
3013 * @param x the int to format.
3014 *
3015 * @return the formatted String.
3016 */
3017 private String printDFormat(int x) {
3018 return printDFormat(Integer.toString(x));
3019 }
3020
3021
3022 /***
3023 * Utility method for formatting using the d conversion character.
3024 *
3025 * @param sx the String to format, the result of converting a short, int,
3026 * or long to a String.
3027 *
3028 * @return the formatted String.
3029 */
3030 private String printDFormat(String sx) {
3031 int nLeadingZeros = 0;
3032 int nBlanks = 0;
3033 int n = 0;
3034 int i = 0;
3035 int jFirst = 0;
3036 boolean neg = sx.charAt(0) == '-';
3037
3038 if (sx.equals("0") && precisionSet && (precision == 0)) {
3039 sx = "";
3040 }
3041
3042 if (!neg) {
3043 if (precisionSet && (sx.length() < precision)) {
3044 nLeadingZeros = precision - sx.length();
3045 }
3046 } else {
3047 if (precisionSet && ((sx.length() - 1) < precision)) {
3048 nLeadingZeros = precision - sx.length() + 1;
3049 }
3050 }
3051
3052 if (nLeadingZeros < 0) {
3053 nLeadingZeros = 0;
3054 }
3055
3056 if (fieldWidthSet) {
3057 nBlanks = fieldWidth - nLeadingZeros - sx.length();
3058
3059 if (!neg && (leadingSign || leadingSpace)) {
3060 nBlanks--;
3061 }
3062 }
3063
3064 if (nBlanks < 0) {
3065 nBlanks = 0;
3066 }
3067
3068 if (leadingSign) {
3069 n++;
3070 } else if (leadingSpace) {
3071 n++;
3072 }
3073
3074 n += nBlanks;
3075 n += nLeadingZeros;
3076 n += sx.length();
3077
3078 char[] ca = new char[n];
3079
3080 if (leftJustify) {
3081 if (neg) {
3082 ca[i++] = '-';
3083 } else if (leadingSign) {
3084 ca[i++] = '+';
3085 } else if (leadingSpace) {
3086 ca[i++] = ' ';
3087 }
3088
3089 char[] csx = sx.toCharArray();
3090 jFirst = neg ? 1
3091 : 0;
3092
3093 for (int j = 0; j < nLeadingZeros; i++, j++)
3094 ca[i] = '0';
3095
3096 for (int j = jFirst; j < csx.length; j++, i++)
3097 ca[i] = csx[j];
3098
3099 for (int j = 0; j < nBlanks; i++, j++)
3100 ca[i] = ' ';
3101 } else {
3102 if (!leadingZeros) {
3103 for (i = 0; i < nBlanks; i++)
3104 ca[i] = ' ';
3105
3106 if (neg) {
3107 ca[i++] = '-';
3108 } else if (leadingSign) {
3109 ca[i++] = '+';
3110 } else if (leadingSpace) {
3111 ca[i++] = ' ';
3112 }
3113 } else {
3114 if (neg) {
3115 ca[i++] = '-';
3116 } else if (leadingSign) {
3117 ca[i++] = '+';
3118 } else if (leadingSpace) {
3119 ca[i++] = ' ';
3120 }
3121
3122 for (int j = 0; j < nBlanks; j++, i++)
3123 ca[i] = '0';
3124 }
3125
3126 for (int j = 0; j < nLeadingZeros; j++, i++)
3127 ca[i] = '0';
3128
3129 char[] csx = sx.toCharArray();
3130 jFirst = neg ? 1
3131 : 0;
3132
3133 for (int j = jFirst; j < csx.length; j++, i++)
3134 ca[i] = csx[j];
3135 }
3136
3137 return new String(ca);
3138 }
3139
3140
3141 /***
3142 * Format method for the e or E conversion character.
3143 *
3144 * @param x the double to format.
3145 *
3146 * @return the formatted String.
3147 */
3148 private String printEFormat(double x) {
3149 if (conversionCharacter == 'e') {
3150 return eFormatString(x, 'e');
3151 } else {
3152 return eFormatString(x, 'E');
3153 }
3154 }
3155
3156
3157 /***
3158 * Format method for the f conversion character.
3159 *
3160 * @param x the double to format.
3161 *
3162 * @return the formatted String.
3163 */
3164 private String printFFormat(double x) {
3165 return fFormatString(x);
3166 }
3167
3168
3169 /***
3170 * Format method for the g conversion character. For g format, the flag
3171 * character '-', means that the output should be left justified within
3172 * the field. The default is to pad with blanks on the left. '+'
3173 * character means that the conversion will always begin with a sign (+
3174 * or -). The blank flag character means that a non-negative input will
3175 * be preceded with a blank. If both a '+' and a ' ' are specified, the
3176 * blank flag is ignored. The '0' flag character implies that padding
3177 * to the field width will be done with zeros instead of blanks. The
3178 * field width is treated as the minimum number of characters to be
3179 * printed. The default is to add no padding. Padding is with blanks
3180 * by default. The precision, if set, is the minimum number of digits to
3181 * appear after the radix character. Padding is with trailing 0s.
3182 *
3183 * @param x the double to format.
3184 *
3185 * @return the formatted String.
3186 */
3187 private String printGFormat(double x) {
3188 String sx;
3189 String sy;
3190 String sz;
3191 String ret;
3192 int savePrecision = precision;
3193 int i;
3194 char[] ca4;
3195 char[] ca5;
3196
3197 if (Double.isInfinite(x)) {
3198 if (x == Double.POSITIVE_INFINITY) {
3199 if (leadingSign) {
3200 ca4 = "+Inf".toCharArray();
3201 } else if (leadingSpace) {
3202 ca4 = " Inf".toCharArray();
3203 } else {
3204 ca4 = "Inf".toCharArray();
3205 }
3206 } else {
3207 ca4 = "-Inf".toCharArray();
3208 }
3209 } else if (Double.isNaN(x)) {
3210 if (leadingSign) {
3211 ca4 = "+NaN".toCharArray();
3212 } else if (leadingSpace) {
3213 ca4 = " NaN".toCharArray();
3214 } else {
3215 ca4 = "NaN".toCharArray();
3216 }
3217 } else {
3218 if (!precisionSet) {
3219 precision = DEFAULTDIGITS;
3220 }
3221
3222 if (precision == 0) {
3223 precision = 1;
3224 }
3225
3226 int ePos = -1;
3227
3228 if (conversionCharacter == 'g') {
3229 sx = eFormatString(x, 'e')
3230 .trim();
3231 ePos = sx.indexOf('e');
3232 } else {
3233 sx = eFormatString(x, 'E')
3234 .trim();
3235 ePos = sx.indexOf('E');
3236 }
3237
3238 i = ePos + 1;
3239
3240 int expon = 0;
3241
3242 if (sx.charAt(i) == '-') {
3243 for (++i; i < sx.length(); i++)
3244 if (sx.charAt(i) != '0') {
3245 break;
3246 }
3247
3248 if (i < sx.length()) {
3249 expon = -Integer.parseInt(sx.substring(i));
3250 }
3251 } else {
3252 if (sx.charAt(i) == '+') {
3253 ++i;
3254 }
3255
3256 for (; i < sx.length(); i++)
3257 if (sx.charAt(i) != '0') {
3258 break;
3259 }
3260
3261 if (i < sx.length()) {
3262 expon = Integer.parseInt(sx.substring(i));
3263 }
3264 }
3265
3266
3267
3268
3269 if (!alternateForm) {
3270 if ((expon >= -4) && (expon < precision)) {
3271 sy = fFormatString(x)
3272 .trim();
3273 } else {
3274 sy = sx.substring(0, ePos);
3275 }
3276
3277 i = sy.length() - 1;
3278
3279 for (; i >= 0; i--)
3280 if (sy.charAt(i) != '0') {
3281 break;
3282 }
3283
3284 if ((i >= 0) && (sy.charAt(i) == '.')) {
3285 i--;
3286 }
3287
3288 if (i == -1) {
3289 sz = "0";
3290 } else if (!Character.isDigit(sy.charAt(i))) {
3291 sz = sy.substring(0, i + 1) + "0";
3292 } else {
3293 sz = sy.substring(0, i + 1);
3294 }
3295
3296 if ((expon >= -4) && (expon < precision)) {
3297 ret = sz;
3298 } else {
3299 ret = sz + sx.substring(ePos);
3300 }
3301 } else {
3302 if ((expon >= -4) && (expon < precision)) {
3303 ret = fFormatString(x)
3304 .trim();
3305 } else {
3306 ret = sx;
3307 }
3308 }
3309
3310
3311
3312 if (leadingSpace) {
3313 if (x >= 0) {
3314 ret = " " + ret;
3315 }
3316 }
3317
3318 ca4 = ret.toCharArray();
3319 }
3320
3321
3322 ca5 = applyFloatPadding(ca4, false);
3323 precision = savePrecision;
3324
3325 return new String(ca5);
3326 }
3327
3328
3329 /***
3330 * Format method for the o conversion character and short argument. For o
3331 * format, the flag character '-', means that the output should be left
3332 * justified within the field. The default is to pad with blanks on the
3333 * left. The '#' flag character means that the output begins with a
3334 * leading 0 and the precision is increased by 1. The field width is
3335 * treated as the minimum number of characters to be printed. The
3336 * default is to add no padding. Padding is with blanks by default. The
3337 * precision, if set, is the minimum number of digits to appear.
3338 * Padding is with leading 0s.
3339 *
3340 * @param x the short to format.
3341 *
3342 * @return the formatted String.
3343 */
3344 private String printOFormat(short x) {
3345 String sx = null;
3346
3347 if (x == Short.MIN_VALUE) {
3348 sx = "100000";
3349 } else if (x < 0) {
3350 String t = Integer.toString((~(-x - 1)) ^ Short.MIN_VALUE, 8);
3351
3352 switch (t.length()) {
3353 case 1:
3354 sx = "10000" + t;
3355
3356 break;
3357
3358 case 2:
3359 sx = "1000" + t;
3360
3361 break;
3362
3363 case 3:
3364 sx = "100" + t;
3365
3366 break;
3367
3368 case 4:
3369 sx = "10" + t;
3370
3371 break;
3372
3373 case 5:
3374 sx = "1" + t;
3375
3376 break;
3377 }
3378 } else {
3379 sx = Integer.toString(x, 8);
3380 }
3381
3382 return printOFormat(sx);
3383 }
3384
3385
3386 /***
3387 * Format method for the o conversion character and long argument. For o
3388 * format, the flag character '-', means that the output should be left
3389 * justified within the field. The default is to pad with blanks on the
3390 * left. The '#' flag character means that the output begins with a
3391 * leading 0 and the precision is increased by 1. The field width is
3392 * treated as the minimum number of characters to be printed. The
3393 * default is to add no padding. Padding is with blanks by default. The
3394 * precision, if set, is the minimum number of digits to appear.
3395 * Padding is with leading 0s.
3396 *
3397 * @param x the long to format.
3398 *
3399 * @return the formatted String.
3400 */
3401 private String printOFormat(long x) {
3402 String sx = null;
3403
3404 if (x == Long.MIN_VALUE) {
3405 sx = "1000000000000000000000";
3406 } else if (x < 0) {
3407 String t = Long.toString((~(-x - 1)) ^ Long.MIN_VALUE, 8);
3408
3409 switch (t.length()) {
3410 case 1:
3411 sx = "100000000000000000000" + t;
3412
3413 break;
3414
3415 case 2:
3416 sx = "10000000000000000000" + t;
3417
3418 break;
3419
3420 case 3:
3421 sx = "1000000000000000000" + t;
3422
3423 break;
3424
3425 case 4:
3426 sx = "100000000000000000" + t;
3427
3428 break;
3429
3430 case 5:
3431 sx = "10000000000000000" + t;
3432
3433 break;
3434
3435 case 6:
3436 sx = "1000000000000000" + t;
3437
3438 break;
3439
3440 case 7:
3441 sx = "100000000000000" + t;
3442
3443 break;
3444
3445 case 8:
3446 sx = "10000000000000" + t;
3447
3448 break;
3449
3450 case 9:
3451 sx = "1000000000000" + t;
3452
3453 break;
3454
3455 case 10:
3456 sx = "100000000000" + t;
3457
3458 break;
3459
3460 case 11:
3461 sx = "10000000000" + t;
3462
3463 break;
3464
3465 case 12:
3466 sx = "1000000000" + t;
3467
3468 break;
3469
3470 case 13:
3471 sx = "100000000" + t;
3472
3473 break;
3474
3475 case 14:
3476 sx = "10000000" + t;
3477
3478 break;
3479
3480 case 15:
3481 sx = "1000000" + t;
3482
3483 break;
3484
3485 case 16:
3486 sx = "100000" + t;
3487
3488 break;
3489
3490 case 17:
3491 sx = "10000" + t;
3492
3493 break;
3494
3495 case 18:
3496 sx = "1000" + t;
3497
3498 break;
3499
3500 case 19:
3501 sx = "100" + t;
3502
3503 break;
3504
3505 case 20:
3506 sx = "10" + t;
3507
3508 break;
3509
3510 case 21:
3511 sx = "1" + t;
3512
3513 break;
3514 }
3515 } else {
3516 sx = Long.toString(x, 8);
3517 }
3518
3519 return printOFormat(sx);
3520 }
3521
3522
3523 /***
3524 * Format method for the o conversion character and int argument. For o
3525 * format, the flag character '-', means that the output should be left
3526 * justified within the field. The default is to pad with blanks on the
3527 * left. The '#' flag character means that the output begins with a
3528 * leading 0 and the precision is increased by 1. The field width is
3529 * treated as the minimum number of characters to be printed. The
3530 * default is to add no padding. Padding is with blanks by default. The
3531 * precision, if set, is the minimum number of digits to appear.
3532 * Padding is with leading 0s.
3533 *
3534 * @param x the int to format.
3535 *
3536 * @return the formatted String.
3537 */
3538 private String printOFormat(int x) {
3539 String sx = null;
3540
3541 if (x == Integer.MIN_VALUE) {
3542 sx = "20000000000";
3543 } else if (x < 0) {
3544 String t = Integer.toString((~(-x - 1)) ^ Integer.MIN_VALUE, 8);
3545
3546 switch (t.length()) {
3547 case 1:
3548 sx = "2000000000" + t;
3549
3550 break;
3551
3552 case 2:
3553 sx = "200000000" + t;
3554
3555 break;
3556
3557 case 3:
3558 sx = "20000000" + t;
3559
3560 break;
3561
3562 case 4:
3563 sx = "2000000" + t;
3564
3565 break;
3566
3567 case 5:
3568 sx = "200000" + t;
3569
3570 break;
3571
3572 case 6:
3573 sx = "20000" + t;
3574
3575 break;
3576
3577 case 7:
3578 sx = "2000" + t;
3579
3580 break;
3581
3582 case 8:
3583 sx = "200" + t;
3584
3585 break;
3586
3587 case 9:
3588 sx = "20" + t;
3589
3590 break;
3591
3592 case 10:
3593 sx = "2" + t;
3594
3595 break;
3596
3597 case 11:
3598 sx = "3" + t.substring(1);
3599
3600 break;
3601 }
3602 } else {
3603 sx = Integer.toString(x, 8);
3604 }
3605
3606 return printOFormat(sx);
3607 }
3608
3609
3610 /***
3611 * Utility method for formatting using the o conversion character.
3612 *
3613 * @param sx the String to format, the result of converting a short, int,
3614 * or long to a String.
3615 *
3616 * @return the formatted String.
3617 */
3618 private String printOFormat(String sx) {
3619 int nLeadingZeros = 0;
3620 int nBlanks = 0;
3621
3622 if (sx.equals("0") && precisionSet && (precision == 0)) {
3623 sx = "";
3624 }
3625
3626 if (precisionSet) {
3627 nLeadingZeros = precision - sx.length();
3628 }
3629
3630 if (alternateForm) {
3631 nLeadingZeros++;
3632 }
3633
3634 if (nLeadingZeros < 0) {
3635 nLeadingZeros = 0;
3636 }
3637
3638 if (fieldWidthSet) {
3639 nBlanks = fieldWidth - nLeadingZeros - sx.length();
3640 }
3641
3642 if (nBlanks < 0) {
3643 nBlanks = 0;
3644 }
3645
3646 int n = nLeadingZeros + sx.length() + nBlanks;
3647 char[] ca = new char[n];
3648 int i;
3649
3650 if (leftJustify) {
3651 for (i = 0; i < nLeadingZeros; i++)
3652 ca[i] = '0';
3653
3654 char[] csx = sx.toCharArray();
3655
3656 for (int j = 0; j < csx.length; j++, i++)
3657 ca[i] = csx[j];
3658
3659 for (int j = 0; j < nBlanks; j++, i++)
3660 ca[i] = ' ';
3661 } else {
3662 if (leadingZeros) {
3663 for (i = 0; i < nBlanks; i++)
3664 ca[i] = '0';
3665 } else {
3666 for (i = 0; i < nBlanks; i++)
3667 ca[i] = ' ';
3668 }
3669
3670 for (int j = 0; j < nLeadingZeros; j++, i++)
3671 ca[i] = '0';
3672
3673 char[] csx = sx.toCharArray();
3674
3675 for (int j = 0; j < csx.length; j++, i++)
3676 ca[i] = csx[j];
3677 }
3678
3679 return new String(ca);
3680 }
3681
3682
3683 /***
3684 * Format method for the s conversion character and String argument. The
3685 * only flag character that affects s format is the '-', meaning that
3686 * the output should be left justified within the field. The default is
3687 * to pad with blanks on the left. The field width is treated as the
3688 * minimum number of characters to be printed. The default is the
3689 * smaller of the number of characters in the the input and the
3690 * precision. Padding is with blanks by default. The precision, if set,
3691 * specifies the maximum number of characters to be printed from the
3692 * string. A null digit string is treated as a 0. The default is not
3693 * to set a maximum number of characters to be printed.
3694 *
3695 * @param x the String to format.
3696 *
3697 * @return the formatted String.
3698 */
3699 private String printSFormat(String x) {
3700 int nPrint = x.length();
3701 int width = fieldWidth;
3702
3703 if (precisionSet && (nPrint > precision)) {
3704 nPrint = precision;
3705 }
3706
3707 if (!fieldWidthSet) {
3708 width = nPrint;
3709 }
3710
3711 int n = 0;
3712
3713 if (width > nPrint) {
3714 n += (width - nPrint);
3715 }
3716
3717 if (nPrint >= x.length()) {
3718 n += x.length();
3719 } else {
3720 n += nPrint;
3721 }
3722
3723 char[] ca = new char[n];
3724 int i = 0;
3725
3726 if (leftJustify) {
3727 if (nPrint >= x.length()) {
3728 char[] csx = x.toCharArray();
3729
3730 for (i = 0; i < x.length(); i++)
3731 ca[i] = csx[i];
3732 } else {
3733 char[] csx = x.substring(0, nPrint)
3734 .toCharArray();
3735
3736 for (i = 0; i < nPrint; i++)
3737 ca[i] = csx[i];
3738 }
3739
3740 for (int j = 0; j < (width - nPrint); j++, i++)
3741 ca[i] = ' ';
3742 } else {
3743 for (i = 0; i < (width - nPrint); i++)
3744 ca[i] = ' ';
3745
3746 if (nPrint >= x.length()) {
3747 char[] csx = x.toCharArray();
3748
3749 for (int j = 0; j < x.length(); i++, j++)
3750 ca[i] = csx[j];
3751 } else {
3752 char[] csx = x.substring(0, nPrint)
3753 .toCharArray();
3754
3755 for (int j = 0; j < nPrint; i++, j++)
3756 ca[i] = csx[j];
3757 }
3758 }
3759
3760 return new String(ca);
3761 }
3762
3763
3764 /***
3765 * Format method for the x conversion character and short argument. For x
3766 * format, the flag character '-', means that the output should be left
3767 * justified within the field. The default is to pad with blanks on the
3768 * left. The '#' flag character means to lead with '0x'. The field
3769 * width is treated as the minimum number of characters to be printed.
3770 * The default is to add no padding. Padding is with blanks by default.
3771 * The precision, if set, is the minimum number of digits to appear.
3772 * Padding is with leading 0s.
3773 *
3774 * @param x the short to format.
3775 *
3776 * @return the formatted String.
3777 */
3778 private String printXFormat(short x) {
3779 String sx = null;
3780
3781 if (x == Short.MIN_VALUE) {
3782 sx = "8000";
3783 } else if (x < 0) {
3784 String t;
3785
3786 if (x == Short.MIN_VALUE) {
3787 t = "0";
3788 } else {
3789 t = Integer.toString((~(-x - 1)) ^ Short.MIN_VALUE, 16);
3790
3791 if ((t.charAt(0) == 'F') || (t.charAt(0) == 'f')) {
3792 t = t.substring(16, 32);
3793 }
3794 }
3795
3796 switch (t.length()) {
3797 case 1:
3798 sx = "800" + t;
3799
3800 break;
3801
3802 case 2:
3803 sx = "80" + t;
3804
3805 break;
3806
3807 case 3:
3808 sx = "8" + t;
3809
3810 break;
3811
3812 case 4:
3813
3814 switch (t.charAt(0)) {
3815 case '1':
3816 sx = "9" + t.substring(1, 4);
3817
3818 break;
3819
3820 case '2':
3821 sx = "a" + t.substring(1, 4);
3822
3823 break;
3824
3825 case '3':
3826 sx = "b" + t.substring(1, 4);
3827
3828 break;
3829
3830 case '4':
3831 sx = "c" + t.substring(1, 4);
3832
3833 break;
3834
3835 case '5':
3836 sx = "d" + t.substring(1, 4);
3837
3838 break;
3839
3840 case '6':
3841 sx = "e" + t.substring(1, 4);
3842
3843 break;
3844
3845 case '7':
3846 sx = "f" + t.substring(1, 4);
3847
3848 break;
3849 }
3850
3851 break;
3852 }
3853 } else {
3854 sx = Integer.toString(x, 16);
3855 }
3856
3857 return printXFormat(sx);
3858 }
3859
3860
3861 /***
3862 * Format method for the x conversion character and long argument. For x
3863 * format, the flag character '-', means that the output should be left
3864 * justified within the field. The default is to pad with blanks on the
3865 * left. The '#' flag character means to lead with '0x'. The field
3866 * width is treated as the minimum number of characters to be printed.
3867 * The default is to add no padding. Padding is with blanks by default.
3868 * The precision, if set, is the minimum number of digits to appear.
3869 * Padding is with leading 0s.
3870 *
3871 * @param x the long to format.
3872 *
3873 * @return the formatted String.
3874 */
3875 private String printXFormat(long x) {
3876 String sx = null;
3877
3878 if (x == Long.MIN_VALUE) {
3879 sx = "8000000000000000";
3880 } else if (x < 0) {
3881 String t = Long.toString((~(-x - 1)) ^ Long.MIN_VALUE, 16);
3882
3883 switch (t.length()) {
3884 case 1:
3885 sx = "800000000000000" + t;
3886
3887 break;
3888
3889 case 2:
3890 sx = "80000000000000" + t;
3891
3892 break;
3893
3894 case 3:
3895 sx = "8000000000000" + t;
3896
3897 break;
3898
3899 case 4:
3900 sx = "800000000000" + t;
3901
3902 break;
3903
3904 case 5:
3905 sx = "80000000000" + t;
3906
3907 break;
3908
3909 case 6:
3910 sx = "8000000000" + t;
3911
3912 break;
3913
3914 case 7:
3915 sx = "800000000" + t;
3916
3917 break;
3918
3919 case 8:
3920 sx = "80000000" + t;
3921
3922 break;
3923
3924 case 9:
3925 sx = "8000000" + t;
3926
3927 break;
3928
3929 case 10:
3930 sx = "800000" + t;
3931
3932 break;
3933
3934 case 11:
3935 sx = "80000" + t;
3936
3937 break;
3938
3939 case 12:
3940 sx = "8000" + t;
3941
3942 break;
3943
3944 case 13:
3945 sx = "800" + t;
3946
3947 break;
3948
3949 case 14:
3950 sx = "80" + t;
3951
3952 break;
3953
3954 case 15:
3955 sx = "8" + t;
3956
3957 break;
3958
3959 case 16:
3960
3961 switch (t.charAt(0)) {
3962 case '1':
3963 sx = "9" + t.substring(1, 16);
3964
3965 break;
3966
3967 case '2':
3968 sx = "a" + t.substring(1, 16);
3969
3970 break;
3971
3972 case '3':
3973 sx = "b" + t.substring(1, 16);
3974
3975 break;
3976
3977 case '4':
3978 sx = "c" + t.substring(1, 16);
3979
3980 break;
3981
3982 case '5':
3983 sx = "d" + t.substring(1, 16);
3984
3985 break;
3986
3987 case '6':
3988 sx = "e" + t.substring(1, 16);
3989
3990 break;
3991
3992 case '7':
3993 sx = "f" + t.substring(1, 16);
3994
3995 break;
3996 }
3997
3998 break;
3999 }
4000 } else {
4001 sx = Long.toString(x, 16);
4002 }
4003
4004 return printXFormat(sx);
4005 }
4006
4007
4008 /***
4009 * Format method for the x conversion character and int argument. For x
4010 * format, the flag character '-', means that the output should be left
4011 * justified within the field. The default is to pad with blanks on the
4012 * left. The '#' flag character means to lead with '0x'. The field
4013 * width is treated as the minimum number of characters to be printed.
4014 * The default is to add no padding. Padding is with blanks by default.
4015 * The precision, if set, is the minimum number of digits to appear.
4016 * Padding is with leading 0s.
4017 *
4018 * @param x the int to format.
4019 *
4020 * @return the formatted String.
4021 */
4022 private String printXFormat(int x) {
4023 String sx = null;
4024
4025 if (x == Integer.MIN_VALUE) {
4026 sx = "80000000";
4027 } else if (x < 0) {
4028 String t = Integer.toString((~(-x - 1)) ^ Integer.MIN_VALUE, 16);
4029
4030 switch (t.length()) {
4031 case 1:
4032 sx = "8000000" + t;
4033
4034 break;
4035
4036 case 2:
4037 sx = "800000" + t;
4038
4039 break;
4040
4041 case 3:
4042 sx = "80000" + t;
4043
4044 break;
4045
4046 case 4:
4047 sx = "8000" + t;
4048
4049 break;
4050
4051 case 5:
4052 sx = "800" + t;
4053
4054 break;
4055
4056 case 6:
4057 sx = "80" + t;
4058
4059 break;
4060
4061 case 7:
4062 sx = "8" + t;
4063
4064 break;
4065
4066 case 8:
4067
4068 switch (t.charAt(0)) {
4069 case '1':
4070 sx = "9" + t.substring(1, 8);
4071
4072 break;
4073
4074 case '2':
4075 sx = "a" + t.substring(1, 8);
4076
4077 break;
4078
4079 case '3':
4080 sx = "b" + t.substring(1, 8);
4081
4082 break;
4083
4084 case '4':
4085 sx = "c" + t.substring(1, 8);
4086
4087 break;
4088
4089 case '5':
4090 sx = "d" + t.substring(1, 8);
4091
4092 break;
4093
4094 case '6':
4095 sx = "e" + t.substring(1, 8);
4096
4097 break;
4098
4099 case '7':
4100 sx = "f" + t.substring(1, 8);
4101
4102 break;
4103 }
4104
4105 break;
4106 }
4107 } else {
4108 sx = Integer.toString(x, 16);
4109 }
4110
4111 return printXFormat(sx);
4112 }
4113
4114
4115 /***
4116 * Utility method for formatting using the x conversion character.
4117 *
4118 * @param sx the String to format, the result of converting a short, int,
4119 * or long to a String.
4120 *
4121 * @return the formatted String.
4122 */
4123 private String printXFormat(String sx) {
4124 int nLeadingZeros = 0;
4125 int nBlanks = 0;
4126
4127 if (sx.equals("0") && precisionSet && (precision == 0)) {
4128 sx = "";
4129 }
4130
4131 if (precisionSet) {
4132 nLeadingZeros = precision - sx.length();
4133 }
4134
4135 if (nLeadingZeros < 0) {
4136 nLeadingZeros = 0;
4137 }
4138
4139 if (fieldWidthSet) {
4140 nBlanks = fieldWidth - nLeadingZeros - sx.length();
4141
4142 if (alternateForm) {
4143 nBlanks = nBlanks - 2;
4144 }
4145 }
4146
4147 if (nBlanks < 0) {
4148 nBlanks = 0;
4149 }
4150
4151 int n = 0;
4152
4153 if (alternateForm) {
4154 n += 2;
4155 }
4156
4157 n += nLeadingZeros;
4158 n += sx.length();
4159 n += nBlanks;
4160
4161 char[] ca = new char[n];
4162 int i = 0;
4163
4164 if (leftJustify) {
4165 if (alternateForm) {
4166 ca[i++] = '0';
4167 ca[i++] = 'x';
4168 }
4169
4170 for (int j = 0; j < nLeadingZeros; j++, i++)
4171 ca[i] = '0';
4172
4173 char[] csx = sx.toCharArray();
4174
4175 for (int j = 0; j < csx.length; j++, i++)
4176 ca[i] = csx[j];
4177
4178 for (int j = 0; j < nBlanks; j++, i++)
4179 ca[i] = ' ';
4180 } else {
4181 if (!leadingZeros) {
4182 for (int j = 0; j < nBlanks; j++, i++)
4183 ca[i] = ' ';
4184 }
4185
4186 if (alternateForm) {
4187 ca[i++] = '0';
4188 ca[i++] = 'x';
4189 }
4190
4191 if (leadingZeros) {
4192 for (int j = 0; j < nBlanks; j++, i++)
4193 ca[i] = '0';
4194 }
4195
4196 for (int j = 0; j < nLeadingZeros; j++, i++)
4197 ca[i] = '0';
4198
4199 char[] csx = sx.toCharArray();
4200
4201 for (int j = 0; j < csx.length; j++, i++)
4202 ca[i] = csx[j];
4203 }
4204
4205 String caReturn = new String(ca);
4206
4207 if (conversionCharacter == 'X') {
4208 caReturn = caReturn.toUpperCase();
4209 }
4210
4211 return caReturn;
4212 }
4213
4214
4215 /***
4216 * Start the symbolic carry process. The process is not quite finished
4217 * because the symbolic carry may change the length of the string and
4218 * change the exponent (in e format).
4219 *
4220 * @param ca DOCUMENT ME!
4221 * @param cLast index of the last digit changed by the round
4222 * @param cFirst index of the first digit allowed to be changed by this
4223 * phase of the round
4224 *
4225 * @return <code>true</code> if the carry forces a round that will change
4226 * the print still more
4227 */
4228 private boolean startSymbolicCarry(char[] ca,
4229 int cLast,
4230 int cFirst) {
4231 boolean carry = true;
4232
4233 for (int i = cLast; carry && (i >= cFirst); i--) {
4234 carry = false;
4235
4236 switch (ca[i]) {
4237 case '0':
4238 ca[i] = '1';
4239
4240 break;
4241
4242 case '1':
4243 ca[i] = '2';
4244
4245 break;
4246
4247 case '2':
4248 ca[i] = '3';
4249
4250 break;
4251
4252 case '3':
4253 ca[i] = '4';
4254
4255 break;
4256
4257 case '4':
4258 ca[i] = '5';
4259
4260 break;
4261
4262 case '5':
4263 ca[i] = '6';
4264
4265 break;
4266
4267 case '6':
4268 ca[i] = '7';
4269
4270 break;
4271
4272 case '7':
4273 ca[i] = '8';
4274
4275 break;
4276
4277 case '8':
4278 ca[i] = '9';
4279
4280 break;
4281
4282 case '9':
4283 ca[i] = '0';
4284 carry = true;
4285
4286 break;
4287 }
4288 }
4289
4290 return carry;
4291 }
4292 }
4293 }