PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lazerdoom/libs/colt/src/corejava/Format.java

http://lazerdoom.googlecode.com/
Java | 643 lines | 440 code | 55 blank | 148 comment | 229 complexity | 24682eab30be2ca8de7714728a522342 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, GPL-3.0, GPL-2.0
  1. /*
  2. Format - printf style formatting for Java
  3. Copyright (C) 1995...2002 Cay S. Horstmann (http://horstmann.com)
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. */
  16. package corejava;
  17. import java.io.*;
  18. /**
  19. A class for formatting numbers that follows <tt>printf</tt> conventions.
  20. Also implements C-like <tt>atoi</tt> and <tt>atof</tt> functions
  21. @version 1.22 2002-11-16
  22. @author Cay Horstmann
  23. 1998-09-14: Fixed a number of bugs.
  24. 1.Formatting the most extreme negative number (-9223372036854775808L) printed with 2 leading minus signs.
  25. 2.Printing 0 with a %e or %g format did not work.
  26. 3.Printing numbers that were closer to 1 than the number of requested decimal places rounded down rather than up, e.g. formatting 1.999 with %.2f printed 1.00. (This one is pretty serious, of course.)
  27. 4.Printing with precision 0 (e.g %10.0f) didn't work.
  28. 5.Printing a string with a precision that exceeded the string length (e.g. print "Hello" with %20.10s) caused a StringIndexOutOfBounds error.
  29. 1998-10-21: Changed method names from print to printf
  30. 2000-06-09: Moved to package com.horstmann; no longer part of
  31. Core Java
  32. 2000-06-09: Fixed a number of bugs.
  33. 1.Printing 100.0 with %e printed 10.0e1, not 1.0e2
  34. 2.Printing Inf and NaN didn't work.
  35. 2000-06-09: Coding guideline cleanup
  36. 2002-11-16: Move to package com.horstmann.format; licensed under LGPL
  37. */
  38. public class Format
  39. {
  40. /**
  41. Formats the number following <tt>printf</tt> conventions.
  42. Main limitation: Can only handle one format parameter at a time
  43. Use multiple Format objects to format more than one number
  44. @param s the format string following printf conventions
  45. The string has a prefix, a format code and a suffix. The prefix and suffix
  46. become part of the formatted output. The format code directs the
  47. formatting of the (single) parameter to be formatted. The code has the
  48. following structure
  49. <ul>
  50. <li> a % (required)
  51. <li> a modifier (optional)
  52. <dl>
  53. <dt> + <dd> forces display of + for positive numbers
  54. <dt> 0 <dd> show leading zeroes
  55. <dt> - <dd> align left in the field
  56. <dt> space <dd> prepend a space in front of positive numbers
  57. <dt> # <dd> use "alternate" format. Add 0 or 0x for octal or hexadecimal numbers. Don't suppress trailing zeroes in general floating point format.
  58. </dl>
  59. <li> an integer denoting field width (optional)
  60. <li> a period followed by an integer denoting precision (optional)
  61. <li> a format descriptor (required)
  62. <dl>
  63. <dt>f <dd> floating point number in fixed format
  64. <dt>e, E <dd> floating point number in exponential notation (scientific format). The E format results in an uppercase E for the exponent (1.14130E+003), the e format in a lowercase e.
  65. <dt>g, G <dd> floating point number in general format (fixed format for small numbers, exponential format for large numbers). Trailing zeroes are suppressed. The G format results in an uppercase E for the exponent (if any), the g format in a lowercase e.
  66. <dt>d, i <dd> integer in decimal
  67. <dt>x <dd> integer in hexadecimal
  68. <dt>o <dd> integer in octal
  69. <dt>s <dd> string
  70. <dt>c <dd> character
  71. </dl>
  72. </ul>
  73. @exception IllegalArgumentException if bad format
  74. */
  75. public Format(String s)
  76. {
  77. width = 0;
  78. precision = -1;
  79. pre = "";
  80. post = "";
  81. leadingZeroes = false;
  82. showPlus = false;
  83. alternate = false;
  84. showSpace = false;
  85. leftAlign = false;
  86. fmt = ' ';
  87. int state = 0;
  88. int length = s.length();
  89. int parseState = 0;
  90. // 0 = prefix, 1 = flags, 2 = width, 3 = precision,
  91. // 4 = format, 5 = end
  92. int i = 0;
  93. while (parseState == 0)
  94. {
  95. if (i >= length) parseState = 5;
  96. else if (s.charAt(i) == '%')
  97. {
  98. if (i < length - 1)
  99. {
  100. if (s.charAt(i + 1) == '%')
  101. {
  102. pre = pre + '%';
  103. i++;
  104. }
  105. else
  106. parseState = 1;
  107. }
  108. else throw new java.lang.IllegalArgumentException();
  109. }
  110. else
  111. pre = pre + s.charAt(i);
  112. i++;
  113. }
  114. while (parseState == 1)
  115. {
  116. if (i >= length) parseState = 5;
  117. else if (s.charAt(i) == ' ') showSpace = true;
  118. else if (s.charAt(i) == '-') leftAlign = true;
  119. else if (s.charAt(i) == '+') showPlus = true;
  120. else if (s.charAt(i) == '0') leadingZeroes = true;
  121. else if (s.charAt(i) == '#') alternate = true;
  122. else { parseState = 2; i--; }
  123. i++;
  124. }
  125. while (parseState == 2)
  126. {
  127. if (i >= length) parseState = 5;
  128. else if ('0' <= s.charAt(i) && s.charAt(i) <= '9')
  129. {
  130. width = width * 10 + s.charAt(i) - '0';
  131. i++;
  132. }
  133. else if (s.charAt(i) == '.')
  134. {
  135. parseState = 3;
  136. precision = 0;
  137. i++;
  138. }
  139. else
  140. parseState = 4;
  141. }
  142. while (parseState == 3)
  143. {
  144. if (i >= length) parseState = 5;
  145. else if ('0' <= s.charAt(i) && s.charAt(i) <= '9')
  146. {
  147. precision = precision * 10 + s.charAt(i) - '0';
  148. i++;
  149. }
  150. else
  151. parseState = 4;
  152. }
  153. if (parseState == 4)
  154. {
  155. if (i >= length) parseState = 5;
  156. else fmt = s.charAt(i);
  157. i++;
  158. }
  159. if (i < length)
  160. post = s.substring(i, length);
  161. }
  162. /**
  163. prints a formatted number following printf conventions
  164. @param fmt the format string
  165. @param x the double to print
  166. */
  167. public static void printf(String fmt, double x)
  168. {
  169. System.out.print(new Format(fmt).format(x));
  170. }
  171. /**
  172. prints a formatted number following printf conventions
  173. @param fmt the format string
  174. @param x the int to print
  175. */
  176. public static void printf(String fmt, int x)
  177. {
  178. System.out.print(new Format(fmt).format(x));
  179. }
  180. /**
  181. prints a formatted number following printf conventions
  182. @param fmt the format string
  183. @param x the long to print
  184. */
  185. public static void printf(String fmt, long x)
  186. {
  187. System.out.print(new Format(fmt).format(x));
  188. }
  189. /**
  190. prints a formatted number following printf conventions
  191. @param fmt the format string
  192. @param x the character to print
  193. */
  194. public static void printf(String fmt, char x)
  195. {
  196. System.out.print(new Format(fmt).format(x));
  197. }
  198. /**
  199. prints a formatted number following printf conventions
  200. @param fmt the format string
  201. @param x a string to print
  202. */
  203. public static void printf(String fmt, String x)
  204. {
  205. System.out.print(new Format(fmt).format(x));
  206. }
  207. /**
  208. Converts a string of digits (decimal, octal or hex) to an integer
  209. @param s a string
  210. @return the numeric value of the prefix of s representing a base 10 integer
  211. */
  212. public static int atoi(String s)
  213. {
  214. return (int)atol(s);
  215. }
  216. /**
  217. Converts a string of digits (decimal, octal or hex) to a long integer
  218. @param s a string
  219. @return the numeric value of the prefix of s representing a base 10 integer
  220. */
  221. public static long atol(String s)
  222. {
  223. int i = 0;
  224. while (i < s.length() && Character.isWhitespace(s.charAt(i))) i++;
  225. if (i < s.length() && s.charAt(i) == '0')
  226. {
  227. if (i + 1 < s.length() && (s.charAt(i + 1) == 'x' || s.charAt(i + 1) == 'X'))
  228. return parseLong(s.substring(i + 2), 16);
  229. else return parseLong(s, 8);
  230. }
  231. else return parseLong(s, 10);
  232. }
  233. private static long parseLong(String s, int base)
  234. {
  235. int i = 0;
  236. int sign = 1;
  237. long r = 0;
  238. while (i < s.length() && Character.isWhitespace(s.charAt(i))) i++;
  239. if (i < s.length() && s.charAt(i) == '-') { sign = -1; i++; }
  240. else if (i < s.length() && s.charAt(i) == '+') { i++; }
  241. while (i < s.length())
  242. {
  243. char ch = s.charAt(i);
  244. if ('0' <= ch && ch < '0' + base)
  245. r = r * base + ch - '0';
  246. else if ('A' <= ch && ch < 'A' + base - 10)
  247. r = r * base + ch - 'A' + 10 ;
  248. else if ('a' <= ch && ch < 'a' + base - 10)
  249. r = r * base + ch - 'a' + 10 ;
  250. else
  251. return r * sign;
  252. i++;
  253. }
  254. return r * sign;
  255. }
  256. /**
  257. Converts a string of digits to a <tt>double</tt>
  258. @param s a string
  259. */
  260. public static double atof(String s)
  261. {
  262. int i = 0;
  263. int sign = 1;
  264. double r = 0; // integer part
  265. double f = 0; // fractional part
  266. double p = 1; // exponent of fractional part
  267. int state = 0; // 0 = int part, 1 = frac part
  268. while (i < s.length() && Character.isWhitespace(s.charAt(i))) i++;
  269. if (i < s.length() && s.charAt(i) == '-') { sign = -1; i++; }
  270. else if (i < s.length() && s.charAt(i) == '+') { i++; }
  271. while (i < s.length())
  272. {
  273. char ch = s.charAt(i);
  274. if ('0' <= ch && ch <= '9')
  275. {
  276. if (state == 0)
  277. r = r * 10 + ch - '0';
  278. else if (state == 1)
  279. {
  280. p = p / 10;
  281. r = r + p * (ch - '0');
  282. }
  283. }
  284. else if (ch == '.')
  285. {
  286. if (state == 0) state = 1;
  287. else return sign * r;
  288. }
  289. else if (ch == 'e' || ch == 'E')
  290. {
  291. long e = (int)parseLong(s.substring(i + 1), 10);
  292. return sign * r * Math.pow(10, e);
  293. }
  294. else return sign * r;
  295. i++;
  296. }
  297. return sign * r;
  298. }
  299. /**
  300. Formats a <tt>double</tt> into a string (like sprintf in C)
  301. @param x the number to format
  302. @return the formatted string
  303. @exception IllegalArgumentException if bad argument
  304. */
  305. public String format(double x)
  306. {
  307. String r;
  308. if (precision < 0) precision = 6;
  309. int s = 1;
  310. if (x < 0) { x = -x; s = -1; }
  311. if (Double.isNaN(x)) r = "NaN";
  312. else if (x == Double.POSITIVE_INFINITY) r = "Inf";
  313. else if (fmt == 'f')
  314. r = fixedFormat(x);
  315. else if (fmt == 'e' || fmt == 'E' || fmt == 'g' || fmt == 'G')
  316. r = expFormat(x);
  317. else throw new java.lang.IllegalArgumentException();
  318. return pad(sign(s, r));
  319. }
  320. /**
  321. Formats an integer into a string (like sprintf in C)
  322. @param x the number to format
  323. @return the formatted string
  324. */
  325. public String format(int x)
  326. {
  327. long lx = x;
  328. if (fmt == 'o' || fmt == 'x' || fmt == 'X')
  329. lx &= 0xFFFFFFFFL;
  330. return format(lx);
  331. }
  332. /**
  333. Formats a long integer into a string (like sprintf in C)
  334. @param x the number to format
  335. @return the formatted string
  336. */
  337. public String format(long x)
  338. {
  339. String r;
  340. int s = 0;
  341. if (fmt == 'd' || fmt == 'i')
  342. {
  343. if (x < 0)
  344. {
  345. r = ("" + x).substring(1);
  346. s = -1;
  347. }
  348. else
  349. {
  350. r = "" + x;
  351. s = 1;
  352. }
  353. }
  354. else if (fmt == 'o')
  355. r = convert(x, 3, 7, "01234567");
  356. else if (fmt == 'x')
  357. r = convert(x, 4, 15, "0123456789abcdef");
  358. else if (fmt == 'X')
  359. r = convert(x, 4, 15, "0123456789ABCDEF");
  360. else throw new java.lang.IllegalArgumentException();
  361. return pad(sign(s, r));
  362. }
  363. /**
  364. Formats a character into a string (like sprintf in C)
  365. @param x the value to format
  366. @return the formatted string
  367. */
  368. public String format(char c)
  369. {
  370. if (fmt != 'c')
  371. throw new java.lang.IllegalArgumentException();
  372. String r = "" + c;
  373. return pad(r);
  374. }
  375. /**
  376. Formats a string into a larger string (like sprintf in C)
  377. @param x the value to format
  378. @return the formatted string
  379. */
  380. public String format(String s)
  381. {
  382. if (fmt != 's')
  383. throw new java.lang.IllegalArgumentException();
  384. if (precision >= 0 && precision < s.length())
  385. s = s.substring(0, precision);
  386. return pad(s);
  387. }
  388. /**
  389. a test stub for the format class
  390. */
  391. public static void main(String[] a)
  392. {
  393. double x = 1.23456789012;
  394. double y = 123;
  395. double z = 1.2345e30;
  396. double w = 1.02;
  397. double u = 1.234e-5;
  398. double v = 10.0;
  399. int d = 0xCAFE;
  400. Format.printf("x = |%f|\n", x);
  401. Format.printf("u = |%20f|\n", u);
  402. Format.printf("x = |% .5f|\n", x);
  403. Format.printf("w = |%20.5f|\n", w);
  404. Format.printf("x = |%020.5f|\n", x);
  405. Format.printf("x = |%+20.5f|\n", x);
  406. Format.printf("x = |%+020.5f|\n", x);
  407. Format.printf("x = |% 020.5f|\n", x);
  408. Format.printf("y = |%#+20.5f|\n", y);
  409. Format.printf("y = |%-+20.5f|\n", y);
  410. Format.printf("z = |%20.5f|\n", z);
  411. Format.printf("x = |%e|\n", x);
  412. Format.printf("u = |%20e|\n", u);
  413. Format.printf("x = |% .5e|\n", x);
  414. Format.printf("w = |%20.5e|\n", w);
  415. Format.printf("x = |%020.5e|\n", x);
  416. Format.printf("x = |%+20.5e|\n", x);
  417. Format.printf("x = |%+020.5e|\n", x);
  418. Format.printf("x = |% 020.5e|\n", x);
  419. Format.printf("y = |%#+20.5e|\n", y);
  420. Format.printf("y = |%-+20.5e|\n", y);
  421. Format.printf("v = |%12.5e|\n", v);
  422. Format.printf("x = |%g|\n", x);
  423. Format.printf("z = |%g|\n", z);
  424. Format.printf("w = |%g|\n", w);
  425. Format.printf("u = |%g|\n", u);
  426. Format.printf("y = |%.2g|\n", y);
  427. Format.printf("y = |%#.2g|\n", y);
  428. Format.printf("d = |%d|\n", d);
  429. Format.printf("d = |%20d|\n", d);
  430. Format.printf("d = |%020d|\n", d);
  431. Format.printf("d = |%+20d|\n", d);
  432. Format.printf("d = |% 020d|\n", d);
  433. Format.printf("d = |%-20d|\n", d);
  434. Format.printf("d = |%20.8d|\n", d);
  435. Format.printf("d = |%x|\n", d);
  436. Format.printf("d = |%20X|\n", d);
  437. Format.printf("d = |%#20x|\n", d);
  438. Format.printf("d = |%020X|\n", d);
  439. Format.printf("d = |%20.8x|\n", d);
  440. Format.printf("d = |%o|\n", d);
  441. Format.printf("d = |%020o|\n", d);
  442. Format.printf("d = |%#20o|\n", d);
  443. Format.printf("d = |%#020o|\n", d);
  444. Format.printf("d = |%20.12o|\n", d);
  445. Format.printf("s = |%-20s|\n", "Hello");
  446. Format.printf("s = |%-20c|\n", '!');
  447. // regression test to confirm fix of reported bugs
  448. Format.printf("|%i|\n", Long.MIN_VALUE);
  449. Format.printf("|%6.2e|\n", 0.0);
  450. Format.printf("|%6.2g|\n", 0.0);
  451. Format.printf("|%6.2f|\n", 9.99);
  452. Format.printf("|%6.2f|\n", 9.999);
  453. Format.printf("|%.2f|\n", 1.999);
  454. Format.printf("|%6.0f|\n", 9.999);
  455. Format.printf("|%20.10s|\n", "Hello");
  456. d = -1;
  457. Format.printf("-1 = |%X|\n", d);
  458. Format.printf("100 = |%e|\n", 100.0); // 2000-06-09
  459. Format.printf("1/0 = |%f|\n", 1.0 / 0.0);
  460. Format.printf("-1/0 = |%e|\n", -1.0 / 0.0);
  461. Format.printf("0/0 = |%g|\n", 0.0 / 0.0);
  462. }
  463. private static String repeat(char c, int n)
  464. {
  465. if (n <= 0) return "";
  466. StringBuffer s = new StringBuffer(n);
  467. for (int i = 0; i < n; i++) s.append(c);
  468. return s.toString();
  469. }
  470. private static String convert(long x, int n, int m, String d)
  471. {
  472. if (x == 0) return "0";
  473. String r = "";
  474. while (x != 0)
  475. {
  476. r = d.charAt((int)(x & m)) + r;
  477. x = x >>> n;
  478. }
  479. return r;
  480. }
  481. private String pad(String r)
  482. {
  483. String p = repeat(' ', width - r.length());
  484. if (leftAlign) return pre + r + p + post;
  485. else return pre + p + r + post;
  486. }
  487. private String sign(int s, String r)
  488. {
  489. String p = "";
  490. if (s < 0) p = "-";
  491. else if (s > 0)
  492. {
  493. if (showPlus) p = "+";
  494. else if (showSpace) p = " ";
  495. }
  496. else
  497. {
  498. if (fmt == 'o' && alternate && r.length() > 0 && r.charAt(0) != '0') p = "0";
  499. else if (fmt == 'x' && alternate) p = "0x";
  500. else if (fmt == 'X' && alternate) p = "0X";
  501. }
  502. int w = 0;
  503. if (leadingZeroes)
  504. w = width;
  505. else if ((fmt == 'd' || fmt == 'i' || fmt == 'x' || fmt == 'X' || fmt == 'o')
  506. && precision > 0) w = precision;
  507. return p + repeat('0', w - p.length() - r.length()) + r;
  508. }
  509. private String fixedFormat(double d)
  510. {
  511. boolean removeTrailing
  512. = (fmt == 'G' || fmt == 'g') && !alternate;
  513. // remove trailing zeroes and decimal point
  514. if (d > 0x7FFFFFFFFFFFFFFFL) return expFormat(d);
  515. if (precision == 0)
  516. return (long)(d + 0.5) + (removeTrailing ? "" : ".");
  517. long whole = (long)d;
  518. double fr = d - whole; // fractional part
  519. if (fr >= 1 || fr < 0) return expFormat(d);
  520. double factor = 1;
  521. String leadingZeroes = "";
  522. for (int i = 1; i <= precision && factor <= 0x7FFFFFFFFFFFFFFFL; i++)
  523. {
  524. factor *= 10;
  525. leadingZeroes = leadingZeroes + "0";
  526. }
  527. long l = (long) (factor * fr + 0.5);
  528. if (l >= factor) { l = 0; whole++; } // CSH 10-25-97
  529. String z = leadingZeroes + l;
  530. z = "." + z.substring(z.length() - precision, z.length());
  531. if (removeTrailing)
  532. {
  533. int t = z.length() - 1;
  534. while (t >= 0 && z.charAt(t) == '0') t--;
  535. if (t >= 0 && z.charAt(t) == '.') t--;
  536. z = z.substring(0, t + 1);
  537. }
  538. return whole + z;
  539. }
  540. private String expFormat(double d)
  541. {
  542. String f = "";
  543. int e = 0;
  544. double dd = d;
  545. double factor = 1;
  546. if (d != 0)
  547. {
  548. while (dd >= 10) { e++; factor /= 10; dd = dd / 10; } // 2000-06-09
  549. while (dd < 1) { e--; factor *= 10; dd = dd * 10; }
  550. }
  551. if ((fmt == 'g' || fmt == 'G') && e >= -4 && e < precision)
  552. return fixedFormat(d);
  553. d = d * factor;
  554. f = f + fixedFormat(d);
  555. if (fmt == 'e' || fmt == 'g')
  556. f = f + "e";
  557. else
  558. f = f + "E";
  559. String p = "000";
  560. if (e >= 0)
  561. {
  562. f = f + "+";
  563. p = p + e;
  564. }
  565. else
  566. {
  567. f = f + "-";
  568. p = p + (-e);
  569. }
  570. return f + p.substring(p.length() - 3, p.length());
  571. }
  572. private int width;
  573. private int precision;
  574. private String pre;
  575. private String post;
  576. private boolean leadingZeroes;
  577. private boolean showPlus;
  578. private boolean alternate;
  579. private boolean showSpace;
  580. private boolean leftAlign;
  581. private char fmt; // one of cdeEfgGiosxXos
  582. }