PageRenderTime 145ms CodeModel.GetById 30ms RepoModel.GetById 6ms app.codeStats 2ms

/core/src/main/java/org/renjin/primitives/text/Formatter.java

http://renjin.googlecode.com/
Java | 1909 lines | 1037 code | 19 blank | 853 comment | 358 complexity | 40e36d5866f2f6004d18fa0a2adb249e MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, LGPL-3.0, CC-BY-SA-4.0, GPL-2.0, GPL-3.0

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file