Source code: org/xmud/util/PrintfFormat.java
1 package org.xmud.util;
2 //
3 // (c) 2000 Sun Microsystems, Inc.
4 // ALL RIGHTS RESERVED
5 //
6 // License Grant-
7 //
8 //
9 // Permission to use, copy, modify, and distribute this Software and its
10 // documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee is
11 // hereby granted.
12 //
13 // This Software is provided "AS IS". All express warranties, including any
14 // implied warranty of merchantability, satisfactory quality, fitness for a
15 // particular purpose, or non-infringement, are disclaimed, except to the extent
16 // that such disclaimers are held to be legally invalid.
17 //
18 // You acknowledge that Software is not designed, licensed or intended for use in
19 // the design, construction, operation or maintenance of any nuclear facility
20 // ("High Risk Activities"). Sun disclaims any express or implied warranty of
21 // fitness for such uses.
22 //
23 // Please refer to the file http://www.sun.com/policies/trademarks/ for further
24 // important trademark information and to
25 // http://java.sun.com/nav/business/index.html for further important licensing
26 // information for the Java Technology.
27 //
28
29
30 import java.util.Enumeration;
31 import java.util.Vector;
32 import java.util.Locale;
33 import java.text.DecimalFormatSymbols;
34
35 /**
36 * PrintfFormat allows the formatting of an array of
37 * objects embedded within a string. Primitive types
38 * must be passed using wrapper types. The formatting
39 * is controlled by a control string.
40 *<p>
41 * A control string is a Java string that contains a
42 * control specification. The control specification
43 * starts at the first percent sign (%) in the string,
44 * provided that this percent sign
45 *<ol>
46 *<li>is not escaped protected by a matching % or is
47 * not an escape % character,
48 *<li>is not at the end of the format string, and
49 *<li>precedes a sequence of characters that parses as
50 * a valid control specification.
51 *</ol>
52 *</p><p>
53 * A control specification usually takes the form:
54 *<pre> % ['-+ #0]* [0..9]* { . [0..9]* }+
55 * { [hlL] }+ [idfgGoxXeEcs]
56 *</pre>
57 * There are variants of this basic form that are
58 * discussed below.</p>
59 *<p>
60 * The format is composed of zero or more directives
61 * defined as follows:
62 *<ul>
63 *<li>ordinary characters, which are simply copied to
64 * the output stream;
65 *<li>escape sequences, which represent non-graphic
66 * characters; and
67 *<li>conversion specifications, each of which
68 * results in the fetching of zero or more arguments.
69 *</ul></p>
70 *<p>
71 * The results are undefined if there are insufficient
72 * arguments for the format. Usually an unchecked
73 * exception will be thrown. If the format is
74 * exhausted while arguments remain, the excess
75 * arguments are evaluated but are otherwise ignored.
76 * In format strings containing the % form of
77 * conversion specifications, each argument in the
78 * argument list is used exactly once.</p>
79 * <p>
80 * Conversions can be applied to the <code>n</code>th
81 * argument after the format in the argument list,
82 * rather than to the next unused argument. In this
83 * case, the conversion characer % is replaced by the
84 * sequence %<code>n</code>$, where <code>n</code> is
85 * a decimal integer giving the position of the
86 * argument in the argument list.</p>
87 * <p>
88 * In format strings containing the %<code>n</code>$
89 * form of conversion specifications, each argument
90 * in the argument list is used exactly once.</p>
91 *
92 *<h4>Escape Sequences</h4>
93 *<p>
94 * The following table lists escape sequences and
95 * associated actions on display devices capable of
96 * the action.
97 *<table>
98 *<tr><th align=left>Sequence</th>
99 * <th align=left>Name</th>
100 * <th align=left>Description</th></tr>
101 *<tr><td>\\</td><td>backlash</td><td>None.
102 *</td></tr>
103 *<tr><td>\a</td><td>alert</td><td>Attempts to alert
104 * the user through audible or visible
105 * notification.
106 *</td></tr>
107 *<tr><td>\b</td><td>backspace</td><td>Moves the
108 * printing position to one column before
109 * the current position, unless the
110 * current position is the start of a line.
111 *</td></tr>
112 *<tr><td>\f</td><td>form-feed</td><td>Moves the
113 * printing position to the initial
114 * printing position of the next logical
115 * page.
116 *</td></tr>
117 *<tr><td>\n</td><td>newline</td><td>Moves the
118 * printing position to the start of the
119 * next line.
120 *</td></tr>
121 *<tr><td>\r</td><td>carriage-return</td><td>Moves
122 * the printing position to the start of
123 * the current line.
124 *</td></tr>
125 *<tr><td>\t</td><td>tab</td><td>Moves the printing
126 * position to the next implementation-
127 * defined horizontal tab position.
128 *</td></tr>
129 *<tr><td>\v</td><td>vertical-tab</td><td>Moves the
130 * printing position to the start of the
131 * next implementation-defined vertical
132 * tab position.
133 *</td></tr>
134 *</table></p>
135 *<h4>Conversion Specifications</h4>
136 *<p>
137 * Each conversion specification is introduced by
138 * the percent sign character (%). After the character
139 * %, the following appear in sequence:</p>
140 *<p>
141 * Zero or more flags (in any order), which modify the
142 * meaning of the conversion specification.</p>
143 *<p>
144 * An optional minimum field width. If the converted
145 * value has fewer characters than the field width, it
146 * will be padded with spaces by default on the left;
147 * t will be padded on the right, if the left-
148 * adjustment flag (-), described below, is given to
149 * the field width. The field width takes the form
150 * of a decimal integer. If the conversion character
151 * is s, the field width is the the minimum number of
152 * characters to be printed.</p>
153 *<p>
154 * An optional precision that gives the minumum number
155 * of digits to appear for the d, i, o, x or X
156 * conversions (the field is padded with leading
157 * zeros); the number of digits to appear after the
158 * radix character for the e, E, and f conversions,
159 * the maximum number of significant digits for the g
160 * and G conversions; or the maximum number of
161 * characters to be written from a string is s and S
162 * conversions. The precision takes the form of an
163 * optional decimal digit string, where a null digit
164 * string is treated as 0. If a precision appears
165 * with a c conversion character the precision is
166 * ignored.
167 * </p>
168 *<p>
169 * An optional h specifies that a following d, i, o,
170 * x, or X conversion character applies to a type
171 * short argument (the argument will be promoted
172 * according to the integral promotions and its value
173 * converted to type short before printing).</p>
174 *<p>
175 * An optional l (ell) specifies that a following
176 * d, i, o, x, or X conversion character applies to a
177 * type long argument.</p>
178 *<p>
179 * A field width or precision may be indicated by an
180 * asterisk (*) instead of a digit string. In this
181 * case, an integer argument supplised the field width
182 * precision. The argument that is actually converted
183 * is not fetched until the conversion letter is seen,
184 * so the the arguments specifying field width or
185 * precision must appear before the argument (if any)
186 * to be converted. If the precision argument is
187 * negative, it will be changed to zero. A negative
188 * field width argument is taken as a - flag, followed
189 * by a positive field width.</p>
190 * <p>
191 * In format strings containing the %<code>n</code>$
192 * form of a conversion specification, a field width
193 * or precision may be indicated by the sequence
194 * *<code>m</code>$, where m is a decimal integer
195 * giving the position in the argument list (after the
196 * format argument) of an integer argument containing
197 * the field width or precision.</p>
198 * <p>
199 * The format can contain either numbered argument
200 * specifications (that is, %<code>n</code>$ and
201 * *<code>m</code>$), or unnumbered argument
202 * specifications (that is % and *), but normally not
203 * both. The only exception to this is that %% can
204 * be mixed with the %<code>n</code>$ form. The
205 * results of mixing numbered and unnumbered argument
206 * specifications in a format string are undefined.</p>
207 *
208 *<h4>Flag Characters</h4>
209 *<p>
210 * The flags and their meanings are:</p>
211 *<dl>
212 * <dt>'<dd> integer portion of the result of a
213 * decimal conversion (%i, %d, %f, %g, or %G) will
214 * be formatted with thousands' grouping
215 * characters. For other conversions the flag
216 * is ignored. The non-monetary grouping
217 * character is used.
218 * <dt>-<dd> result of the conversion is left-justified
219 * within the field. (It will be right-justified
220 * if this flag is not specified).</td></tr>
221 * <dt>+<dd> result of a signed conversion always
222 * begins with a sign (+ or -). (It will begin
223 * with a sign only when a negative value is
224 * converted if this flag is not specified.)
225 * <dt><space><dd> If the first character of a
226 * signed conversion is not a sign, a space
227 * character will be placed before the result.
228 * This means that if the space character and +
229 * flags both appear, the space flag will be
230 * ignored.
231 * <dt>#<dd> value is to be converted to an alternative
232 * form. For c, d, i, and s conversions, the flag
233 * has no effect. For o conversion, it increases
234 * the precision to force the first digit of the
235 * result to be a zero. For x or X conversion, a
236 * non-zero result has 0x or 0X prefixed to it,
237 * respectively. For e, E, f, g, and G
238 * conversions, the result always contains a radix
239 * character, even if no digits follow the radix
240 * character (normally, a decimal point appears in
241 * the result of these conversions only if a digit
242 * follows it). For g and G conversions, trailing
243 * zeros will not be removed from the result as
244 * they normally are.
245 * <dt>0<dd> d, i, o, x, X, e, E, f, g, and G
246 * conversions, leading zeros (following any
247 * indication of sign or base) are used to pad to
248 * the field width; no space padding is
249 * performed. If the 0 and - flags both appear,
250 * the 0 flag is ignored. For d, i, o, x, and X
251 * conversions, if a precision is specified, the
252 * 0 flag will be ignored. For c conversions,
253 * the flag is ignored.
254 *</dl>
255 *
256 *<h4>Conversion Characters</h4>
257 *<p>
258 * Each conversion character results in fetching zero
259 * or more arguments. The results are undefined if
260 * there are insufficient arguments for the format.
261 * Usually, an unchecked exception will be thrown.
262 * If the format is exhausted while arguments remain,
263 * the excess arguments are ignored.</p>
264 *
265 *<p>
266 * The conversion characters and their meanings are:
267 *</p>
268 *<dl>
269 * <dt>d,i<dd>The int argument is converted to a
270 * signed decimal in the style [-]dddd. The
271 * precision specifies the minimum number of
272 * digits to appear; if the value being
273 * converted can be represented in fewer
274 * digits, it will be expanded with leading
275 * zeros. The default precision is 1. The
276 * result of converting 0 with an explicit
277 * precision of 0 is no characters.
278 * <dt>o<dd> The int argument is converted to unsigned
279 * octal format in the style ddddd. The
280 * precision specifies the minimum number of
281 * digits to appear; if the value being
282 * converted can be represented in fewer
283 * digits, it will be expanded with leading
284 * zeros. The default precision is 1. The
285 * result of converting 0 with an explicit
286 * precision of 0 is no characters.
287 * <dt>x<dd> The int argument is converted to unsigned
288 * hexadecimal format in the style dddd; the
289 * letters abcdef are used. The precision
290 * specifies the minimum numberof digits to
291 * appear; if the value being converted can be
292 * represented in fewer digits, it will be
293 * expanded with leading zeros. The default
294 * precision is 1. The result of converting 0
295 * with an explicit precision of 0 is no
296 * characters.
297 * <dt>X<dd> Behaves the same as the x conversion
298 * character except that letters ABCDEF are
299 * used instead of abcdef.
300 * <dt>f<dd> The floating point number argument is
301 * written in decimal notation in the style
302 * [-]ddd.ddd, where the number of digits after
303 * the radix character (shown here as a decimal
304 * point) is equal to the precision
305 * specification. A Locale is used to determine
306 * the radix character to use in this format.
307 * If the precision is omitted from the
308 * argument, six digits are written after the
309 * radix character; if the precision is
310 * explicitly 0 and the # flag is not specified,
311 * no radix character appears. If a radix
312 * character appears, at least 1 digit appears
313 * before it. The value is rounded to the
314 * appropriate number of digits.
315 * <dt>e,E<dd>The floating point number argument is
316 * written in the style [-]d.ddde{+-}dd
317 * (the symbols {+-} indicate either a plus or
318 * minus sign), where there is one digit before
319 * the radix character (shown here as a decimal
320 * point) and the number of digits after it is
321 * equal to the precision. A Locale is used to
322 * determine the radix character to use in this
323 * format. When the precision is missing, six
324 * digits are written after the radix character;
325 * if the precision is 0 and the # flag is not
326 * specified, no radix character appears. The
327 * E conversion will produce a number with E
328 * instead of e introducing the exponent. The
329 * exponent always contains at least two digits.
330 * However, if the value to be written requires
331 * an exponent greater than two digits,
332 * additional exponent digits are written as
333 * necessary. The value is rounded to the
334 * appropriate number of digits.
335 * <dt>g,G<dd>The floating point number argument is
336 * written in style f or e (or in sytle E in the
337 * case of a G conversion character), with the
338 * precision specifying the number of
339 * significant digits. If the precision is
340 * zero, it is taken as one. The style used
341 * depends on the value converted: style e
342 * (or E) will be used only if the exponent
343 * resulting from the conversion is less than
344 * -4 or greater than or equal to the precision.
345 * Trailing zeros are removed from the result.
346 * A radix character appears only if it is
347 * followed by a digit.
348 * <dt>c,C<dd>The integer argument is converted to a
349 * char and the result is written.
350 *
351 * <dt>s,S<dd>The argument is taken to be a string and
352 * bytes from the string are written until the
353 * end of the string or the number of bytes
354 * indicated by the precision specification of
355 * the argument is reached. If the precision
356 * is omitted from the argument, it is taken to
357 * be infinite, so all characters up to the end
358 * of the string are written.
359 * <dt>%<dd>Write a % character; no argument is
360 * converted.
361 *</dl>
362 *<p>
363 * If a conversion specification does not match one of
364 * the above forms, an IllegalArgumentException is
365 * thrown and the instance of PrintfFormat is not
366 * created.</p>
367 *<p>
368 * If a floating point value is the internal
369 * representation for infinity, the output is
370 * [+]Infinity, where Infinity is either Infinity or
371 * Inf, depending on the desired output string length.
372 * Printing of the sign follows the rules described
373 * above.</p>
374 *<p>
375 * If a floating point value is the internal
376 * representation for "not-a-number," the output is
377 * [+]NaN. Printing of the sign follows the rules
378 * described above.</p>
379 *<p>
380 * In no case does a non-existent or small field width
381 * cause truncation of a field; if the result of a
382 * conversion is wider than the field width, the field
383 * is simply expanded to contain the conversion result.
384 *</p>
385 *<p>
386 * The behavior is like printf. One exception is that
387 * the minimum number of exponent digits is 3 instead
388 * of 2 for e and E formats when the optional L is used
389 * before the e, E, g, or G conversion character. The
390 * optional L does not imply conversion to a long long
391 * double. </p>
392 * <p>
393 * The biggest divergence from the C printf
394 * specification is in the use of 16 bit characters.
395 * This allows the handling of characters beyond the
396 * small ASCII character set and allows the utility to
397 * interoperate correctly with the rest of the Java
398 * runtime environment.</p>
399 *<p>
400 * Omissions from the C printf specification are
401 * numerous. All the known omissions are present
402 * because Java never uses bytes to represent
403 * characters and does not have pointers:</p>
404 *<ul>
405 * <li>%c is the same as %C.
406 * <li>%s is the same as %S.
407 * <li>u, p, and n conversion characters.
408 * <li>%ws format.
409 * <li>h modifier applied to an n conversion character.
410 * <li>l (ell) modifier applied to the c, n, or s
411 * conversion characters.
412 * <li>ll (ell ell) modifier to d, i, o, u, x, or X
413 * conversion characters.
414 * <li>ll (ell ell) modifier to an n conversion
415 * character.
416 * <li>c, C, d,i,o,u,x, and X conversion characters
417 * apply to Byte, Character, Short, Integer, Long
418 * types.
419 * <li>f, e, E, g, and G conversion characters apply
420 * to Float and Double types.
421 * <li>s and S conversion characters apply to String
422 * types.
423 * <li>All other reference types can be formatted
424 * using the s or S conversion characters only.
425 *</ul>
426 * <p>
427 * Most of this specification is quoted from the Unix
428 * man page for the sprintf utility.</p>
429 *
430 * @author Allan Jacobs
431 * @version 1
432 * Release 1: Initial release.
433 * Release 2: Asterisk field widths and precisions
434 * %n$ and *m$
435 * Bug fixes
436 * g format fix (2 digits in e form corrupt)
437 * rounding in f format implemented
438 * round up when digit not printed is 5
439 * formatting of -0.0f
440 * round up/down when last digits are 50000...
441 */
442 public class PrintfFormat {
443 /**
444 * Constructs an array of control specifications
445 * possibly preceded, separated, or followed by
446 * ordinary strings. Control strings begin with
447 * unpaired percent signs. A pair of successive
448 * percent signs designates a single percent sign in
449 * the format.
450 * @param fmtArg Control string.
451 * @exception IllegalArgumentException if the control
452 * string is null, zero length, or otherwise
453 * malformed.
454 */
455 public PrintfFormat(String fmtArg)
456 throws IllegalArgumentException {
457 this(Locale.getDefault(),fmtArg);
458 }
459 /**
460 * Constructs an array of control specifications
461 * possibly preceded, separated, or followed by
462 * ordinary strings. Control strings begin with
463 * unpaired percent signs. A pair of successive
464 * percent signs designates a single percent sign in
465 * the format.
466 * @param fmtArg Control string.
467 * @exception IllegalArgumentException if the control
468 * string is null, zero length, or otherwise
469 * malformed.
470 */
471 public PrintfFormat(Locale locale,String fmtArg)
472 throws IllegalArgumentException {
473 dfs = new DecimalFormatSymbols(locale);
474 int ePos=0;
475 ConversionSpecification sFmt=null;
476 String unCS = this.nonControl(fmtArg,0);
477 if (unCS!=null) {
478 sFmt = new ConversionSpecification();
479 sFmt.setLiteral(unCS);
480 vFmt.addElement(sFmt);
481 }
482 while(cPos!=-1 && cPos<fmtArg.length()) {
483 for (ePos=cPos+1; ePos<fmtArg.length();
484 ePos++) {
485 char c=0;
486 c = fmtArg.charAt(ePos);
487 if (c == 'i') break;
488 if (c == 'd') break;
489 if (c == 'f') break;
490 if (c == 'g') break;
491 if (c == 'G') break;
492 if (c == 'o') break;
493 if (c == 'x') break;
494 if (c == 'X') break;
495 if (c == 'e') break;
496 if (c == 'E') break;
497 if (c == 'c') break;
498 if (c == 's') break;
499 if (c == '%') break;
500 }
501 ePos=Math.min(ePos+1,fmtArg.length());
502 sFmt = new ConversionSpecification(
503 fmtArg.substring(cPos,ePos));
504 vFmt.addElement(sFmt);
505 unCS = this.nonControl(fmtArg,ePos);
506 if (unCS!=null) {
507 sFmt = new ConversionSpecification();
508 sFmt.setLiteral(unCS);
509 vFmt.addElement(sFmt);
510 }
511 }
512 }
513 /**
514 * Return a substring starting at
515 * <code>start</code> and ending at either the end
516 * of the String <code>s</code>, the next unpaired
517 * percent sign, or at the end of the String if the
518 * last character is a percent sign.
519 * @param s Control string.
520 * @param start Position in the string
521 * <code>s</code> to begin looking for the start
522 * of a control string.
523 * @return the substring from the start position
524 * to the beginning of the control string.
525 */
526 private String nonControl(String s,int start) {
527 String ret="";
528 cPos=s.indexOf("%",start);
529 if (cPos==-1) cPos=s.length();
530 return s.substring(start,cPos);
531 }
532 /**
533 * Format an array of objects. Byte, Short,
534 * Integer, Long, Float, Double, and Character
535 * arguments are treated as wrappers for primitive
536 * types.
537 * @param o The array of objects to format.
538 * @return The formatted String.
539 */
540 public String sprintf(Object[] o) {
541 Enumeration e = vFmt.elements();
542 ConversionSpecification cs = null;
543 char c = 0;
544 int i=0;
545 StringBuffer sb=new StringBuffer();
546 while (e.hasMoreElements()) {
547 cs = (ConversionSpecification)
548 e.nextElement();
549 c = cs.getConversionCharacter();
550 if (c=='\0') sb.append(cs.getLiteral());
551 else if (c=='%') sb.append("%");
552 else {
553 if (cs.isPositionalSpecification()) {
554 i=cs.getArgumentPosition()-1;
555 if (cs.isPositionalFieldWidth()) {
556 int ifw=cs.getArgumentPositionForFieldWidth()-1;
557 cs.setFieldWidthWithArg(((Integer)o[ifw]).intValue());
558 }
559 if (cs.isPositionalPrecision()) {
560 int ipr=cs.getArgumentPositionForPrecision()-1;
561 cs.setPrecisionWithArg(((Integer)o[ipr]).intValue());
562 }
563 }
564 else {
565 if (cs.isVariableFieldWidth()) {
566 cs.setFieldWidthWithArg(((Integer)o[i]).intValue());
567 i++;
568 }
569 if (cs.isVariablePrecision()) {
570 cs.setPrecisionWithArg(((Integer)o[i]).intValue());
571 i++;
572 }
573 }
574 if (o[i] instanceof Byte)
575 sb.append(cs.internalsprintf(
576 ((Byte)o[i]).byteValue()));
577 else if (o[i] instanceof Short)
578 sb.append(cs.internalsprintf(
579 ((Short)o[i]).shortValue()));
580 else if (o[i] instanceof Integer)
581 sb.append(cs.internalsprintf(
582 ((Integer)o[i]).intValue()));
583 else if (o[i] instanceof Long)
584 sb.append(cs.internalsprintf(
585 ((Long)o[i]).longValue()));
586 else if (o[i] instanceof Float)
587 sb.append(cs.internalsprintf(
588 ((Float)o[i]).floatValue()));
589 else if (o[i] instanceof Double)
590 sb.append(cs.internalsprintf(
591 ((Double)o[i]).doubleValue()));
592 else if (o[i] instanceof Character)
593 sb.append(cs.internalsprintf(
594 ((Character)o[i]).charValue()));
595 else if (o[i] instanceof String)
596 sb.append(cs.internalsprintf(
597 (String)o[i]));
598 else
599 sb.append(cs.internalsprintf(
600 o[i]));
601 if (!cs.isPositionalSpecification())
602 i++;
603 }
604 }
605 return sb.toString();
606 }
607 /**
608 * Format nothing. Just use the control string.
609 * @return the formatted String.
610 */
611 public String sprintf() {
612 Enumeration e = vFmt.elements();
613 ConversionSpecification cs = null;
614 char c = 0;
615 StringBuffer sb=new StringBuffer();
616 while (e.hasMoreElements()) {
617 cs = (ConversionSpecification)
618 e.nextElement();
619 c = cs.getConversionCharacter();
620 if (c=='\0') sb.append(cs.getLiteral());
621 else if (c=='%') sb.append("%");
622 }
623 return sb.toString();
624 }
625 /**
626 * Format an int.
627 * @param x The int to format.
628 * @return The formatted String.
629 * @exception IllegalArgumentException if the
630 * conversion character is f, e, E, g, G, s,
631 * or S.
632 */
633 public String sprintf(int x)
634 throws IllegalArgumentException {
635 Enumeration e = vFmt.elements();
636 ConversionSpecification cs = null;
637 char c = 0;
638 StringBuffer sb=new StringBuffer();
639 while (e.hasMoreElements()) {
640 cs = (ConversionSpecification)
641 e.nextElement();
642 c = cs.getConversionCharacter();
643 if (c=='\0') sb.append(cs.getLiteral());
644 else if (c=='%') sb.append("%");
645 else sb.append(cs.internalsprintf(x));
646 }
647 return sb.toString();
648 }
649 /**
650 * Format an long.
651 * @param x The long to format.
652 * @return The formatted String.
653 * @exception IllegalArgumentException if the
654 * conversion character is f, e, E, g, G, s,
655 * or S.
656 */
657 public String sprintf(long x)
658 throws IllegalArgumentException {
659 Enumeration e = vFmt.elements();
660 ConversionSpecification cs = null;
661 char c = 0;
662 StringBuffer sb=new StringBuffer();
663 while (e.hasMoreElements()) {
664 cs = (ConversionSpecification)
665 e.nextElement();
666 c = cs.getConversionCharacter();
667 if (c=='\0') sb.append(cs.getLiteral());
668 else if (c=='%') sb.append("%");
669 else sb.append(cs.internalsprintf(x));
670 }
671 return sb.toString();
672 }
673 /**
674 * Format a double.
675 * @param x The double to format.
676 * @return The formatted String.
677 * @exception IllegalArgumentException if the
678 * conversion character is c, C, s, S,
679 * d, d, x, X, or o.
680 */
681 public String sprintf(double x)
682 throws IllegalArgumentException {
683 Enumeration e = vFmt.elements();
684 ConversionSpecification cs = null;
685 char c = 0;
686 StringBuffer sb=new StringBuffer();
687 while (e.hasMoreElements()) {
688 cs = (ConversionSpecification)
689 e.nextElement();
690 c = cs.getConversionCharacter();
691 if (c=='\0') sb.append(cs.getLiteral());
692 else if (c=='%') sb.append("%");
693 else sb.append(cs.internalsprintf(x));
694 }
695 return sb.toString();
696 }
697 /**
698 * Format a String.
699 * @param x The String to format.
700 * @return The formatted String.
701 * @exception IllegalArgumentException if the
702 * conversion character is neither s nor S.
703 */
704 public String sprintf(String x)
705 throws IllegalArgumentException {
706 Enumeration e = vFmt.elements();
707 ConversionSpecification cs = null;
708 char c = 0;
709 StringBuffer sb=new StringBuffer();
710 while (e.hasMoreElements()) {
711 cs = (ConversionSpecification)
712 e.nextElement();
713 c = cs.getConversionCharacter();
714 if (c=='\0') sb.append(cs.getLiteral());
715 else if (c=='%') sb.append("%");
716 else sb.append(cs.internalsprintf(x));
717 }
718 return sb.toString();
719 }
720 /**
721 * Format an Object. Convert wrapper types to
722 * their primitive equivalents and call the
723 * appropriate internal formatting method. Convert
724 * Strings using an internal formatting method for
725 * Strings. Otherwise use the default formatter
726 * (use toString).
727 * @param x the Object to format.
728 * @return the formatted String.
729 * @exception IllegalArgumentException if the
730 * conversion character is inappropriate for
731 * formatting an unwrapped value.
732 */
733 public String sprintf(Object x)
734 throws IllegalArgumentException {
735 Enumeration e = vFmt.elements();
736 ConversionSpecification cs = null;
737 char c = 0;
738 StringBuffer sb=new StringBuffer();
739 while (e.hasMoreElements()) {
740 cs = (ConversionSpecification)
741 e.nextElement();
742 c = cs.getConversionCharacter();
743 if (c=='\0') sb.append(cs.getLiteral());
744 else if (c=='%') sb.append("%");
745 else {
746 if (x instanceof Byte)
747 sb.append(cs.internalsprintf(
748 ((Byte)x).byteValue()));
749 else if (x instanceof Short)
750 sb.append(cs.internalsprintf(
751 ((Short)x).shortValue()));
752 else if (x instanceof Integer)
753 sb.append(cs.internalsprintf(
754 ((Integer)x).intValue()));
755 else if (x instanceof Long)
756 sb.append(cs.internalsprintf(
757 ((Long)x).longValue()));
758 else if (x instanceof Float)
759 sb.append(cs.internalsprintf(
760 ((Float)x).floatValue()));
761 else if (x instanceof Double)
762 sb.append(cs.internalsprintf(
763 ((Double)x).doubleValue()));
764 else if (x instanceof Character)
765 sb.append(cs.internalsprintf(
766 ((Character)x).charValue()));
767 else if (x instanceof String)
768 sb.append(cs.internalsprintf(
769 (String)x));
770 else
771 sb.append(cs.internalsprintf(x));
772 }
773 }
774 return sb.toString();
775 }
776 /**
777 *<p>
778 * ConversionSpecification allows the formatting of
779 * a single primitive or object embedded within a
780 * string. The formatting is controlled by a
781 * format string. Only one Java primitive or
782 * object can be formatted at a time.
783 *<p>
784 * A format string is a Java string that contains
785 * a control string. The control string starts at
786 * the first percent sign (%) in the string,
787 * provided that this percent sign
788 *<ol>
789 *<li>is not escaped protected by a matching % or
790 * is not an escape % character,
791 *<li>is not at the end of the format string, and
792 *<li>precedes a sequence of characters that parses
793 * as a valid control string.
794 *</ol>
795 *<p>
796 * A control string takes the form:
797 *<pre> % ['-+ #0]* [0..9]* { . [0..9]* }+
798 * { [hlL] }+ [idfgGoxXeEcs]
799 *</pre>
800 *<p>
801 * The behavior is like printf. One (hopefully the
802 * only) exception is that the minimum number of
803 * exponent digits is 3 instead of 2 for e and E
804 * formats when the optional L is used before the
805 * e, E, g, or G conversion character. The
806 * optional L does not imply conversion to a long
807 * long double.
808 */
809 private class ConversionSpecification {
810 /**
811 * Constructor. Used to prepare an instance
812 * to hold a literal, not a control string.
813 */
814 ConversionSpecification() { }
815 /**
816 * Constructor for a conversion specification.
817 * The argument must begin with a % and end
818 * with the conversion character for the
819 * conversion specification.
820 * @param fmtArg String specifying the
821 * conversion specification.
822 * @exception IllegalArgumentException if the
823 * input string is null, zero length, or
824 * otherwise malformed.
825 */
826 ConversionSpecification(String fmtArg)
827 throws IllegalArgumentException {
828 if (fmtArg==null)
829 throw new NullPointerException();
830 if (fmtArg.length()==0)
831 throw new IllegalArgumentException(
832 "Control strings must have positive"+
833 " lengths.");
834 if (fmtArg.charAt(0)=='%') {
835 fmt = fmtArg;
836 pos=1;
837 setArgPosition();
838 setFlagCharacters();
839 setFieldWidth();
840 setPrecision();
841 setOptionalHL();
842 if (setConversionCharacter()) {
843 if (pos==fmtArg.length()) {
844 if(leadingZeros&&leftJustify)
845 leadingZeros=false;
846 if(precisionSet&&leadingZeros){
847 if(conversionCharacter=='d'
848 ||conversionCharacter=='i'
849 ||conversionCharacter=='o'
850 ||conversionCharacter=='x')
851 {
852 leadingZeros=false;
853 }
854 }
855 }
856 else
857 throw new IllegalArgumentException(
858 "Malformed conversion specification="+
859 fmtArg);
860 }
861 else
862 throw new IllegalArgumentException(
863 "Malformed conversion specification="+
864 fmtArg);
865 }
866 else
867 throw new IllegalArgumentException(
868 "Control strings must begin with %.");
869 }
870 /**
871 * Set the String for this instance.
872 * @param s the String to store.
873 */
874 void setLiteral(String s) {
875 fmt = s;
876 }
877 /**
878 * Get the String for this instance. Translate
879 * any escape sequences.
880 *
881 * @return s the stored String.
882 */
883 String getLiteral() {
884 StringBuffer sb=new StringBuffer();
885 int i=0;
886 while (i<fmt.length()) {
887 if (fmt.charAt(i)=='\\') {
888 i++;
889 if (i<fmt.length()) {
890 char c=fmt.charAt(i);
891 switch(c) {
892 case 'a':
893 sb.append((char)0x07);
894 break;
895 case 'b':
896 sb.append('\b');
897 break;
898 case 'f':
899 sb.append('\f');
900 break;
901 case 'n':
902 sb.append(System.getProperty("line.separator"));
903 break;
904 case 'r':
905 sb.append('\r');
906 break;
907 case 't':
908 sb.append('\t');
909 break;
910 case 'v':
911 sb.append((char)0x0b);
912 break;
913 case '\\':
914 sb.append('\\');
915 break;
916 }
917 i++;
918 }
919 else
920 sb.append('\\');
921 }
922 else
923 i++;
924 }
925 return fmt;
926 }
927 /**
928 * Get the conversion character that tells what
929 * type of control character this instance has.
930 *
931 * @return the conversion character.
932 */
933 char getConversionCharacter() {
934 return conversionCharacter;
935 }
936 /**
937 * Check whether the specifier has a variable
938 * field width that is going to be set by an
939 * argument.
940 * @return <code>true</code> if the conversion
941 * uses an * field width; otherwise
942 * <code>false</code>.
943 */
944 boolean isVariableFieldWidth() {
945 return variableFieldWidth;
946 }
947 /**
948 * Set the field width with an argument. A
949 * negative field width is taken as a - flag
950 * followed by a positive field width.
951 * @param fw the field width.
952 */
953 void setFieldWidthWithArg(int fw) {
954 if (fw<0) leftJustify = true;
955 fieldWidthSet = true;
956 fieldWidth = Math.abs(fw);
957 }
958 /**
959 * Check whether the specifier has a variable
960 * precision that is going to be set by an
961 * argument.
962 * @return <code>true</code> if the conversion
963 * uses an * precision; otherwise
964 * <code>false</code>.
965 */
966 boolean isVariablePrecision() {
967 return variablePrecision;
968 }
969 /**
970 * Set the precision with an argument. A
971 * negative precision will be changed to zero.
972 * @param pr the precision.
973 */
974 void setPrecisionWithArg(int pr) {
975 precisionSet = true;
976 precision = Math.max(pr,0);
977 }
978 /**
979 * Format an int argument using this conversion
980 * specification.
981 * @param s the int to format.
982 * @return the formatted String.
983 * @exception IllegalArgumentException if the
984 * conversion character is f, e, E, g, or G.
985 */
986 String internalsprintf(int s)
987 throws IllegalArgumentException {
988 String s2 = "";
989 switch(conversionCharacter) {
990 case 'd':
991 case 'i':
992 if (optionalh)
993 s2 = printDFormat((short)s);
994 else if (optionall)
995 s2 = printDFormat((long)s);
996 else
997 s2 = printDFormat(s);
998 break;
999 case 'x':
1000 case 'X':
1001 if (optionalh)
1002 s2 = printXFormat((short)s);
1003 else if (optionall)
1004 s2 = printXFormat((long)s);
1005 else
1006 s2 = printXFormat(s);
1007 break;
1008 case 'o':
1009 if (optionalh)
1010 s2 = printOFormat((short)s);
1011 else if (optionall)
1012 s2 = printOFormat((long)s);
1013 else
1014 s2 = printOFormat(s);
1015 break;
1016 case 'c':
1017 case 'C':
1018 s2 = printCFormat((char)s);
1019 break;
1020 default:
1021 throw new IllegalArgumentException(
1022 "Cannot format a int with a format using a "+
1023 conversionCharacter+
1024 " conversion character.");
1025 }
1026 return s2;
1027 }
1028 /**
1029 * Format a long argument using this conversion
1030 * specification.
1031 * @param s the long to format.
1032 * @return the formatted String.
1033 * @exception IllegalArgumentException if the
1034 * conversion character is f, e, E, g, or G.
1035 */
1036 String internalsprintf(long s)
1037 throws IllegalArgumentException {
1038 String s2 = "";
1039 switch(conversionCharacter) {
1040 case 'd':
1041 case 'i':
1042 if (optionalh)
1043 s2 = printDFormat((short)s);
1044 else if (optionall)
1045 s2 = printDFormat(s);
1046 else
1047 s2 = printDFormat((int)s);
1048 break;
1049 case 'x':
1050 case 'X':
1051 if (optionalh)
1052 s2 = printXFormat((short)s);
1053 else if (optionall)
1054 s2 = printXFormat(s);
1055 else
1056 s2 = printXFormat((int)s);
1057 break;
1058 case 'o':
1059 if (optionalh)
1060 s2 = printOFormat((short)s);
1061 else if (optionall)
1062 s2 = printOFormat(s);
1063 else
1064 s2 = printOFormat((int)s);
1065 break;
1066 case 'c':
1067 case 'C':
1068 s2 = printCFormat((char)s);
1069 break;
1070 default:
1071 throw new IllegalArgumentException(
1072 "Cannot format a long with a format using a "+
1073 conversionCharacter+" conversion character.");
1074 }
1075 return s2;
1076 }
1077 /**
1078 * Format a double argument using this conversion
1079 * specification.
1080 * @param s the double to format.
1081 * @return the formatted String.
1082 * @exception IllegalArgumentException if the
1083 * conversion character is c, C, s, S, i, d,
1084 * x, X, or o.
1085 */
1086 String internalsprintf(double s)
1087 throws IllegalArgumentException {
1088 String s2 = "";
1089 switch(conversionCharacter) {
1090 case 'f':
1091 s2 = printFFormat(s);
1092 break;
1093 case 'E':
1094 case 'e':
1095 s2 = printEFormat(s);
1096 break;
1097 case 'G':
1098 case 'g':
1099 s2 = printGFormat(s);
1100 break;
1101 default:
1102 throw new IllegalArgumentException("Cannot "+
1103 "format a double with a format using a "+
1104 conversionCharacter+" conversion character.");
1105 }
1106 return s2;
1107 }
1108 /**
1109 * Format a String argument using this conversion
1110 * specification.
1111 * @param s the String to format.
1112 * @return the formatted String.
1113 * @exception IllegalArgumentException if the
1114 * conversion character is neither s nor S.
1115 */
1116 String internalsprintf(String s)
1117 throws IllegalArgumentException {
1118 String s2 = "";
1119 if(conversionCharacter=='s'
1120 || conversionCharacter=='S')
1121 s2 = printSFormat(s);
1122 else
1123 throw new IllegalArgumentException("Cannot "+
1124 "format a String with a format using a "+
1125 conversionCharacter+" conversion character.");
1126 return s2;
1127 }
1128 /**
1129 * Format an Object argument using this conversion
1130 * specification.
1131 * @param s the Object to format.
1132 * @return the formatted String.
1133 * @exception IllegalArgumentException if the
1134 * conversion character is neither s nor S.
1135 */
1136 String internalsprintf(Object s) {
1137 String s2 = "";
1138 if(conversionCharacter=='s'
1139 || conversionCharacter=='S')
1140 s2 = printSFormat(s.toString());
1141 else
1142 throw new IllegalArgumentException(
1143 "Cannot format a String with a format using"+
1144 " a "+conversionCharacter+
1145 " conversion character.");
1146 return s2;
1147 }
1148 /**
1149 * For f format, the flag character '-', means that
1150 * the output should be left justified within the
1151 * field. The default is to pad with blanks on the
1152 * left. '+' character means that the conversion
1153 * will always begin with a sign (+ or -). The
1154 * blank flag character means that a non-negative
1155 * input will be preceded with a blank. If both
1156 * a '+' and a ' ' are specified, the blank flag
1157 * is ignored. The '0' flag character implies that
1158 * padding to the field width will be done with
1159 * zeros instead of blanks.
1160 *
1161 * The field width is treated as the minimum number
1162 * of characters to be printed. The default is to
1163 * add no padding. Padding is with blanks by
1164 * default.
1165 *
1166 * The precision, if set, is the number of digits
1167 * to appear after the radix character. Padding is
1168 * with trailing 0s.
1169 */
1170 private char[] fFormatDigits(double x) {
1171 // int defaultDigits=6;
1172 String sx,sxOut;
1173 int i,j,k;
1174 int n1In,n2In;
1175 int expon=0;
1176 boolean minusSign=false;
1177 if (x>0.0)
1178 sx = Double.toString(x);
1179 else if (x<0.0) {
1180 sx = Double.toString(-x);
1181 minusSign=true;
1182 }
1183 else {
1184 sx = Double.toString(x);
1185 if (sx.charAt(0)=='-') {
1186 minusSign=true;
1187 sx=sx.substring(1);
1188 }
1189 }
1190 int ePos = sx.indexOf('E');
1191 int rPos = sx.indexOf('.');
1192 if (rPos!=-1) n1In=rPos;
1193 else if (ePos!=-1) n1In=ePos;
1194 else n1In=sx.length();
1195 if (rPos!=-1) {
1196 if (ePos!=-1) n2In = ePos-rPos-1;
1197 else n2In = sx.length()-rPos-1;
1198 }
1199 else
1200 n2In = 0;
1201 if (ePos!=-1) {
1202 int ie=ePos+1;
1203 expon=0;
1204 if (sx.charAt(ie)=='-') {
1205 for (++ie; ie<sx.length(); ie++)
1206 if (sx.charAt(ie)!='0') break;
1207 if (ie<sx.length())
1208 expon=-Integer.parseInt(sx.substring(ie));
1209 }
1210 else {
1211 if (sx.charAt(ie)=='+') ++ie;
1212 for (; ie<sx.length(); ie++)
1213 if (sx.charAt(ie)!='0') break;
1214 if (ie<sx.length())
1215 expon=Integer.parseInt(sx.substring(ie));
1216 }
1217 }
1218 int p;
1219 if (precisionSet) p = precision;
1220 else p = defaultDigits-1;
1221 char[] ca1 = sx.toCharArray();
1222 char[] ca2 = new char[n1In+n2In];
1223 char[] ca3,ca4,ca5;
1224 for (j=0; j<n1In; j++)
1225 ca2[j] = ca1[j];
1226 i = j+1;
1227 for (k=0; k<n2In; j++,i++,k++)
1228 ca2[j] = ca1[i];
1229 if (n1In+expon<=0) {
1230 ca3 = new char[-expon+n2In];
1231 for (j=0,k=0; k<(-n1In-expon); k++,j++)
1232 ca3[j]='0';
1233 for (i=0; i<(n1In+n2In); i++,j++)
1234 ca3[j]=ca2[i];
1235 }
1236 else
1237 ca3 = ca2;
1238 boolean carry=false;
1239 if (p<-expon+n2In) {
1240 if (expon<0) i = p;
1241 else i = p+n1In;
1242 carry=checkForCarry(ca3,i);
1243 if (carry)
1244 carry=startSymbolicCarry(ca3,i-1,0);
1245 }
1246 if (n1In+expon<=0) {
1247 ca4 = new char[2+p];
1248 if (!carry) ca4[0]='0';
1249 else ca4[0]='1';
1250 if(alternateForm||!precisionSet||precision!=0){
1251 ca4[1]='.';
1252 for(i=0,j=2;i<Math.min(p,ca3.length);i++,j++)
1253 ca4[j]=ca3[i];
1254 for (; j<ca4.length; j++) ca4[j]='0';
1255 }
1256 }
1257 else {
1258 if (!carry) {
1259 if(alternateForm||!precisionSet
1260 ||precision!=0)
1261 ca4 = new char[n1In+expon+p+1];
1262 else
1263 ca4 = new char[n1In+expon];
1264 j=0;
1265 }
1266 else {
1267 if(alternateForm||!precisionSet
1268 ||precision!=0)
1269 ca4 = new char[n1In+expon+p+2];
1270 else
1271 ca4 = new char[n1In+expon+1];
1272 ca4[0]='1';
1273 j=1;
1274 }
1275 for (i=0; i<Math.min(n1In+expon,ca3.length); i++,j++)
1276 ca4[j]=ca3[i];
1277 for (; i<n1In+expon; i++,j++)
1278 ca4[j]='0';
1279 if(alternateForm||!precisionSet||precision!=0){
1280 ca4[j]='.'; j++;
1281 for (k=0; i<ca3.length && k<p; i++,j++,k++)
1282 ca4[j]=ca3[i];
1283 for (; j<ca4.length; j++) ca4[j]='0';
1284 }
1285 }
1286 int nZeros=0;
1287 if (!leftJustify && leadingZeros) {
1288 int xThousands=0;
1289 if (thousands) {
1290 int xlead=0;
1291 if (ca4[0]=='+'||ca4[0]=='-'||ca4[0]==' ')
1292 xlead=1;
1293 int xdp=xlead;
1294 for (; xdp<ca4.length; xdp++)
1295 if (ca4[xdp]=='.') break;
1296 xThousands=(xdp-xlead)/3;
1297 }
1298 if (fieldWidthSet)
1299 nZeros = fieldWidth-ca4.length;
1300 if ((!minusSign&&(leadingSign||leadingSpace))||minusSign)
1301 nZeros--;
1302 nZeros-=xThousands;
1303 if (nZeros<0) nZeros=0;
1304 }
1305 j=0;
1306 if ((!minusSign&&(leadingSign||leadingSpace))||minusSign) {
1307 ca5 = new char[ca4.length+nZeros+1];
1308 j++;
1309 }
1310 else
1311 ca5 = new char[ca4.length+nZeros];
1312 if (!minusSign) {
1313 if (leadingSign) ca5[0]='+';
1314 if (leadingSpace) ca5[0]=' ';
1315 }
1316 else
1317 ca5[0]='-';
1318 for (i=0; i<nZeros; i++,j++)
1319 ca5[j]='0';
1320 for (i=0; i<ca4.length; i++,j++) ca5[j]=ca4[i];
1321
1322 int lead=0;
1323 if (ca5[0]=='+'||ca5[0]=='-'||ca5[0]==' ')
1324 lead=1;
1325 int dp=lead;
1326 for (; dp<ca5.length; dp++)
1327 if (ca5[dp]=='.') break;
1328 int nThousands=(dp-lead)/3;
1329 // Localize the decimal point.
1330 if (dp<ca5.length)
1331 ca5[dp]=dfs.getDecimalSeparator();
1332 char[] ca6 = ca5;
1333 if (thousands && nThousands>0) {
1334 ca6 = new char[ca5.length+nThousands+lead];
1335 ca6[0]=ca5[0];
1336 for (i=lead,k=lead; i<dp; i++) {
1337 if (i>0 && (dp-i)%3==0) {
1338 // ca6[k]=',';
1339 ca6[k]=dfs.getGroupingSeparator();
1340 ca6[k+1]=ca5[i];
1341 k+=2;
1342 }
1343 else {
1344 ca6[k]=ca5[i]; k++;
1345 }
1346 }
1347 for (; i<ca5.length; i++,k++) {
1348 ca6[k]=ca5[i];
1349 }
1350 }
1351 return ca6;
1352 }
1353 /**
1354 * An intermediate routine on the way to creating
1355 * an f format String. The method decides whether
1356 * the input double value is an infinity,
1357 * not-a-number, or a finite double and formats
1358 * each type of input appropriately.
1359 * @param x the double value to be formatted.
1360 * @return the converted double value.
1361 */
1362 private String fFormatString(double x) {
1363 boolean noDigits=false;
1364 char[] ca6,ca7;
1365 if (Double.isInfinite(x)) {
1366 if (x==Double.POSITIVE_INFINITY) {
1367 if (leadingSign) ca6 = "+Inf".toCharArray();
1368 else if (leadingSpace)
1369 ca6 = " Inf".toCharArray();
1370 else ca6 = "Inf".toCharArray();
1371 }
1372 else
1373 ca6 = "-Inf".toCharArray();
1374 noDigits = true;
1375 }
1376 else if (Double.isNaN(x)) {
1377 if (leadingSign) ca6 = "+NaN".toCharArray();
1378 else if (leadingSpace)
1379 ca6 = " NaN".toCharArray();
1380 else ca6 = "NaN".toCharArray();
1381 noDigits = true;
1382 }
1383 else
1384 ca6 = fFormatDigits(x);
1385 ca7 = applyFloatPadding(ca6,false);
1386 return new String(ca7);
1387 }
1388 /**
1389 * For e format, the flag character '-', means that
1390 * the output should be left justified within the
1391 * field. The default is to pad with blanks on the
1392 * left. '+' character means that the conversion
1393 * will always begin with a sign (+ or -). The
1394 * blank flag character means that a non-negative
1395 * input will be preceded with a blank. If both a
1396 * '+' and a ' ' are specified, the blank flag is
1397 * ignored. The '0' flag character implies that
1398 * padding to the field width will be done with
1399 * zeros instead of blanks.
1400 *
1401 * The field width is treated as the minimum number
1402 * of characters to be printed. The default is to
1403 * add no padding. Padding is with blanks by
1404 * default.
1405 *
1406 * The precision, if set, is the minimum number of
1407 * digits to appear after the radix character.
1408 * Padding is with trailing 0s.
1409 *
1410 * The behavior is like printf. One (hopefully the
1411 * only) exception is that the minimum number of
1412 * exponent digits is 3 instead of 2 for e and E
1413 * formats when the optional L is used before the
1414 * e, E, g, or G conversion character. The optional
1415 * L does not imply conversion to a long long
1416 * double.
1417 */
1418 private char[] eFormatDigits(double x,char eChar) {
1419 char[] ca1,ca2,ca3;
1420 // int defaultDigits=6;
1421 String sx,sxOut;
1422 int i,j,k,p;
1423 int n1In,n2In;
1424 int expon=0;
1425 int ePos,rPos,eSize;
1426 boolean minusSign=false;
1427 if (x>0.0)
1428 sx = Double.toString(x);
1429 else if (x<0.0) {
1430 sx = Double.toString(-x);
1431 minusSign=true;
1432 }
1433 else {
1434 sx = Double.toString(x);
1435 if (sx.charAt(0)=='-') {
1436 minusSign=true;
1437 sx=sx.substring(1);
1438 }
1439 }
1440 ePos = sx.indexOf('E');
1441 if (ePos==-1) ePos = sx.indexOf('e');
1442 rPos = sx.indexOf('.');
1443 if (rPos!=-1) n1In=rPos;
1444 else if (ePos!=-1) n1In=ePos;
1445 else n1In=sx.length();
1446 if (rPos!=-1) {
1447 if (ePos!=-1) n2In = ePos-rPos-1;
1448 else n2In = sx.length()-rPos-1;
1449 }
1450 else
1451 n2In = 0;
1452 if (ePos!=-1) {
1453 int ie=ePos+1;
1454 expon=0;
1455 if (sx.charAt(ie)=='-') {
1456 for (++ie; ie<sx.length(); ie++)
1457 if (sx.charAt(ie)!='0') break;
1458 if (ie<sx.length())
1459 expon=-Integer.parseInt(sx.substring(ie));
1460 }
1461 else {
1462 if (sx.charAt(ie)=='+') ++ie;
1463 for (; ie<sx.length(); ie++)
1464 if (sx.charAt(ie)!='0') break;
1465 if (ie<sx.length())
1466 expon=Integer.parseInt(sx.substring(ie));
1467 }
1468 }
1469 if (rPos!=-1) expon += rPos-1;
1470 if (precisionSet) p = precision;
1471 else p = defaultDigits-1;
1472 if (rPos!=-1 && ePos!=-1)
1473 ca1=(sx.substring(0,rPos)+
1474 sx.substring(rPos+1,ePos)).toCharArray();
1475 else if (rPos!=-1)
1476 ca1 = (sx.substring(0,rPos)+
1477 sx.substring(rPos+1)).toCharArray();
1478 else if (ePos!=-1)
1479 ca1 = sx.substring(0,ePos).toCharArray();
1480 else
1481 ca1 = sx.toCharArray();
1482 boolean carry=false;
1483 int i0=0;
1484 if (ca1[0]!='0')
1485 i0 = 0;
1486 else
1487 for (i0=0; i0<ca1.length; i0++)
1488 if (ca1[i0]!='0') break;
1489 if (i0+p<ca1.length-1) {
1490 carry=checkForCarry(ca1,i0+p+1);
1491 if (carry)
1492 carry = startSymbolicCarry(ca1,i0+p,i0);
1493 if (carry) {
1494 ca2 = new char[i0+p+1];
1495 ca2[i0]='1';
1496 for (j=0; j<i0; j++) ca2[j]='0';
1497 for (i=i0,j=i0+1; j<p+1; i++,j++)
1498 ca2[j] = ca1[i];
1499 expon++;
1500 ca1 = ca2;
1501 }
1502 }
1503 if (Math.abs(expon)<100 && !optionalL) eSize=4;
1504 else eSize=5;
1505 if (alternateForm||!precisionSet||precision!=0)
1506 ca2 = new char[2+p+eSize];
1507 else