1 package net.bonzoun.cocodonkey;
2
3
4
5 //
6 // (c) 2000 Sun Microsystems, Inc.
7 // ALL RIGHTS RESERVED
8 //
9 // License Grant-
10 //
11 //
12 // Permission to use, copy, modify, and distribute this Software and its
13 // documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee is
14 // hereby granted.
15 //
16 // This Software is provided "AS IS". All express warranties, including any
17 // implied warranty of merchantability, satisfactory quality, fitness for a
18 // particular purpose, or non-infringement, are disclaimed, except to the extent
19 // that such disclaimers are held to be legally invalid.
20 //
21 // You acknowledge that Software is not designed, licensed or intended for use in
22 // the design, construction, operation or maintenance of any nuclear facility
23 // ("High Risk Activities"). Sun disclaims any express or implied warranty of
24 // fitness for such uses.
25 //
26 // Please refer to the file http://www.sun.com/policies/trademarks/ for further
27 // important trademark information and to
28 // http://java.sun.com/nav/business/index.html for further important licensing
29 // information for the Java Technology.
30 //
31
32
33 import java.util.Enumeration;
34 import java.util.Vector;
35 import java.util.Locale;
36 import java.text.DecimalFormatSymbols;
37
38 /**
39 * PrintfFormat allows the formatting of an array of
40 * objects embedded within a string. Primitive types
41 * must be passed using wrapper types. The formatting
42 * is controlled by a control string.
43 *<p>
44 * A control string is a Java string that contains a
45 * control specification. The control specification
46 * starts at the first percent sign (%) in the string,
47 * provided that this percent sign
48 *<ol>
49 *<li>is not escaped protected by a matching % or is
50 * not an escape % character,
51 *<li>is not at the end of the format string, and
52 *<li>precedes a sequence of characters that parses as
53 * a valid control specification.
54 *</ol>
55 *</p><p>
56 * A control specification usually takes the form:
57 *<pre> % ['-+ #0]* [0..9]* { . [0..9]* }+
58 * { [hlL] }+ [idfgGoxXeEcs]
59 *</pre>
60 * There are variants of this basic form that are
61 * discussed below.</p>
62 *<p>
63 * The format is composed of zero or more directives
64 * defined as follows:
65 *<ul>
66 *<li>ordinary characters, which are simply copied to
67 * the output stream;
68 *<li>escape sequences, which represent non-graphic
69 * characters; and
70 *<li>conversion specifications, each of which
71 * results in the fetching of zero or more arguments.
72 *</ul></p>
73 *<p>
74 * The results are undefined if there are insufficient
75 * arguments for the format. Usually an unchecked
76 * exception will be thrown. If the format is
77 * exhausted while arguments remain, the excess
78 * arguments are evaluated but are otherwise ignored.
79 * In format strings containing the % form of
80 * conversion specifications, each argument in the
81 * argument list is used exactly once.</p>
82 * <p>
83 * Conversions can be applied to the <code>n</code>th
84 * argument after the format in the argument list,
85 * rather than to the next unused argument. In this
86 * case, the conversion characer % is replaced by the
87 * sequence %<code>n</code>$, where <code>n</code> is
88 * a decimal integer giving the position of the
89 * argument in the argument list.</p>
90 * <p>
91 * In format strings containing the %<code>n</code>$
92 * form of conversion specifications, each argument
93 * in the argument list is used exactly once.</p>
94 *
95 *<h4>Escape Sequences</h4>
96 *<p>
97 * The following table lists escape sequences and
98 * associated actions on display devices capable of
99 * the action.
100 *<table>
101 *<tr><th align=left>Sequence</th>
102 * <th align=left>Name</th>
103 * <th align=left>Description</th></tr>
104 *<tr><td>\\</td><td>backlash</td><td>None.
105 *</td></tr>
106 *<tr><td>\a</td><td>alert</td><td>Attempts to alert
107 * the user through audible or visible
108 * notification.
109 *</td></tr>
110 *<tr><td>\b</td><td>backspace</td><td>Moves the
111 * printing position to one column before
112 * the current position, unless the
113 * current position is the start of a line.
114 *</td></tr>
115 *<tr><td>\f</td><td>form-feed</td><td>Moves the
116 * printing position to the initial
117 * printing position of the next logical
118 * page.
119 *</td></tr>
120 *<tr><td>\n</td><td>newline</td><td>Moves the
121 * printing position to the start of the
122 * next line.
123 *</td></tr>
124 *<tr><td>\r</td><td>carriage-return</td><td>Moves
125 * the printing position to the start of
126 * the current line.
127 *</td></tr>
128 *<tr><td>\t</td><td>tab</td><td>Moves the printing
129 * position to the next implementation-
130 * defined horizontal tab position.
131 *</td></tr>
132 *<tr><td>\v</td><td>vertical-tab</td><td>Moves the
133 * printing position to the start of the
134 * next implementation-defined vertical
135 * tab position.
136 *</td></tr>
137 *</table></p>
138 *<h4>Conversion Specifications</h4>
139 *<p>
140 * Each conversion specification is introduced by
141 * the percent sign character (%). After the character
142 * %, the following appear in sequence:</p>
143 *<p>
144 * Zero or more flags (in any order), which modify the
145 * meaning of the conversion specification.</p>
146 *<p>
147 * An optional minimum field width. If the converted
148 * value has fewer characters than the field width, it
149 * will be padded with spaces by default on the left;
150 * t will be padded on the right, if the left-
151 * adjustment flag (-), described below, is given to
152 * the field width. The field width takes the form
153 * of a decimal integer. If the conversion character
154 * is s, the field width is the the minimum number of
155 * characters to be printed.</p>
156 *<p>
157 * An optional precision that gives the minumum number
158 * of digits to appear for the d, i, o, x or X
159 * conversions (the field is padded with leading
160 * zeros); the number of digits to appear after the
161 * radix character for the e, E, and f conversions,
162 * the maximum number of significant digits for the g
163 * and G conversions; or the maximum number of
164 * characters to be written from a string is s and S
165 * conversions. The precision takes the form of an
166 * optional decimal digit string, where a null digit
167 * string is treated as 0. If a precision appears
168 * with a c conversion character the precision is
169 * ignored.
170 * </p>
171 *<p>
172 * An optional h specifies that a following d, i, o,
173 * x, or X conversion character applies to a type
174 * short argument (the argument will be promoted
175 * according to the integral promotions and its value
176 * converted to type short before printing).</p>
177 *<p>
178 * An optional l (ell) specifies that a following
179 * d, i, o, x, or X conversion character applies to a
180 * type long argument.</p>
181 *<p>
182 * A field width or precision may be indicated by an
183 * asterisk (*) instead of a digit string. In this
184 * case, an integer argument supplised the field width
185 * precision. The argument that is actually converted
186 * is not fetched until the conversion letter is seen,
187 * so the the arguments specifying field width or
188 * precision must appear before the argument (if any)
189 * to be converted. If the precision argument is
190 * negative, it will be changed to zero. A negative
191 * field width argument is taken as a - flag, followed
192 * by a positive field width.</p>
193 * <p>
194 * In format strings containing the %<code>n</code>$
195 * form of a conversion specification, a field width
196 * or precision may be indicated by the sequence
197 * *<code>m</code>$, where m is a decimal integer
198 * giving the position in the argument list (after the
199 * format argument) of an integer argument containing
200 * the field width or precision.</p>
201 * <p>
202 * The format can contain either numbered argument
203 * specifications (that is, %<code>n</code>$ and
204 * *<code>m</code>$), or unnumbered argument
205 * specifications (that is % and *), but normally not
206 * both. The only exception to this is that %% can
207 * be mixed with the %<code>n</code>$ form. The
208 * results of mixing numbered and unnumbered argument
209 * specifications in a format string are undefined.</p>
210 *
211 *<h4>Flag Characters</h4>
212 *<p>
213 * The flags and their meanings are:</p>
214 *<dl>
215 * <dt>'<dd> integer portion of the result of a
216 * decimal conversion (%i, %d, %f, %g, or %G) will
217 * be formatted with thousands' grouping
218 * characters. For other conversions the flag
219 * is ignored. The non-monetary grouping
220 * character is used.
221 * <dt>-<dd> result of the conversion is left-justified
222 * within the field. (It will be right-justified
223 * if this flag is not specified).</td></tr>
224 * <dt>+<dd> result of a signed conversion always
225 * begins with a sign (+ or -). (It will begin
226 * with a sign only when a negative value is
227 * converted if this flag is not specified.)
228 * <dt><space><dd> If the first character of a
229 * signed conversion is not a sign, a space
230 * character will be placed before the result.
231 * This means that if the space character and +
232 * flags both appear, the space flag will be
233 * ignored.
234 * <dt>#<dd> value is to be converted to an alternative
235 * form. For c, d, i, and s conversions, the flag
236 * has no effect. For o conversion, it increases
237 * the precision to force the first digit of the
238 * result to be a zero. For x or X conversion, a
239 * non-zero result has 0x or 0X prefixed to it,
240 * respectively. For e, E, f, g, and G
241 * conversions, the result always contains a radix
242 * character, even if no digits follow the radix
243 * character (normally, a decimal point appears in
244 * the result of these conversions only if a digit
245 * follows it). For g and G conversions, trailing
246 * zeros will not be removed from the result as
247 * they normally are.
248 * <dt>0<dd> d, i, o, x, X, e, E, f, g, and G
249 * conversions, leading zeros (following any
250 * indication of sign or base) are used to pad to
251 * the field width; no space padding is
252 * performed. If the 0 and - flags both appear,
253 * the 0 flag is ignored. For d, i, o, x, and X
254 * conversions, if a precision is specified, the
255 * 0 flag will be ignored. For c conversions,
256 * the flag is ignored.
257 *</dl>
258 *
259 *<h4>Conversion Characters</h4>
260 *<p>
261 * Each conversion character results in fetching zero
262 * or more arguments. The results are undefined if
263 * there are insufficient arguments for the format.
264 * Usually, an unchecked exception will be thrown.
265 * If the format is exhausted while arguments remain,
266 * the excess arguments are ignored.</p>
267 *
268 *<p>
269 * The conversion characters and their meanings are:
270 *</p>
271 *<dl>
272 * <dt>d,i<dd>The int argument is converted to a
273 * signed decimal in the style [-]dddd. The
274 * precision specifies the minimum number of
275 * digits to appear; if the value being
276 * converted can be represented in fewer
277 * digits, it will be expanded with leading
278 * zeros. The default precision is 1. The
279 * result of converting 0 with an explicit
280 * precision of 0 is no characters.
281 * <dt>o<dd> The int argument is converted to unsigned
282 * octal format in the style ddddd. The
283 * precision specifies the minimum number of
284 * digits to appear; if the value being
285 * converted can be represented in fewer
286 * digits, it will be expanded with leading
287 * zeros. The default precision is 1. The
288 * result of converting 0 with an explicit
289 * precision of 0 is no characters.
290 * <dt>x<dd> The int argument is converted to unsigned
291 * hexadecimal format in the style dddd; the
292 * letters abcdef are used. The precision
293 * specifies the minimum numberof digits to
294 * appear; if the value being converted can be
295 * represented in fewer digits, it will be
296 * expanded with leading zeros. The default
297 * precision is 1. The result of converting 0
298 * with an explicit precision of 0 is no
299 * characters.
300 * <dt>X<dd> Behaves the same as the x conversion
301 * character except that letters ABCDEF are
302 * used instead of abcdef.
303 * <dt>f<dd> The floating point number argument is
304 * written in decimal notation in the style
305 * [-]ddd.ddd, where the number of digits after
306 * the radix character (shown here as a decimal
307 * point) is equal to the precision
308 * specification. A Locale is used to determine
309 * the radix character to use in this format.
310 * If the precision is omitted from the
311 * argument, six digits are written after the
312 * radix character; if the precision is
313 * explicitly 0 and the # flag is not specified,
314 * no radix character appears. If a radix
315 * character appears, at least 1 digit appears
316 * before it. The value is rounded to the
317 * appropriate number of digits.
318 * <dt>e,E<dd>The floating point number argument is
319 * written in the style [-]d.ddde{+-}dd
320 * (the symbols {+-} indicate either a plus or
321 * minus sign), where there is one digit before
322 * the radix character (shown here as a decimal
323 * point) and the number of digits after it is
324 * equal to the precision. A Locale is used to
325 * determine the radix character to use in this
326 * format. When the precision is missing, six
327 * digits are written after the radix character;
328 * if the precision is 0 and the # flag is not
329 * specified, no radix character appears. The
330 * E conversion will produce a number with E
331 * instead of e introducing the exponent. The
332 * exponent always contains at least two digits.
333 * However, if the value to be written requires
334 * an exponent greater than two digits,
335 * additional exponent digits are written as
336 * necessary. The value is rounded to the
337 * appropriate number of digits.
338 * <dt>g,G<dd>The floating point number argument is
339 * written in style f or e (or in sytle E in the
340 * case of a G conversion character), with the
341 * precision specifying the number of
342 * significant digits. If the precision is
343 * zero, it is taken as one. The style used
344 * depends on the value converted: style e
345 * (or E) will be used only if the exponent
346 * resulting from the conversion is less than
347 * -4 or greater than or equal to the precision.
348 * Trailing zeros are removed from the result.
349 * A radix character appears only if it is
350 * followed by a digit.
351 * <dt>c,C<dd>The integer argument is converted to a
352 * char and the result is written.
353 *
354 * <dt>s,S<dd>The argument is taken to be a string and
355 * bytes from the string are written until the
356 * end of the string or the number of bytes
357 * indicated by the precision specification of
358 * the argument is reached. If the precision
359 * is omitted from the argument, it is taken to
360 * be infinite, so all characters up to the end
361 * of the string are written.
362 * <dt>%<dd>Write a % character; no argument is
363 * converted.
364 *</dl>
365 *<p>
366 * If a conversion specification does not match one of
367 * the above forms, an IllegalArgumentException is
368 * thrown and the instance of PrintfFormat is not
369 * created.</p>
370 *<p>
371 * If a floating point value is the internal
372 * representation for infinity, the output is
373 * [+]Infinity, where Infinity is either Infinity or
374 * Inf, depending on the desired output string length.
375 * Printing of the sign follows the rules described
376 * above.</p>
377 *<p>
378 * If a floating point value is the internal
379 * representation for "not-a-number," the output is
380 * [+]NaN. Printing of the sign follows the rules
381 * described above.</p>
382 *<p>
383 * In no case does a non-existent or small field width
384 * cause truncation of a field; if the result of a
385 * conversion is wider than the field width, the field
386 * is simply expanded to contain the conversion result.
387 *</p>
388 *<p>
389 * The behavior is like printf. One exception is that
390 * the minimum number of exponent digits is 3 instead
391 * of 2 for e and E formats when the optional L is used
392 * before the e, E, g, or G conversion character. The
393 * optional L does not imply conversion to a long long
394 * double. </p>
395 * <p>
396 * The biggest divergence from the C printf
397 * specification is in the use of 16 bit characters.
398 * This allows the handling of characters beyond the
399 * small ASCII character set and allows the utility to
400 * interoperate correctly with the rest of the Java
401 * runtime environment.</p>
402 *<p>
403 * Omissions from the C printf specification are
404 * numerous. All the known omissions are present
405 * because Java never uses bytes to represent
406 * characters and does not have pointers:</p>
407 *<ul>
408 * <li>%c is the same as %C.
409 * <li>%s is the same as %S.
410 * <li>u, p, and n conversion characters.
411 * <li>%ws format.
412 * <li>h modifier applied to an n conversion character.
413 * <li>l (ell) modifier applied to the c, n, or s
414 * conversion characters.
415 * <li>ll (ell ell) modifier to d, i, o, u, x, or X
416 * conversion characters.
417 * <li>ll (ell ell) modifier to an n conversion
418 * character.
419 * <li>c, C, d,i,o,u,x, and X conversion characters
420 * apply to Byte, Character, Short, Integer, Long
421 * types.
422 * <li>f, e, E, g, and G conversion characters apply
423 * to Float and Double types.
424 * <li>s and S conversion characters apply to String
425 * types.
426 * <li>All other reference types can be formatted
427 * using the s or S conversion characters only.
428 *</ul>
429 * <p>
430 * Most of this specification is quoted from the Unix
431 * man page for the sprintf utility.</p>
432 *
433 * @author Allan Jacobs
434 * @version 1
435 * Release 1: Initial release.
436 * Release 2: Asterisk field widths and precisions
437 * %n$ and *m$
438 * Bug fixes
439 * g format fix (2 digits in e form corrupt)
440 * rounding in f format implemented
441 * round up when digit not printed is 5
442 * formatting of -0.0f
443 * round up/down when last digits are 50000...
444 */
445 public class PrintfFormat {
446 /**
447 * Constructs an array of control specifications
448 * possibly preceded, separated, or followed by
449 * ordinary strings. Control strings begin with
450 * unpaired percent signs. A pair of successive
451 * percent signs designates a single percent sign in
452 * the format.
453 * @param fmtArg Control string.
454 * @exception IllegalArgumentException if the control
455 * string is null, zero length, or otherwise
456 * malformed.
457 */
458 public PrintfFormat(String fmtArg)
459 throws IllegalArgumentException {
460 this(Locale.getDefault(),fmtArg);
461 }
462 /**
463 * Constructs an array of control specifications
464 * possibly preceded, separated, or followed by
465 * ordinary strings. Control strings begin with
466 * unpaired percent signs. A pair of successive
467 * percent signs designates a single percent sign in
468 * the format.
469 * @param fmtArg Control string.
470 * @exception IllegalArgumentException if the control
471 * string is null, zero length, or otherwise
472 * malformed.
473 */
474 public PrintfFormat(Locale locale,String fmtArg)
475 throws IllegalArgumentException {
476 dfs = new DecimalFormatSymbols(locale);
477 int ePos=0;
478 ConversionSpecification sFmt=null;
479 String unCS = this.nonControl(fmtArg,0);
480 if (unCS!=null) {
481 sFmt = new ConversionSpecification();
482 sFmt.setLiteral(unCS);
483 vFmt.addElement(sFmt);
484 }
485 while(cPos!=-1 && cPos<fmtArg.length()) {
486 for (ePos=cPos+1; ePos<fmtArg.length();
487 ePos++) {
488 char c=0;
489 c = fmtArg.charAt(ePos);
490 if (c == 'i') break;
491 if (c == 'd') break;
492 if (c == 'f') break;
493 if (c == 'g') break;
494 if (c == 'G') break;
495 if (c == 'o') break;
496 if (c == 'x') break;
497 if (c == 'X') break;
498 if (c == 'e') break;
499 if (c == 'E') break;
500 if (c == 'c') break;
501 if (c == 's') break;
502 if (c == '%') break;
503 }
504 ePos=Math.min(ePos+1,fmtArg.length());
505 sFmt = new ConversionSpecification(
506 fmtArg.substring(cPos,ePos));
507 vFmt.addElement(sFmt);
508 unCS = this.nonControl(fmtArg,ePos);
509 if (unCS!=null) {
510 sFmt = new ConversionSpecification();
511 sFmt.setLiteral(unCS);
512 vFmt.addElement(sFmt);
513 }
514 }
515 }
516 /**
517 * Return a substring starting at
518 * <code>start</code> and ending at either the end
519 * of the String <code>s</code>, the next unpaired
520 * percent sign, or at the end of the String if the
521 * last character is a percent sign.
522 * @param s Control string.
523 * @param start Position in the string
524 * <code>s</code> to begin looking for the start
525 * of a control string.
526 * @return the substring from the start position
527 * to the beginning of the control string.
528 */
529 private String nonControl(String s,int start) {
530 String ret="";
531 cPos=s.indexOf("%",start);
532 if (cPos==-1) cPos=s.length();
533 return s.substring(start,cPos);
534 }
535 /**
536 * Format an array of objects. Byte, Short,
537 * Integer, Long, Float, Double, and Character
538 * arguments are treated as wrappers for primitive
539 * types.
540 * @param o The array of objects to format.
541 * @return The formatted String.
542 */
543 public String sprintf(Object[] o) {
544 Enumeration e = vFmt.elements();
545 ConversionSpecification cs = null;
546 char c = 0;
547 int i=0;
548 StringBuffer sb=new StringBuffer();
549 while (e.hasMoreElements()) {
550 cs = (ConversionSpecification)
551 e.nextElement();
552 c = cs.getConversionCharacter();
553 if (c=='\0') sb.append(cs.getLiteral());
554 else if (c=='%') sb.append("%");
555 else {
556 if (cs.isPositionalSpecification()) {
557 i=cs.getArgumentPosition()-1;
558 if (cs.isPositionalFieldWidth()) {
559 int ifw=cs.getArgumentPositionForFieldWidth()-1;
560 cs.setFieldWidthWithArg(((Integer)o[ifw]).intValue());
561 }
562 if (cs.isPositionalPrecision()) {
563 int ipr=cs.getArgumentPositionForPrecision()-1;
564 cs.setPrecisionWithArg(((Integer)o[ipr]).intValue());
565 }
566 }
567 else {
568 if (cs.isVariableFieldWidth()) {
569 cs.setFieldWidthWithArg(((Integer)o[i]).intValue());
570 i++;
571 }
572 if (cs.isVariablePrecision()) {
573 cs.setPrecisionWithArg(((Integer)o[i]).intValue());
574 i++;
575 }
576 }
577 if (o[i] instanceof Byte)
578 sb.append(cs.internalsprintf(
579 ((Byte)o[i]).byteValue()));
580 else if (o[i] instanceof Short)
581 sb.append(cs.internalsprintf(
582 ((Short)o[i]).shortValue()));
583 else if (o[i] instanceof Integer)
584 sb.append(cs.internalsprintf(
585 ((Integer)o[i]).intValue()));
586 else if (o[i] instanceof Long)
587 sb.append(cs.internalsprintf(
588 ((Long)o[i]).longValue()));
589 else if (o[i] instanceof Float)
590 sb.append(cs.internalsprintf(
591 ((Float)o[i]).floatValue()));
592 else if (o[i] instanceof Double)
593 sb.append(cs.internalsprintf(
594 ((Double)o[i]).doubleValue()));
595 else if (o[i] instanceof Character)
596 sb.append(cs.internalsprintf(
597 ((Character)o[i]).charValue()));
598 else if (o[i] instanceof String)
599 sb.append(cs.internalsprintf(
600 (String)o[i]));
601 else
602 sb.append(cs.internalsprintf(
603 o[i]));
604 if (!cs.isPositionalSpecification())
605 i++;
606 }
607 }
608 return sb.toString();
609 }
610 /**
611 * Format nothing. Just use the control string.
612 * @return the formatted String.
613 */
614 public String sprintf() {
615 Enumeration e = vFmt.elements();
616 ConversionSpecification cs = null;
617 char c = 0;
618 StringBuffer sb=new StringBuffer();
619 while (e.hasMoreElements()) {
620 cs = (ConversionSpecification)
621 e.nextElement();
622 c = cs.getConversionCharacter();
623 if (c=='\0') sb.append(cs.getLiteral());
624 else if (c=='%') sb.append("%");
625 }
626 return sb.toString();
627 }
628 /**
629 * Format an int.
630 * @param x The int to format.
631 * @return The formatted String.
632 * @exception IllegalArgumentException if the
633 * conversion character is f, e, E, g, G, s,
634 * or S.
635 */
636 public String sprintf(int x)
637 throws IllegalArgumentException {
638 Enumeration e = vFmt.elements();
639 ConversionSpecification cs = null;
640 char c = 0;
641 StringBuffer sb=new StringBuffer();
642 while (e.hasMoreElements()) {
643 cs = (ConversionSpecification)
644 e.nextElement();
645 c = cs.getConversionCharacter();
646 if (c=='\0') sb.append(cs.getLiteral());
647 else if (c=='%') sb.append("%");
648 else sb.append(cs.internalsprintf(x));
649 }
650 return sb.toString();
651 }
652 /**
653 * Format an long.
654 * @param x The long to format.
655 * @return The formatted String.
656 * @exception IllegalArgumentException if the
657 * conversion character is f, e, E, g, G, s,
658 * or S.
659 */
660 public String sprintf(long x)
661 throws IllegalArgumentException {
662 Enumeration e = vFmt.elements();
663 ConversionSpecification cs = null;
664 char c = 0;
665 StringBuffer sb=new StringBuffer();
666 while (e.hasMoreElements()) {
667 cs = (ConversionSpecification)
668 e.nextElement();
669 c = cs.getConversionCharacter();
670 if (c=='\0') sb.append(cs.getLiteral());
671 else if (c=='%') sb.append("%");
672 else sb.append(cs.internalsprintf(x));
673 }
674 return sb.toString();
675 }
676 /**
677 * Format a double.
678 * @param x The double to format.
679 * @return The formatted String.
680 * @exception IllegalArgumentException if the
681 * conversion character is c, C, s, S,
682 * d, d, x, X, or o.
683 */
684 public String sprintf(double x)
685 throws IllegalArgumentException {
686 Enumeration e = vFmt.elements();
687 ConversionSpecification cs = null;
688 char c = 0;
689 StringBuffer sb=new StringBuffer();
690 while (e.hasMoreElements()) {
691 cs = (ConversionSpecification)
692 e.nextElement();
693 c = cs.getConversionCharacter();
694 if (c=='\0') sb.append(cs.getLiteral());
695 else if (c=='%') sb.append("%");
696 else sb.append(cs.internalsprintf(x));
697 }
698 return sb.toString();
699 }
700 /**
701 * Format a String.
702 * @param x The String to format.
703 * @return The formatted String.
704 * @exception IllegalArgumentException if the
705 * conversion character is neither s nor S.
706 */
707 public String sprintf(String x)
708 throws IllegalArgumentException {
709 Enumeration e = vFmt.elements();
710 ConversionSpecification cs = null;
711 char c = 0;
712 StringBuffer sb=new StringBuffer();
713 while (e.hasMoreElements()) {
714 cs = (ConversionSpecification)
715 e.nextElement();
716 c = cs.getConversionCharacter();
717 if (c=='\0') sb.append(cs.getLiteral());
718 else if (c=='%') sb.append("%");
719 else sb.append(cs.internalsprintf(x));
720 }
721 return sb.toString();
722 }
723 /**
724 * Format an Object. Convert wrapper types to
725 * their primitive equivalents and call the
726 * appropriate internal formatting method. Convert
727 * Strings using an internal formatting method for
728 * Strings. Otherwise use the default formatter
729 * (use toString).
730 * @param x the Object to format.
731 * @return the formatted String.
732 * @exception IllegalArgumentException if the
733 * conversion character is inappropriate for
734 * formatting an unwrapped value.
735 */
736 public String sprintf(Object x)
737 throws IllegalArgumentException {
738 Enumeration e = vFmt.elements();
739 ConversionSpecification cs = null;
740 char c = 0;
741 StringBuffer sb=new StringBuffer();
742 while (e.hasMoreElements()) {
743 cs = (ConversionSpecification)
744 e.nextElement();
745 c = cs.getConversionCharacter();
746 if (c=='\0') sb.append(cs.getLiteral());
747 else if (c=='%') sb.append("%");
748 else {
749 if (x instanceof Byte)
750 sb.append(cs.internalsprintf(
751 ((Byte)x).byteValue()));
752 else if (x instanceof Short)
753 sb.append(cs.internalsprintf(
754 ((Short)x).shortValue()));
755 else if (x instanceof Integer)
756 sb.append(cs.internalsprintf(
757 ((Integer)x).intValue()));
758 else if (x instanceof Long)
759 sb.append(cs.internalsprintf(
760 ((Long)x).longValue()));
761 else if (x instanceof Float)
762 sb.append(cs.internalsprintf(
763 ((Float)x).floatValue()));
764 else if (x instanceof Double)
765 sb.append(cs.internalsprintf(
766 ((Double)x).doubleValue()));
767 else if (x instanceof Character)
768 sb.append(cs.internalsprintf(
769 ((Character)x).charValue()));
770 else if (x instanceof String)
771 sb.append(cs.internalsprintf(
772 (String)x));
773 else
774 sb.append(cs.internalsprintf(x));
775 }
776 }
777 return sb.toString();
778 }
779 /**
780 *<p>
781 * ConversionSpecification allows the formatting of
782 * a single primitive or object embedded within a
783 * string. The formatting is controlled by a
784 * format string. Only one Java primitive or
785 * object can be formatted at a time.
786 *<p>
787 * A format string is a Java string that contains
788 * a control string. The control string starts at
789 * the first percent sign (%) in the string,
790 * provided that this percent sign
791 *<ol>
792 *<li>is not escaped protected by a matching % or
793 * is not an escape % character,
794 *<li>is not at the end of the format string, and
795 *<li>precedes a sequence of characters that parses
796 * as a valid control string.
797 *</ol>
798 *<p>
799 * A control string takes the form:
800 *<pre> % ['-+ #0]* [0..9]* { . [0..9]* }+
801 * { [hlL] }+ [idfgGoxXeEcs]
802 *</pre>
803 *<p>
804 * The behavior is like printf. One (hopefully the
805 * only) exception is that the minimum number of
806 * exponent digits is 3 instead of 2 for e and E
807 * formats when the optional L is used before the
808 * e, E, g, or G conversion character. The
809 * optional L does not imply conversion to a long
810 * long double.
811 */
812 private class ConversionSpecification {
813 /**
814 * Constructor. Used to prepare an instance
815 * to hold a literal, not a control string.
816 */
817 ConversionSpecification() { }
818 /**
819 * Constructor for a conversion specification.
820 * The argument must begin with a % and end
821 * with the conversion character for the
822 * conversion specification.
823 * @param fmtArg String specifying the
824 * conversion specification.
825 * @exception IllegalArgumentException if the
826 * input string is null, zero length, or
827 * otherwise malformed.
828 */
829 ConversionSpecification(String fmtArg)
830 throws IllegalArgumentException {
831 if (fmtArg==null)
832 throw new NullPointerException();
833 if (fmtArg.length()==0)
834 throw new IllegalArgumentException(
835 "Control strings must have positive"+
836 " lengths.");
837 if (fmtArg.charAt(0)=='%') {
838 fmt = fmtArg;
839 pos=1;
840 setArgPosition();
841 setFlagCharacters();
842 setFieldWidth();
843 setPrecision();
844 setOptionalHL();
845 if (setConversionCharacter()) {
846 if (pos==fmtArg.length()) {
847 if(leadingZeros&&leftJustify)
848 leadingZeros=false;
849 if(precisionSet&&leadingZeros){
850 if(conversionCharacter=='d'
851 ||conversionCharacter=='i'
852 ||conversionCharacter=='o'
853 ||conversionCharacter=='x')
854 {
855 leadingZeros=false;
856 }
857 }
858 }
859 else
860 throw new IllegalArgumentException(
861 "Malformed conversion specification="+
862 fmtArg);
863 }
864 else
865 throw new IllegalArgumentException(
866 "Malformed conversion specification="+
867 fmtArg);
868 }
869 else
870 throw new IllegalArgumentException(
871 "Control strings must begin with %.");
872 }
873 /**
874 * Set the String for this instance.
875 * @param s the String to store.
876 */
877 void setLiteral(String s) {
878 fmt = s;
879 }
880 /**
881 * Get the String for this instance. Translate
882 * any escape sequences.
883 *
884 * @return s the stored String.
885 */
886 String getLiteral() {
887 StringBuffer sb=new StringBuffer();
888 int i=0;
889 while (i<fmt.length()) {
890 if (fmt.charAt(i)=='\\') {
891 i++;
892 if (i<fmt.length()) {
893 char c=fmt.charAt(i);
894 switch(c) {
895 case 'a':
896 sb.append((char)0x07);
897 break;
898 case 'b':
899 sb.append('\b');
900 break;
901 case 'f':
902 sb.append('\f');
903 break;
904 case 'n':
905 sb.append(System.getProperty("line.separator"));
906 break;
907 case 'r':
908 sb.append('\r');
909 break;
910 case 't':
911 sb.append('\t');
912 break;
913 case 'v':
914 sb.append((char)0x0b);
915 break;
916 case '\\':
917 sb.append('\\');
918 break;
919 }
920 i++;
921 }
922 else
923 sb.append('\\');
924 }
925 else
926 i++;
927 }
928 return fmt;
929 }
930 /**
931 * Get the conversion character that tells what
932 * type of control character this instance has.
933 *
934 * @return the conversion character.
935 */
936 char getConversionCharacter() {
937 return conversionCharacter;
938 }
939 /**
940 * Check whether the specifier has a variable
941 * field width that is going to be set by an
942 * argument.
943 * @return <code>true</code> if the conversion
944 * uses an * field width; otherwise
945 * <code>false</code>.
946 */
947 boolean isVariableFieldWidth() {
948 return variableFieldWidth;
949 }
950 /**
951 * Set the field width with an argument. A
952 * negative field width is taken as a - flag
953 * followed by a positive field width.
954 * @param fw the field width.
955 */
956 void setFieldWidthWithArg(int fw) {
957 if (fw<0) leftJustify = true;
958 fieldWidthSet = true;
959 fieldWidth = Math.abs(fw);
960 }
961 /**
962 * Check whether the specifier has a variable
963 * precision that is going to be set by an
964 * argument.
965 * @return <code>true</code> if the conversion
966 * uses an * precision; otherwise
967 * <code>false</code>.
968 */
969 boolean isVariablePrecision() {
970 return variablePrecision;
971 }
972 /**
973 * Set the precision with an argument. A
974 * negative precision will be changed to zero.
975 * @param pr the precision.
976 */
977 void setPrecisionWithArg(int pr) {
978 precisionSet = true;
979 precision = Math.max(pr,0);
980 }
981 /**
982 * Format an int argument using this conversion
983 * specification.
984 * @param s the int to format.
985 * @return the formatted String.
986 * @exception IllegalArgumentException if the
987 * conversion character is f, e, E, g, or G.
988 */
989 String internalsprintf(int s)
990 throws IllegalArgumentException {
991 String s2 = "";
992 switch(conversionCharacter) {
993 case 'd':
994 case 'i':
995 if (optionalh)
996 s2 = printDFormat((short)s);
997 else if (optionall)
998 s2 = printDFormat((long)s);
999 else
1000 s2 = printDFormat(s);
1001 break;
1002 case 'x':
1003 case 'X':
1004 if (optionalh)
1005 s2 = printXFormat((short)s);
1006 else if (optionall)
1007 s2 = printXFormat((long)s);
1008 else
1009 s2 = printXFormat(s);
1010 break;
1011 case 'o':
1012 if (optionalh)
1013 s2 = printOFormat((short)s);
1014 else if (optionall)
1015 s2 = printOFormat((long)s);
1016 else
1017 s2 = printOFormat(s);
1018 break;
1019 case 'c':
1020 case 'C':
1021 s2 = printCFormat((char)s);
1022 break;
1023 default:
1024 throw new IllegalArgumentException(
1025 "Cannot format a int with a format using a "+
1026 conversionCharacter+
1027 " conversion character.");
1028 }
1029 return s2;
1030 }
1031 /**
1032 * Format a long argument using this conversion
1033 * specification.
1034 * @param s the long to format.
1035 * @return the formatted String.
1036 * @exception IllegalArgumentException if the
1037 * conversion character is f, e, E, g, or G.
1038 */
1039 String internalsprintf(long s)
1040 throws IllegalArgumentException {
1041 String s2 = "";
1042 switch(conversionCharacter) {
1043 case 'd':
1044 case 'i':
1045 if (optionalh)
1046 s2 = printDFormat((short)s);
1047 else if (optionall)
1048 s2 = printDFormat(s);
1049 else
1050 s2 = printDFormat((int)s);
1051 break;
1052 case 'x':
1053 case 'X':
1054 if (optionalh)
1055 s2 = printXFormat((short)s);
1056 else if (optionall)
1057 s2 = printXFormat(s);
1058 else
1059 s2 = printXFormat((int)s);
1060 break;
1061 case 'o':
1062 if (optionalh)
1063 s2 = printOFormat((short)s);
1064 else if (optionall)
1065 s2 = printOFormat(s);
1066 else
1067 s2 = printOFormat((int)s);
1068 break;
1069 case 'c':
1070 case 'C':
1071 s2 = printCFormat((char)s);
1072 break;
1073 default:
1074 throw new IllegalArgumentException(
1075 "Cannot format a long with a format using a "+
1076 conversionCharacter+" conversion character.");
1077 }
1078 return s2;
1079 }
1080 /**
1081 * Format a double argument using this conversion
1082 * specification.
1083 * @param s the double to format.
1084 * @return the formatted String.
1085 * @exception IllegalArgumentException if the
1086 * conversion character is c, C, s, S, i, d,
1087 * x, X, or o.
1088 */
1089 String internalsprintf(double s)
1090 throws IllegalArgumentException {
1091 String s2 = "";
1092 switch(conversionCharacter) {
1093 case 'f':
1094 s2 = printFFormat(s);
1095 break;
1096 case 'E':
1097 case 'e':
1098 s2 = printEFormat(s);
1099 break;
1100 case 'G':
1101 case 'g':
1102 s2 = printGFormat(s);
1103 break;
1104 default:
1105 throw new IllegalArgumentException("Cannot "+
1106 "format a double with a format using a "+
1107 conversionCharacter+" conversion character.");
1108 }
1109 return s2;
1110 }
1111 /**
1112 * Format a String argument using this conversion
1113 * specification.
1114 * @param s the String to format.
1115 * @return the formatted String.
1116 * @exception IllegalArgumentException if the
1117 * conversion character is neither s nor S.
1118 */
1119 String internalsprintf(String s)
1120 throws IllegalArgumentException {
1121 String s2 = "";
1122 if(conversionCharacter=='s'
1123 || conversionCharacter=='S')
1124 s2 = printSFormat(s);
1125 else
1126 throw new IllegalArgumentException("Cannot "+
1127 "format a String with a format using a "+
1128 conversionCharacter+" conversion character.");
1129 return s2;
1130 }
1131 /**
1132 * Format an Object argument using this conversion
1133 * specification.
1134 * @param s the Object to format.
1135 * @return the formatted String.
1136 * @exception IllegalArgumentException if the
1137 * conversion character is neither s nor S.
1138 */
1139 String internalsprintf(Object s) {
1140 String s2 = "";
1141 if(conversionCharacter=='s'
1142 || conversionCharacter=='S')
1143 s2 = printSFormat(s.toString());
1144 else
1145 throw new IllegalArgumentException(
1146 "Cannot format a String with a format using"+
1147 " a "+conversionCharacter+
1148 " conversion character.");
1149 return s2;
1150 }
1151 /**
1152 * For f format, the flag character '-', means that
1153 * the output should be left justified within the
1154 * field. The default is to pad with blanks on the
1155 * left. '+' character means that the conversion
1156 * will always begin with a sign (+ or -). The
1157 * blank flag character means that a non-negative
1158 * input will be preceded with a blank. If both
1159 * a '+' and a ' ' are specified, the blank flag
1160 * is ignored. The '0' flag character implies that
1161 * padding to the field width will be done with
1162 * zeros instead of blanks.
1163 *
1164 * The field width is treated as the minimum number
1165 * of characters to be printed. The default is to
1166 * add no padding. Padding is with blanks by
1167 * default.
1168 *
1169 * The precision, if set, is the number of digits
1170 * to appear after the radix character. Padding is
1171 * with trailing 0s.
1172 */
1173 private char[] fFormatDigits(double x) {
1174 // int defaultDigits=6;
1175 String sx,sxOut;
1176 int i,j,k;
1177 int n1In,n2In;
1178 int expon=0;
1179 boolean minusSign=false;
1180 if (x>0.0)
1181 sx = Double.toString(x);
1182 else if (x<0.0) {
1183 sx = Double.toString(-x);
1184 minusSign=true;
1185 }
1186 else {
1187 sx = Double.toString(x);
1188 if (sx.charAt(0)=='-') {
1189 minusSign=true;
1190 sx=sx.substring(1);
1191 }
1192 }
1193 int ePos = sx.indexOf('E');
1194 int rPos = sx.indexOf('.');
1195 if (rPos!=-1) n1In=rPos;
1196 else if (ePos!=-1) n1In=ePos;
1197 else n1In=sx.length();
1198 if (rPos!=-1) {
1199 if (ePos!=-1) n2In = ePos-rPos-1;
1200 else n2In = sx.length()-rPos-1;
1201 }
1202 else
1203 n2In = 0;
1204 if (ePos!=-1) {
1205 int ie=ePos+1;
1206 expon=0;
1207 if (sx.charAt(ie)=='-') {
1208 for (++ie; ie<sx.length(); ie++)
1209 if (sx.charAt(ie)!='0') break;
1210 if (ie<sx.length())
1211 expon=-Integer.parseInt(sx.substring(ie));
1212 }
1213 else {
1214 if (sx.charAt(ie)=='+') ++ie;
1215 for (; ie<sx.length(); ie++)
1216 if (sx.charAt(ie)!='0') break;
1217 if (ie<sx.length())
1218 expon=Integer.parseInt(sx.substring(ie));
1219 }
1220 }
1221 int p;
1222 if (precisionSet) p = precision;
1223 else p = defaultDigits-1;
1224 char[] ca1 = sx.toCharArray();
1225 char[] ca2 = new char[n1In+n2In];
1226 char[] ca3,ca4,ca5;
1227 for (j=0; j<n1In; j++)
1228 ca2[j] = ca1[j];
1229 i = j+1;
1230 for (k=0; k<n2In; j++,i++,k++)
1231 ca2[j] = ca1[i];
1232 if (n1In+expon<=0) {
1233 ca3 = new char[-expon+n2In];
1234 for (j=0,k=0; k<(-n1In-expon); k++,j++)
1235 ca3[j]='0';
1236 for (i=0; i<(n1In+n2In); i++,j++)
1237 ca3[j]=ca2[i];
1238 }
1239 else
1240 ca3 = ca2;
1241 boolean carry=false;
1242 if (p<-expon+n2In) {
1243 if (expon<0) i = p;
1244 else i = p+n1In;
1245 carry=checkForCarry(ca3,i);
1246 if (carry)
1247 carry=startSymbolicCarry(ca3,i-1,0);
1248 }
1249 if (n1In+expon<=0) {
1250 ca4 = new char[2+p];
1251 if (!carry) ca4[0]='0';
1252 else ca4[0]='1';
1253 if(alternateForm||!precisionSet||precision!=0){
1254 ca4[1]='.';
1255 for(i=0,j=2;i<Math.min(p,ca3.length);i++,j++)
1256 ca4[j]=ca3[i];
1257 for (; j<ca4.length; j++) ca4[j]='0';
1258 }
1259 }
1260 else {
1261 if (!carry) {
1262 if(alternateForm||!precisionSet
1263 ||precision!=0)
1264 ca4 = new char[n1In+expon+p+1];
1265 else
1266 ca4 = new char[n1In+expon];
1267 j=0;
1268 }
1269 else {
1270 if(alternateForm||!precisionSet
1271 ||precision!=0)
1272 ca4 = new char[n1In+expon+p+2];
1273 else
1274 ca4 = new char[n1In+expon+1];
1275 ca4[0]='1';
1276 j=1;
1277 }
1278 for (i=0; i<Math.min(n1In+expon,ca3.length); i++,j++)
1279 ca4[j]=ca3[i];
1280 for (; i<n1In+expon; i++,j++)
1281 ca4[j]='0';
1282 if(alternateForm||!precisionSet||precision!=0){
1283 ca4[j]='.'; j++;
1284 for (k=0; i<ca3.length && k<p; i++,j++,k++)
1285 ca4[j]=ca3[i];
1286 for (; j<ca4.length; j++) ca4[j]='0';
1287 }
1288 }
1289 int nZeros=0;
1290 if (!leftJustify && leadingZeros) {
1291 int xThousands=0;
1292 if (thousands) {
1293 int xlead=0;
1294 if (ca4[0]=='+'||ca4[0]=='-'||ca4[0]==' ')
1295 xlead=1;
1296 int xdp=xlead;
1297 for (; xdp<ca4.length; xdp++)
1298 if (ca4[xdp]=='.') break;
1299 xThousands=(xdp-xlead)/3;
1300 }
1301 if (fieldWidthSet)
1302 nZeros = fieldWidth-ca4.length;
1303 if ((!minusSign&&(leadingSign||leadingSpace))||minusSign)
1304 nZeros--;
1305 nZeros-=xThousands;
1306 if (nZeros<0) nZeros=0;
1307 }
1308 j=0;
1309 if ((!minusSign&&(leadingSign||leadingSpace))||minusSign) {
1310 ca5 = new char[ca4.length+nZeros+1];
1311 j++;
1312 }
1313 else
1314 ca5 = new char[ca4.length+nZeros];
1315 if (!minusSign) {
1316 if (leadingSign) ca5[0]='+';
1317 if (leadingSpace) ca5[0]=' ';
1318 }
1319 else
1320 ca5[0]='-';
1321 for (i=0; i<nZeros; i++,j++)
1322 ca5[j]='0';
1323 for (i=0; i<ca4.length; i++,j++) ca5[j]=ca4[i];
1324
1325 int lead=0;
1326 if (ca5[0]=='+'||ca5[0]=='-'||ca5[0]==' ')
1327 lead=1;
1328 int dp=lead;
1329 for (; dp<ca5.length; dp++)
1330 if (ca5[dp]=='.') break;
1331 int nThousands=(dp-lead)/3;
1332 // Localize the decimal point.
1333 if (dp<ca5.length)
1334 ca5[dp]=dfs.getDecimalSeparator();
1335 char[] ca6 = ca5;
1336 if (thousands && nThousands>0) {
1337 ca6 = new char[ca5.length+nThousands+lead];
1338 ca6[0]=ca5[0];
1339 for (i=lead,k=lead; i<dp; i++) {
1340 if (i>0 && (dp-i)%3==0) {
1341 // ca6[k]=',';
1342 ca6[k]=dfs.getGroupingSeparator();
1343 ca6[k+1]=ca5[i];
1344 k+=2;
1345 }
1346 else {
1347 ca6[k]=ca5[i]; k++;
1348 }
1349 }
1350 for (; i<ca5.length; i++,k++) {
1351 ca6[k]=ca5[i];
1352 }
1353 }
1354 return ca6;
1355 }
1356 /**
1357 * An intermediate routine on the way to creating
1358 * an f format String. The method decides whether
1359 * the input double value is an infinity,
1360 * not-a-number, or a finite double and formats
1361 * each type of input appropriately.
1362 * @param x the double value to be formatted.
1363 * @return the converted double value.
1364 */
1365 private String fFormatString(double x) {
1366 boolean noDigits=false;
1367 char[] ca6,ca7;
1368 if (Double.isInfinite(x)) {
1369 if (x==Double.POSITIVE_INFINITY) {
1370 if (leadingSign) ca6 = "+Inf".toCharArray();
1371 else if (leadingSpace)
1372 ca6 = " Inf".toCharArray();
1373 else ca6 = "Inf".toCharArray();
1374 }
1375 else
1376 ca6 = "-Inf".toCharArray();
1377 noDigits = true;
1378 }
1379 else if (Double.isNaN(x)) {
1380 if (leadingSign) ca6 = "+NaN".toCharArray();
1381 else if (leadingSpace)
1382 ca6 = " NaN".toCharArray();
1383 else ca6 = "NaN".toCharArray();
1384 noDigits = true;
1385 }
1386 else
1387 ca6 = fFormatDigits(x);
1388 ca7 = applyFloatPadding(ca6,false);
1389 return new String(ca7);
1390 }
1391 /**
1392 * For e format, the flag character '-', means that
1393 * the output should be left justified within the
1394 * field. The default is to pad with blanks on the
1395 * left. '+' character means that the conversion
1396 * will always begin with a sign (+ or -). The
1397 * blank flag character means that a non-negative
1398 * input will be preceded with a blank. If both a
1399 * '+' and a ' ' are specified, the blank flag is
1400 * ignored. The '0' flag character implies that
1401 * padding to the field width will be done with
1402 * zeros instead of blanks.
1403 *
1404 * The field width is treated as the minimum number
1405 * of characters to be printed. The default is to
1406 * add no padding. Padding is with blanks by
1407 * default.
1408 *
1409 * The precision, if set, is the minimum number of
1410 * digits to appear after the radix character.
1411 * Padding is with trailing 0s.
1412 *
1413 * The behavior is like printf. One (hopefully the
1414 * only) exception is that the minimum number of
1415 * exponent digits is 3 instead of 2 for e and E
1416 * formats when the optional L is used before the
1417 * e, E, g, or G conversion character. The optional
1418 * L does not imply conversion to a long long
1419 * double.
1420 */
1421 private char[] eFormatDigits(double x,char eChar) {
1422 char[] ca1,ca2,ca3;
1423 // int defaultDigits=6;
1424 String sx,sxOut;
1425 int i,j,k,p;
1426 int n1In,n2In;
1427 int expon=0;
1428 int ePos,rPos,eSize;
1429 boolean minusSign=false;
1430 if (x>0.0)
1431 sx = Double.toString(x);
1432 else if (x<0.0) {
1433 sx = Double.toString(-x);
1434 minusSign=true;
1435 }
1436 else {
1437 sx = Double.toString(x);
1438 if (sx.charAt(0)=='-') {
1439 minusSign=true;
1440 sx=sx.substring(1);
1441 }
1442 }
1443 ePos = sx.indexOf('E');
1444 if (ePos==-1) ePos = sx.indexOf('e');
1445 rPos = sx.indexOf('.');
1446 if (rPos!=-1) n1In=rPos;
1447 else if (ePos!=-1) n1In=ePos;
1448 else n1In=sx.length();
1449 if (rPos!=-1) {
1450 if (ePos!=-1) n2In = ePos-rPos-1;
1451 else n2In = sx.length()-rPos-1;
1452 }
1453 else
1454 n2In = 0;
1455 if (ePos!=-1) {
1456 int ie=ePos+1;
1457 expon=0;
1458 if (sx.charAt(ie)=='-') {
1459 for (++ie; ie<sx.length(); ie++)
1460 if (sx.charAt(ie)!='0') break;
1461 if (ie<sx.length())
1462 expon=-Integer.parseInt(sx.substring(ie));
1463 }
1464 else {
1465 if (sx.charAt(ie)=='+') ++ie;
1466 for (; ie<sx.length(); ie++)
1467 if (sx.charAt(ie)!='0') break;
1468 if (ie<sx.length())
1469 expon=Integer.parseInt(sx.substring(ie));
1470 }
1471 }
1472 if (rPos!=-1) expon += rPos-1;
1473 if (precisionSet) p = precision;
1474 else p = defaultDigits-1;
1475 if (rPos!=-1 && ePos!=-1)
1476 ca1=(sx.substring(0,rPos)+
1477 sx.substring(rPos+1,ePos)).toCharArray();
1478 else if (rPos!=-1)
1479 ca1 = (sx.substring(0,rPos)+
1480 sx.substring(rPos+1)).toCharArray();
1481 else if (ePos!=-1)
1482 ca1 = sx.substring(0,ePos).toCharArray();
1483 else
1484 ca1 = sx.toCharArray();
1485 boolean carry=false;
1486 int i0=0;
1487 if (ca1[0]!='0')
1488 i0 = 0;
1489 else
1490 for (i0=0; i0<ca1.length; i0++)
1491 if (ca1[i0]!='0') break;
1492 if (i0+p<ca1.length-1) {
1493 carry=checkForCarry(ca1,i0+p+1);
1494 if (carry)
1495 carry = startSymbolicCarry(ca1,i0+p,i0);
1496 if (carry) {
1497 ca2 = new char[i0+p+1];
1498 ca2[i0]='1';
1499 for (j=0; j<i0; j++) ca2[j]='0';
1500 for (i=i0,j=i0+1; j<p+1; i++,j++)
1501 ca2[j] = ca1[i];
1502 expon++;
1503 ca1 = ca2;
1504 }
1505 }
1506 if (Math.abs(expon)<100 && !optionalL) eSize=4;
1507 else eSize=5;
1508 if (alternateForm||!precisionSet||precision!=0)
1509 ca2 = new char[2+p+eSize];
1510 else
1511 ca2 = new char[1+eSize];
1512 if (ca1[0]!='0') {
1513 ca2[0] = ca1[0];
1514 j=1;
1515 }
1516 else {
1517 for (j=1; j<(ePos==-1?ca1.length:ePos); j++)
1518 if (ca1[j]!='0') break;
1519 if ((ePos!=-1 && j<ePos)||
1520 (ePos==-1 && j<ca1.length)) {
1521 ca2[0] = ca1[j];
1522 expon -= j;
1523 j++;
1524 }
1525 else {
1526 ca2[0]='0';
1527 j=2;
1528 }
1529 }
1530 if (alternateForm||!precisionSet||precision!=0) {
1531 ca2[1] = '.';
1532 i=2;
1533 }
1534 else
1535 i=1;
1536 for (k=0; k<p && j<ca1.length; j++,i++,k++)
1537 ca2[i] = ca1[j];
1538 for (;i<ca2.length-eSize; i++)
1539 ca2[i] = '0';
1540 ca2[i++] = eChar;
1541 if (expon<0) ca2[i++]='-';
1542 else ca2[i++]='+';
1543 expon = Math.abs(expon);
1544 if (expon>=100) {
1545 switch(expon/100) {
1546 case 1: ca2[i]='1'; break;
1547 case 2: ca2[i]='2'; break;
1548 case 3: ca2[i]='3'; break;
1549 case 4: ca2[i]='4'; break;
1550 case 5: ca2[i]='5'; break;
1551 case 6: ca2[i]='6'; break;
1552 case 7: ca2[i]='7'; break;
1553 case 8: ca2[i]='8'; break;
1554 case 9: ca2[i]='9'; break;
1555 }
1556 i++;
1557 }
1558 switch((expon%100)/10) {
1559 case 0: ca2[i]='0'; break;
1560 case 1: ca2[i]='1'; break;
1561 case 2: ca2[i]='2'; break;
1562 case 3: ca2[i]='3'; break;
1563 case 4: ca2[i]='4'; break;
1564 case 5: ca2[i]='5'; break;
1565 case 6: ca2[i]='6'; break;
1566 case 7: ca2[i]='7'; break;
1567 case 8: ca2[i]='8'; break;
1568 case 9: ca2[i]='9'; break;
1569 }
1570 i++;
1571 switch(expon%10) {
1572 case 0: ca2[i]='0'; break;
1573 case 1: ca2[i]='1'; break;
1574 case 2: ca2[i]='2'; break;
1575 case 3: ca2[i]='3'; break;
1576 case 4: ca2[i]='4'; break;
1577 case 5: ca2[i]='5'; break;
1578 case 6: ca2[i]='6'; break;
1579 case 7: ca2[i]='7'; break;
1580 case 8: ca2[i]='8'; break;
1581 case 9: ca2[i]='9'; break;
1582 }
1583 int nZeros=0;
1584 if (!leftJustify && leadingZeros) {
1585 int xThousands=0;
1586 if (thousands) {
1587 int xlead=0;
1588 if (ca2[0]=='+'||ca2[0]=='-'||ca2[0]==' ')
1589 xlead=1;
1590 int xdp=xlead;
1591 for (; xdp<ca2.length; xdp++)
1592 if (ca2[xdp]=='.') break;
1593 xThousands=(xdp-xlead)/3;
1594 }
1595 if (fieldWidthSet)
1596 nZeros = fieldWidth-ca2.length;
1597 if ((!minusSign&&(leadingSign||leadingSpace))||minusSign)
1598 nZeros--;
1599 nZeros-=xThousands;
1600 if (nZeros<0) nZeros=0;
1601 }
1602 j=0;
1603 if ((!minusSign&&(leadingSign || leadingSpace))||minusSign) {
1604 ca3 = new char[ca2.length+nZeros+1];
1605 j++;
1606 }
1607 else
1608 ca3 = new char[ca2.length+nZeros];
1609 if (!minusSign) {
1610 if (leadingSign) ca3[0]='+';
1611 if (leadingSpace) ca3[0]=' ';
1612 }
1613 else
1614 ca3[0]='-';
1615 for (k=0; k<nZeros; j++,k++)
1616 ca3[j]='0';
1617 for (i=0; i<ca2.length && j<ca3.length; i++,j++)
1618 ca3[j]=ca2[i];
1619
1620 int lead=0;
1621 if (ca3[0]=='+'||ca3[0]=='-'||ca3[0]==' ')
1622 lead=1;
1623 int dp=lead;
1624 for (; dp<ca3.length; dp++)
1625 if (ca3[dp]=='.') break;
1626 int nThousands=dp/3;
1627 // Localize the decimal point.
1628 if (dp < ca3.length)
1629 ca3[dp] = dfs.getDecimalSeparator();
1630 char[] ca4 = ca3;
1631 if (thousands && nThousands>0) {
1632 ca4 = new char[ca3.length+nThousands+lead];
1633 ca4[0]=ca3[0];
1634 for (i=lead,k=lead; i<dp; i++) {
1635 if (i>0 && (dp-i)%3==0) {
1636 // ca4[k]=',';
1637 ca4[k]=dfs.getGroupingSeparator();
1638 ca4[k+1]=ca3[i];
1639 k+=2;
1640 }
1641 else {
1642 ca4[k]=ca3[i]; k++;
1643 }
1644 }
1645 for (; i<ca3.length; i++,k++)
1646 ca4[k]=ca3[i];
1647 }
1648 return ca4;
1649 }
1650 /**
1651 * Check to see if the digits that are going to
1652 * be truncated because of the precision should
1653 * force a round in the preceding digits.
1654 * @param ca1 the array of digits
1655 * @param icarry the index of the first digit that
1656 * is to be truncated from the print
1657 * @return <code>true</code> if the truncation forces
1658 * a round that will change the print
1659 */
1660 private boolean checkForCarry(char[] ca1,int icarry) {
1661 boolean carry=false;
1662 if (icarry<ca1.length) {
1663 if (ca1[icarry]=='6'||ca1[icarry]=='7'
1664 ||ca1[icarry]=='8'||ca1[icarry]=='9') carry=true;
1665 else if (ca1[icarry]=='5') {
1666 int ii=icarry+1;
1667 for (;ii<ca1.length; ii++)
1668 if (ca1[ii]!='0') break;
1669 carry=ii<ca1.length;
1670 if (!carry&&icarry>0) {
1671 carry=(ca1[icarry-1]=='1'||ca1[icarry-1]=='3'
1672 ||ca1[icarry-1]=='5'||ca1[icarry-1]=='7'
1673 ||ca1[icarry-1]=='9');
1674 }
1675 }
1676 }
1677 return carry;
1678 }
1679 /**
1680 * Start the symbolic carry process. The process
1681 * is not quite finished because the symbolic
1682 * carry may change the length of the string and
1683 * change the exponent (in e format).
1684 * @param cLast index of the last digit changed
1685 * by the round
1686 * @param cFirst index of the first digit allowed
1687 * to be changed by this phase of the round
1688 * @return <code>true</code> if the carry forces
1689 * a round that will change the print still
1690 * more
1691 */
1692 private boolean startSymbolicCarry(
1693 char[] ca,int cLast,int cFirst) {
1694 boolean carry=true;
1695 for (int i=cLast; carry && i>=cFirst; i--) {
1696 carry = false;
1697 switch(ca[i]) {
1698 case '0': ca[i]='1'; break;
1699 case '1': ca[i]='2'; break;
1700 case '2': ca[i]='3'; break;
1701 case '3': ca[i]='4'; break;
1702 case '4': ca[i]='5'; break;
1703 case '5': ca[i]='6'; break;
1704 case '6': ca[i]='7'; break;
1705 case '7': ca[i]='8'; break;
1706 case '8': ca[i]='9'; break;
1707 case '9': ca[i]='0'; carry=true; break;
1708 }
1709 }
1710 return carry;
1711 }
1712 /**
1713 * An intermediate routine on the way to creating
1714 * an e format String. The method decides whether
1715 * the input double value is an infinity,
1716 * not-a-number, or a finite double and formats
1717 * each type of input appropriately.
1718 * @param x the double value to be formatted.
1719 * @param eChar an 'e' or 'E' to use in the
1720 * converted double value.
1721 * @return the converted double value.
1722 */
1723 private String eFormatString(double x,char eChar) {
1724 boolean noDigits=false;
1725 char[] ca4,ca5;
1726 if (Double.isInfinite(x)) {
1727 if (x==Double.POSITIVE_INFINITY) {
1728 if (leadingSign) ca4 = "+Inf".toCharArray();
1729 else if (leadingSpace)
1730 ca4 = " Inf".toCharArray();
1731 else ca4 = "Inf".toCharArray();
1732 }
1733 else
1734 ca4 = "-Inf".toCharArray();
1735 noDigits = true;
1736 }
1737 else if (Double.isNaN(x)) {
1738 if (leadingSign) ca4 = "+NaN".toCharArray();
1739 else if (leadingSpace)
1740 ca4 = " NaN".toCharArray();
1741 else ca4 = "NaN".toCharArray();
1742 noDigits = true;
1743 }
1744 else
1745 ca4 = eFormatDigits(x,eChar);
1746 ca5 = applyFloatPadding(ca4,false);
1747 return new String(ca5);
1748 }
1749 /**
1750 * Apply zero or blank, left or right padding.
1751 * @param ca4 array of characters before padding is
1752 * finished
1753 * @param noDigits NaN or signed Inf
1754 * @return a padded array of characters
1755 */
1756 private char[] applyFloatPadding(
1757 char[] ca4,boolean noDigits) {
1758 char[] ca5 = ca4;
1759 if (fieldWidthSet) {
1760 int i,j,nBlanks;
1761 if (leftJustify) {
1762 nBlanks = fieldWidth-ca4.length;
1763 if (nBlanks > 0) {
1764 ca5 = new char[ca4.length+nBlanks];
1765 for (i=0; i<ca4.length; i++)
1766 ca5[i] = ca4[i];
1767 for (j=0; j<nBlanks; j++,i++)
1768 ca5[i] = ' ';
1769 }
1770 }
1771 else if (!leadingZeros || noDigits) {
1772 nBlanks = fieldWidth-ca4.length;
1773 if (nBlanks > 0) {
1774 ca5 = new char[ca4.length+nBlanks];
1775 for (i=0; i<nBlanks; i++)
1776 ca5[i] = ' ';
1777 for (j=0; j<ca4.length; i++,j++)
1778 ca5[i] = ca4[j];
1779 }
1780 }
1781 else if (leadingZeros) {
1782 nBlanks = fieldWidth-ca4.length;
1783 if (nBlanks > 0) {
1784 ca5 = new char[ca4.length+nBlanks];
1785 i=0; j=0;
1786 if (ca4[0]=='-') { ca5[0]='-'; i++; j++; }
1787 for (int k=0; k<nBlanks; i++,k++)
1788 ca5[i] = '0';
1789 for (; j<ca4.length; i++,j++)
1790 ca5[i] = ca4[j];
1791 }
1792 }
1793 }
1794 return ca5;
1795 }
1796 /**
1797 * Format method for the f conversion character.
1798 * @param x the double to format.
1799 * @return the formatted String.
1800 */
1801 private String printFFormat(double x) {
1802 return fFormatString(x);
1803 }
1804 /**
1805 * Format method for the e or E conversion
1806 * character.
1807 * @param x the double to format.
1808 * @return the formatted String.
1809 */
1810 private String printEFormat(double x) {
1811 if (conversionCharacter=='e')
1812 return eFormatString(x,'e');
1813 else
1814 return eFormatString(x,'E');
1815 }
1816 /**
1817 * Format method for the g conversion character.
1818 *
1819 * For g format, the flag character '-', means that
1820 * the output should be left justified within the
1821 * field. The default is to pad with blanks on the
1822 * left. '+' character means that the conversion
1823 * will always begin with a sign (+ or -). The
1824 * blank flag character means that a non-negative
1825 * input will be preceded with a blank. If both a
1826 * '+' and a ' ' are specified, the blank flag is
1827 * ignored. The '0' flag character implies that
1828 * padding to the field width will be done with
1829 * zeros instead of blanks.
1830 *
1831 * The field width is treated as the minimum number
1832 * of characters to be printed. The default is to
1833 * add no padding. Padding is with blanks by
1834 * default.
1835 *
1836 * The precision, if set, is the minimum number of
1837 * digits to appear after the radix character.
1838 * Padding is with trailing 0s.
1839 * @param x the double to format.
1840 * @return the formatted String.
1841 */
1842 private String printGFormat(double x) {
1843 String sx,sy,sz,ret;
1844 int savePrecision=precision;
1845 int i;
1846 char[] ca4,ca5;
1847 boolean noDigits=false;
1848 if (Double.isInfinite(x)) {
1849 if (x==Double.POSITIVE_INFINITY) {
1850 if (leadingSign) ca4 = "+Inf".toCharArray();
1851 else if (leadingSpace)
1852 ca4 = " Inf".toCharArray();
1853 else ca4 = "Inf".toCharArray();
1854 }
1855 else
1856 ca4 = "-Inf".toCharArray();
1857 noDigits = true;
1858 }
1859 else if (Double.isNaN(x)) {
1860 if (leadingSign) ca4 = "+NaN".toCharArray();
1861 else if (leadingSpace)
1862 ca4 = " NaN".toCharArray();
1863 else ca4 = "NaN".toCharArray();
1864 noDigits = true;
1865 }
1866 else {
1867 if (!precisionSet) precision=defaultDigits;
1868 if (precision==0) precision=1;
1869 int ePos=-1;
1870 if (conversionCharacter=='g') {
1871 sx = eFormatString(x,'e').trim();
1872 ePos=sx.indexOf('e');
1873 }
1874 else {
1875 sx = eFormatString(x,'E').trim();
1876 ePos=sx.indexOf('E');
1877 }
1878 i=ePos+1;
1879 int expon=0;
1880 if (sx.charAt(i)=='-') {
1881 for (++i; i<sx.length(); i++)
1882 if (sx.charAt(i)!='0') break;
1883 if (i<sx.length())
1884 expon=-Integer.parseInt(sx.substring(i));
1885 }
1886 else {
1887 if (sx.charAt(i)=='+') ++i;
1888 for (; i<sx.length(); i++)
1889 if (sx.charAt(i)!='0') break;
1890 if (i<sx.length())
1891 expon=Integer.parseInt(sx.substring(i));
1892 }
1893 // Trim trailing zeros.
1894 // If the radix character is not followed by
1895 // a digit, trim it, too.
1896 if (!alternateForm) {
1897 if (expon>=-4 && expon<precision)
1898 sy = fFormatString(x).trim();
1899 else
1900 sy = sx.substring(0,ePos);
1901 i=sy.length()-1;
1902 for (; i>=0; i--)
1903 if (sy.charAt(i)!='0') break;
1904 if (i>=0 && sy.charAt(i)=='.') i--;
1905 if (i==-1) sz="0";
1906 else if (!Character.isDigit(sy.charAt(i)))
1907 sz=sy.substring(0,i+1)+"0";
1908 else sz=sy.substring(0,i+1);
1909 if (expon>=-4 && expon<precision)
1910 ret=sz;
1911 else
1912 ret=sz+sx.substring(ePos);
1913 }
1914 else {
1915 if (expon>=-4 && expon<precision)
1916 ret = fFormatString(x).trim();
1917 else
1918 ret = sx;
1919 }
1920 // leading space was trimmed off during
1921 // construction
1922 if (leadingSpace) if (x>=0) ret = " "+ret;
1923 ca4 = ret.toCharArray();
1924 }
1925 // Pad with blanks or zeros.
1926 ca5 = applyFloatPadding(ca4,false);
1927 precision=savePrecision;
1928 return new String(ca5);
1929 }
1930 /**
1931 * Format method for the d conversion specifer and
1932 * short argument.
1933 *
1934 * For d format, the flag character '-', means that
1935 * the output should be left justified within the
1936 * field. The default is to pad with blanks on the
1937 * left. A '+' character means that the conversion
1938 * will always begin with a sign (+ or -). The
1939 * blank flag character means that a non-negative
1940 * input will be preceded with a blank. If both a
1941 * '+' and a ' ' are specified, the blank flag is
1942 * ignored. The '0' flag character implies that
1943 * padding to the field width will be done with
1944 * zeros instead of blanks.
1945 *
1946 * The field width is treated as the minimum number
1947 * of characters to be printed. The default is to
1948 * add no padding. Padding is with blanks by
1949 * default.
1950 *
1951 * The precision, if set, is the minimum number of
1952 * digits to appear. Padding is with leading 0s.
1953 * @param x the short to format.
1954 * @return the formatted String.
1955 */
1956 private String printDFormat(short x) {
1957 return printDFormat(Short.toString(x));
1958 }
1959 /**
1960 * Format method for the d conversion character and
1961 * long argument.
1962 *
1963 * For d format, the flag character '-', means that
1964 * the output should be left justified within the
1965 * field. The default is to pad with blanks on the
1966 * left. A '+' character means that the conversion
1967 * will always begin with a sign (+ or -). The
1968 * blank flag character means that a non-negative
1969 * input will be preceded with a blank. If both a
1970 * '+' and a ' ' are specified, the blank flag is
1971 * ignored. The '0' flag character implies that
1972 * padding to the field width will be done with
1973 * zeros instead of blanks.
1974 *
1975 * The field width is treated as the minimum number
1976 * of characters to be printed. The default is to
1977 * add no padding. Padding is with blanks by
1978 * default.
1979 *
1980 * The precision, if set, is the minimum number of
1981 * digits to appear. Padding is with leading 0s.
1982 * @param x the long to format.
1983 * @return the formatted String.
1984 */
1985 private String printDFormat(long x) {
1986 return printDFormat(Long.toString(x));
1987 }
1988 /**
1989 * Format method for the d conversion character and
1990 * int argument.
1991 *
1992 * For d format, the flag character '-', means that
1993 * the output should be left justified within the
1994 * field. The default is to pad with blanks on the
1995 * left. A '+' character means that the conversion
1996 * will always begin with a sign (+ or -). The
1997 * blank flag character means that a non-negative
1998 * input will be preceded with a blank. If both a
1999 * '+' and a ' ' are specified, the blank flag is
2000 * ignored. The '0' flag character implies that
2001 * padding to the field width will be done with
2002 * zeros instead of blanks.
2003 *
2004 * The field width is treated as the minimum number
2005 * of characters to be printed. The default is to
2006 * add no padding. Padding is with blanks by
2007 * default.
2008 *
2009 * The precision, if set, is the minimum number of
2010 * digits to appear. Padding is with leading 0s.
2011 * @param x the int to format.
2012 * @return the formatted String.
2013 */
2014 private String printDFormat(int x) {
2015 return printDFormat(Integer.toString(x));
2016 }
2017 /**
2018 * Utility method for formatting using the d
2019 * conversion character.
2020 * @param sx the String to format, the result of
2021 * converting a short, int, or long to a
2022 * String.
2023 * @return the formatted String.
2024 */
2025 private String printDFormat(String sx) {
2026 int nLeadingZeros=0;
2027 int nBlanks=0,n=0;
2028 int i=0,jFirst=0;
2029 boolean neg = sx.charAt(0)=='-';
2030 if (sx.equals("0")&&precisionSet&&precision==0)
2031 sx="";
2032 if (!neg) {
2033 if (precisionSet && sx.length() < precision)
2034 nLeadingZeros = precision-sx.length();
2035 }
2036 else {
2037 if (precisionSet&&(sx.length()-1)<precision)
2038 nLeadingZeros = precision-sx.length()+1;
2039 }
2040 if (nLeadingZeros<0) nLeadingZeros=0;
2041 if (fieldWidthSet) {
2042 nBlanks = fieldWidth-nLeadingZeros-sx.length();
2043 if (!neg&&(leadingSign||leadingSpace))
2044 nBlanks--;
2045 }
2046 if (nBlanks<0) nBlanks=0;
2047 if (leadingSign) n++;
2048 else if (leadingSpace) n++;
2049 n += nBlanks;
2050 n += nLeadingZeros;
2051 n += sx.length();
2052 char[] ca = new char[n];
2053 if (leftJustify) {
2054 if (neg) ca[i++] = '-';
2055 else if (leadingSign) ca[i++] = '+';
2056 else if (leadingSpace) ca[i++] = ' ';
2057 char[] csx = sx.toCharArray();
2058 jFirst = neg?1:0;
2059 for (int j=0; j<nLeadingZeros; i++,j++)
2060 ca[i]='0';
2061 for (int j=jFirst; j<csx.length; j++,i++)
2062 ca[i] = csx[j];
2063 for (int j=0; j<nBlanks; i++,j++)
2064 ca[i] = ' ';
2065 }
2066 else {
2067 if (!leadingZeros) {
2068 for (i=0; i<nBlanks; i++)
2069 ca[i] = ' ';
2070 if (neg) ca[i++] = '-';
2071 else if (leadingSign) ca[i++] = '+';
2072 else if (leadingSpace) ca[i++] = ' ';
2073 }
2074 else {
2075 if (neg) ca[i++] = '-';
2076 else if (leadingSign) ca[i++] = '+';
2077 else if (leadingSpace) ca[i++] = ' ';
2078 for (int j=0; j<nBlanks; j++,i++)
2079 ca[i] = '0';
2080 }
2081 for (int j=0; j<nLeadingZeros; j++,i++)
2082 ca[i] = '0';
2083 char[] csx = sx.toCharArray();
2084 jFirst = neg?1:0;
2085 for (int j=jFirst; j<csx.length; j++,i++)
2086 ca[i] = csx[j];
2087 }
2088 return new String(ca);
2089 }
2090 /**
2091 * Format method for the x conversion character and
2092 * short argument.
2093 *
2094 * For x format, the flag character '-', means that
2095 * the output should be left justified within the
2096 * field. The default is to pad with blanks on the
2097 * left. The '#' flag character means to lead with
2098 * '0x'.
2099 *
2100 * The field width is treated as the minimum number
2101 * of characters to be printed. The default is to
2102 * add no padding. Padding is with blanks by
2103 * default.
2104 *
2105 * The precision, if set, is the minimum number of
2106 * digits to appear. Padding is with leading 0s.
2107 * @param x the short to format.
2108 * @return the formatted String.
2109 */
2110 private String printXFormat(short x) {
2111 String sx=null;
2112 if (x == Short.MIN_VALUE)
2113 sx = "8000";
2114 else if (x < 0) {
2115 String t;
2116 if (x==Short.MIN_VALUE)
2117 t = "0";
2118 else {
2119 t = Integer.toString(
2120 (~(-x-1))^Short.MIN_VALUE,16);
2121 if (t.charAt(0)=='F'||t.charAt(0)=='f')
2122 t = t.substring(16,32);
2123 }
2124 switch (t.length()) {
2125 case 1:
2126 sx = "800"+t;
2127 break;
2128 case 2:
2129 sx = "80"+t;
2130 break;
2131 case 3:
2132 sx = "8"+t;
2133 break;
2134 case 4:
2135 switch (t.charAt(0)) {
2136 case '1':
2137 sx = "9"+t.substring(1,4);
2138 break;
2139 case '2':
2140 sx = "a"+t.substring(1,4);
2141 break;
2142 case '3':
2143 sx = "b"+t.substring(1,4);
2144 break;
2145 case '4':
2146 sx = "c"+t.substring(1,4);
2147 break;
2148 case '5':
2149 sx = "d"+t.substring(1,4);
2150 break;
2151 case '6':
2152 sx = "e"+t.substring(1,4);
2153 break;
2154 case '7':
2155 sx = "f"+t.substring(1,4);
2156 break;
2157 }
2158 break;
2159 }
2160 }
2161 else
2162 sx = Integer.toString((int)x,16);
2163 return printXFormat(sx);
2164 }
2165 /**
2166 * Format method for the x conversion character and
2167 * long argument.
2168 *
2169 * For x format, the flag character '-', means that
2170 * the output should be left justified within the
2171 * field. The default is to pad with blanks on the
2172 * left. The '#' flag character means to lead with
2173 * '0x'.
2174 *
2175 * The field width is treated as the minimum number
2176 * of characters to be printed. The default is to
2177 * add no padding. Padding is with blanks by
2178 * default.
2179 *
2180 * The precision, if set, is the minimum number of
2181 * digits to appear. Padding is with leading 0s.
2182 * @param x the long to format.
2183 * @return the formatted String.
2184 */
2185 private String printXFormat(long x) {
2186 String sx=null;
2187 if (x == Long.MIN_VALUE)
2188 sx = "8000000000000000";
2189 else if (x < 0) {
2190 String t = Long.toString(
2191 (~(-x-1))^Long.MIN_VALUE,16);
2192 switch (t.length()) {
2193 case 1:
2194 sx = "800000000000000"+t;
2195 break;
2196 case 2:
2197 sx = "80000000000000"+t;
2198 break;
2199 case 3:
2200 sx = "8000000000000"+t;
2201 break;
2202 case 4:
2203 sx = "800000000000"+t;
2204 break;
2205 case 5:
2206 sx = "80000000000"+t;
2207 break;
2208 case 6:
2209 sx = "8000000000"+t;
2210 break;
2211 case 7:
2212 sx = "800000000"+t;
2213 break;
2214 case 8:
2215 sx = "80000000"+t;
2216 break;
2217 case 9:
2218 sx = "8000000"+t;
2219 break;
2220 case 10:
2221 sx = "800000"+t;
2222 break;
2223 case 11:
2224 sx = "80000"+t;
2225 break;
2226 case 12:
2227 sx = "8000"+t;
2228 break;
2229 case 13:
2230 sx = "800"+t;
2231 break;
2232 case 14:
2233 sx = "80"+t;
2234 break;
2235 case 15:
2236 sx = "8"+t;
2237 break;
2238 case 16:
2239 switch (t.charAt(0)) {
2240 case '1':
2241 sx = "9"+t.substring(1,16);
2242 break;
2243 case '2':
2244 sx = "a"+t.substring(1,16);
2245 break;
2246 case '3':
2247 sx = "b"+t.substring(1,16);
2248 break;
2249 case '4':
2250 sx = "c"+t.substring(1,16);
2251 break;
2252 case '5':
2253 sx = "d"+t.substring(1,16);
2254 break;
2255 case '6':
2256 sx = "e"+t.substring(1,16);
2257 break;
2258 case '7':
2259 sx = "f"+t.substring(1,16);
2260 break;
2261 }
2262 break;
2263 }
2264 }
2265 else
2266 sx = Long.toString(x,16);
2267 return printXFormat(sx);
2268 }
2269 /**
2270 * Format method for the x conversion character and
2271 * int argument.
2272 *
2273 * For x format, the flag character '-', means that
2274 * the output should be left justified within the
2275 * field. The default is to pad with blanks on the
2276 * left. The '#' flag character means to lead with
2277 * '0x'.
2278 *
2279 * The field width is treated as the minimum number
2280 * of characters to be printed. The default is to
2281 * add no padding. Padding is with blanks by
2282 * default.
2283 *
2284 * The precision, if set, is the minimum number of
2285 * digits to appear. Padding is with leading 0s.
2286 * @param x the int to format.
2287 * @return the formatted String.
2288 */
2289 private String printXFormat(int x) {
2290 String sx=null;
2291 if (x == Integer.MIN_VALUE)
2292 sx = "80000000";
2293 else if (x < 0) {
2294 String t = Integer.toString(
2295 (~(-x-1))^Integer.MIN_VALUE,16);
2296 switch (t.length()) {
2297 case 1:
2298 sx = "8000000"+t;
2299 break;
2300 case 2:
2301 sx = "800000"+t;
2302 break;
2303 case 3:
2304 sx = "80000"+t;
2305 break;
2306 case 4:
2307 sx = "8000"+t;
2308 break;
2309 case 5:
2310 sx = "800"+t;
2311 break;
2312 case 6:
2313 sx = "80"+t;
2314 break;
2315 case 7:
2316 sx = "8"+t;
2317 break;
2318 case 8:
2319 switch (t.charAt(0)) {
2320 case '1':
2321 sx = "9"+t.substring(1,8);
2322 break;
2323 case '2':
2324 sx = "a"+t.substring(1,8);
2325 break;
2326 case '3':
2327 sx = "b"+t.substring(1,8);
2328 break;
2329 case '4':
2330 sx = "c"+t.substring(1,8);
2331 break;
2332 case '5':
2333 sx = "d"+t.substring(1,8);
2334 break;
2335 case '6':
2336 sx = "e"+t.substring(1,8);
2337 break;
2338 case '7':
2339 sx = "f"+t.substring(1,8);
2340 break;
2341 }
2342 break;
2343 }
2344 }
2345 else
2346 sx = Integer.toString(x,16);
2347 return printXFormat(sx);
2348 }
2349 /**
2350 * Utility method for formatting using the x
2351 * conversion character.
2352 * @param sx the String to format, the result of
2353 * converting a short, int, or long to a
2354 * String.
2355 * @return the formatted String.
2356 */
2357 private String printXFormat(String sx) {
2358 int nLeadingZeros = 0;
2359 int nBlanks = 0;
2360 if (sx.equals("0")&&precisionSet&&precision==0)
2361 sx="";
2362 if (precisionSet)
2363 nLeadingZeros = precision-sx.length();
2364 if (nLeadingZeros<0) nLeadingZeros=0;
2365 if (fieldWidthSet) {
2366 nBlanks = fieldWidth-nLeadingZeros-sx.length();
2367 if (alternateForm) nBlanks = nBlanks - 2;
2368 }
2369 if (nBlanks<0) nBlanks=0;
2370 int n=0;
2371 if (alternateForm) n+=2;
2372 n += nLeadingZeros;
2373 n += sx.length();
2374 n += nBlanks;
2375 char[] ca = new char[n];
2376 int i=0;
2377 if (leftJustify) {
2378 if (alternateForm) {
2379 ca[i++]='0'; ca[i++]='x';
2380 }
2381 for (int j=0; j<nLeadingZeros; j++,i++)
2382 ca[i]='0';
2383 char[] csx = sx.toCharArray();
2384 for (int j=0; j<csx.length; j++,i++)
2385 ca[i] = csx[j];
2386 for (int j=0; j<nBlanks; j++,i++)
2387 ca[i] = ' ';
2388 }
2389 else {
2390 if (!leadingZeros)
2391 for (int j=0; j<nBlanks; j++,i++)
2392 ca[i] = ' ';
2393 if (alternateForm) {
2394 ca[i++]='0'; ca[i++]='x';
2395 }
2396 if (leadingZeros)
2397 for (int j=0; j<nBlanks; j++,i++)
2398 ca[i] = '0';
2399 for (int j=0; j<nLeadingZeros; j++,i++)
2400 ca[i]='0';
2401 char[] csx = sx.toCharArray();
2402 for (int j=0; j<csx.length; j++,i++)
2403 ca[i] = csx[j];
2404 }
2405 String caReturn=new String(ca);
2406 if (conversionCharacter=='X')
2407 caReturn = caReturn.toUpperCase();
2408 return caReturn;
2409 }
2410 /**
2411 * Format method for the o conversion character and
2412 * short argument.
2413 *
2414 * For o format, the flag character '-', means that
2415 * the output should be left justified within the
2416 * field. The default is to pad with blanks on the
2417 * left. The '#' flag character means that the
2418 * output begins with a leading 0 and the precision
2419 * is increased by 1.
2420 *
2421 * The field width is treated as the minimum number
2422 * of characters to be printed. The default is to
2423 * add no padding. Padding is with blanks by
2424 * default.
2425 *
2426 * The precision, if set, is the minimum number of
2427 * digits to appear. Padding is with leading 0s.
2428 * @param x the short to format.
2429 * @return the formatted String.
2430 */
2431 private String printOFormat(short x) {
2432 String sx=null;
2433 if (x == Short.MIN_VALUE)
2434 sx = "100000";
2435 else if (x < 0) {
2436 String t = Integer.toString(
2437 (~(-x-1))^Short.MIN_VALUE,8);
2438 switch (t.length()) {
2439 case 1:
2440 sx = "10000"+t;
2441 break;
2442 case 2:
2443 sx = "1000"+t;
2444 break;
2445 case 3:
2446 sx = "100"+t;
2447 break;
2448 case 4:
2449 sx = "10"+t;
2450 break;
2451 case 5:
2452 sx = "1"+t;
2453 break;
2454 }
2455 }
2456 else
2457 sx = Integer.toString((int)x,8);
2458 return printOFormat(sx);
2459 }
2460 /**
2461 * Format method for the o conversion character and
2462 * long argument.
2463 *
2464 * For o format, the flag character '-', means that
2465 * the output should be left justified within the
2466 * field. The default is to pad with blanks on the
2467 * left. The '#' flag character means that the
2468 * output begins with a leading 0 and the precision
2469 * is increased by 1.
2470 *
2471 * The field width is treated as the minimum number
2472 * of characters to be printed. The default is to
2473 * add no padding. Padding is with blanks by
2474 * default.
2475 *
2476 * The precision, if set, is the minimum number of
2477 * digits to appear. Padding is with leading 0s.
2478 * @param x the long to format.
2479 * @return the formatted String.
2480 */
2481 private String printOFormat(long x) {
2482 String sx=null;
2483 if (x == Long.MIN_VALUE)
2484 sx = "1000000000000000000000";
2485 else if (x < 0) {
2486 String t = Long.toString(
2487 (~(-x-1))^Long.MIN_VALUE,8);
2488 switch (t.length()) {
2489 case 1:
2490 sx = "100000000000000000000"+t;
2491 break;
2492 case 2:
2493 sx = "10000000000000000000"+t;
2494 break;
2495 case 3:
2496 sx = "1000000000000000000"+t;
2497 break;
2498 case 4:
2499 sx = "100000000000000000"+t;
2500 break;
2501 case 5:
2502 sx = "10000000000000000"+t;
2503 break;
2504 case 6:
2505 sx = "1000000000000000"+t;
2506 break;
2507 case 7:
2508 sx = "100000000000000"+t;
2509 break;
2510 case 8:
2511 sx = "10000000000000"+t;
2512 break;
2513 case 9:
2514 sx = "1000000000000"+t;
2515 break;
2516 case 10:
2517 sx = "100000000000"+t;
2518 break;
2519 case 11:
2520 sx = "10000000000"+t;
2521 break;
2522 case 12:
2523 sx = "1000000000"+t;
2524 break;
2525 case 13:
2526 sx = "100000000"+t;
2527 break;
2528 case 14:
2529 sx = "10000000"+t;
2530 break;
2531 case 15:
2532 sx = "1000000"+t;
2533 break;
2534 case 16:
2535 sx = "100000"+t;
2536 break;
2537 case 17:
2538 sx = "10000"+t;
2539 break;
2540 case 18:
2541 sx = "1000"+t;
2542 break;
2543 case 19:
2544 sx = "100"+t;
2545 break;
2546 case 20:
2547 sx = "10"+t;
2548 break;
2549 case 21:
2550 sx = "1"+t;
2551 break;
2552 }
2553 }
2554 else
2555 sx = Long.toString(x,8);
2556 return printOFormat(sx);
2557 }
2558 /**
2559 * Format method for the o conversion character and
2560 * int argument.
2561 *
2562 * For o format, the flag character '-', means that
2563 * the output should be left justified within the
2564 * field. The default is to pad with blanks on the
2565 * left. The '#' flag character means that the
2566 * output begins with a leading 0 and the precision
2567 * is increased by 1.
2568 *
2569 * The field width is treated as the minimum number
2570 * of characters to be printed. The default is to
2571 * add no padding. Padding is with blanks by
2572 * default.
2573 *
2574 * The precision, if set, is the minimum number of
2575 * digits to appear. Padding is with leading 0s.
2576 * @param x the int to format.
2577 * @return the formatted String.
2578 */
2579 private String printOFormat(int x) {
2580 String sx=null;
2581 if (x == Integer.MIN_VALUE)
2582 sx = "20000000000";
2583 else if (x < 0) {
2584 String t = Integer.toString(
2585 (~(-x-1))^Integer.MIN_VALUE,8);
2586 switch (t.length()) {
2587 case 1:
2588 sx = "2000000000"+t;
2589 break;
2590 case 2:
2591 sx = "200000000"+t;
2592 break;
2593 case 3:
2594 sx = "20000000"+t;
2595 break;
2596 case 4:
2597 sx = "2000000"+t;
2598 break;
2599 case 5:
2600 sx = "200000"+t;
2601 break;
2602 case 6:
2603 sx = "20000"+t;
2604 break;
2605 case 7:
2606 sx = "2000"+t;
2607 break;
2608 case 8:
2609 sx = "200"+t;
2610 break;
2611 case 9:
2612 sx = "20"+t;
2613 break;
2614 case 10:
2615 sx = "2"+t;
2616 break;
2617 case 11:
2618 sx = "3"+t.substring(1);
2619 break;
2620 }
2621 }
2622 else
2623 sx = Integer.toString(x,8);
2624 return printOFormat(sx);
2625 }
2626 /**
2627 * Utility method for formatting using the o
2628 * conversion character.
2629 * @param sx the String to format, the result of
2630 * converting a short, int, or long to a
2631 * String.
2632 * @return the formatted String.
2633 */
2634 private String printOFormat(String sx) {
2635 int nLeadingZeros = 0;
2636 int nBlanks = 0;
2637 if (sx.equals("0")&&precisionSet&&precision==0)
2638 sx="";
2639 if (precisionSet)
2640 nLeadingZeros = precision-sx.length();
2641 if (alternateForm) nLeadingZeros++;
2642 if (nLeadingZeros<0) nLeadingZeros=0;
2643 if (fieldWidthSet)
2644 nBlanks = fieldWidth-nLeadingZeros-sx.length();
2645 if (nBlanks<0) nBlanks=0;
2646 int n=nLeadingZeros+sx.length()+nBlanks;
2647 char[] ca = new char[n];
2648 int i;
2649 if (leftJustify) {
2650 for (i=0; i<nLeadingZeros; i++) ca[i]='0';
2651 char[] csx = sx.toCharArray();
2652 for (int j=0; j<csx.length; j++,i++)
2653 ca[i] = csx[j];
2654 for (int j=0; j<nBlanks; j++,i++) ca[i] = ' ';
2655 }
2656 else {
2657 if (leadingZeros)
2658 for (i=0; i<nBlanks; i++) ca[i]='0';
2659 else
2660 for (i=0; i<nBlanks; i++) ca[i]=' ';
2661 for (int j=0; j<nLeadingZeros; j++,i++)
2662 ca[i]='0';
2663 char[] csx = sx.toCharArray();
2664 for (int j=0; j<csx.length; j++,i++)
2665 ca[i] = csx[j];
2666 }
2667 return new String(ca);
2668 }
2669 /**
2670 * Format method for the c conversion character and
2671 * char argument.
2672 *
2673 * The only flag character that affects c format is
2674 * the '-', meaning that the output should be left
2675 * justified within the field. The default is to
2676 * pad with blanks on the left.
2677 *
2678 * The field width is treated as the minimum number
2679 * of characters to be printed. Padding is with
2680 * blanks by default. The default width is 1.