1 3 package jodd.format; 4 5 import java.math.BigInteger ; 6 7 10 public class PrintfFormat { 11 12 protected int width; 13 protected int precision; 14 protected StringBuffer pre; 15 protected StringBuffer post; 16 protected boolean leadingZeroes; 17 protected boolean showPlus; 18 protected boolean alternate; 19 protected boolean showSpace; 20 protected boolean leftAlign; 21 protected boolean groupDigits; 22 protected char fmt; protected boolean countSignInLen; 24 private final static BigInteger bgInt = new BigInteger ("9223372036854775808"); 26 74 public PrintfFormat(String s) { 75 init(s, 0); 76 } 77 78 81 protected PrintfFormat() { 82 } 83 84 protected PrintfFormat reinit(String s) { 85 if (pre == null) { 86 init(s, 0); 87 } else { 88 init(s, pre.length()); 89 } 90 return this; 91 } 92 93 protected void init(String s, int i) { 94 width = 0; 95 precision = -1; 96 pre = (i == 0 ? new StringBuffer () : new StringBuffer (s.substring(0, i))); 97 post = new StringBuffer (); 98 leadingZeroes = false; 99 showPlus = false; 100 alternate = false; 101 showSpace = false; 102 leftAlign = false; 103 countSignInLen = true; 104 fmt = ' '; 105 106 int length = s.length(); 107 int parseState; 109 while (true) { 111 if (i >= length) { 112 throw new IllegalArgumentException ("Format string requires '%'."); 113 } 114 char c = s.charAt(i); 115 if (c != '%') { 116 pre.append(c); 117 i++; 118 continue; 119 } 120 if (i >= length - 1) { 121 throw new IllegalArgumentException ("Format string can not end with '%'."); 122 } 123 if (s.charAt(i + 1) == '%') { pre.append('%'); 125 i += 2; 126 continue; 127 } 128 parseState = 1; i++; 130 break; 131 } 132 133 flagsloop: 135 while (parseState == 1) { 136 if (i >= length) { 137 parseState = 5; 138 break; 139 } 140 char c = s.charAt(i); 141 switch (c) { 142 case ' ': showSpace = true; break; 143 case '-': leftAlign = true; break; 144 case '+': showPlus = true; break; 145 case '0': leadingZeroes = true; break; 146 case '#': alternate = true; break; 147 case '~': countSignInLen = false; break; 148 case ',': groupDigits = true; break; 149 default: 150 parseState = 2; 151 break flagsloop; 152 } 153 i++; 154 } 155 156 while (parseState == 2) { 158 if (i >= length) { 159 parseState = 5; 160 break; 161 } 162 char c = s.charAt(i); 163 if (('0' <= c) && (c <= '9')) { 164 width = (width * 10) + s.charAt(i) - '0'; 165 i++; 166 continue; 167 } 168 if (s.charAt(i) == '.') { 169 parseState = 3; 170 precision = 0; 171 i++; 172 } else { 173 parseState = 4; 174 } 175 break; 176 } 177 178 while (parseState == 3) { 180 if (i >= length) { 181 parseState = 5; 182 break; 183 } 184 char c = s.charAt(i); 185 if (('0' <= c) && (c <= '9')) { 186 precision = (precision * 10) + s.charAt(i) - '0'; 187 i++; 188 continue; 189 } 190 parseState = 4; 191 break; 192 } 193 194 if (parseState == 4) { 196 if (i < length) { 197 fmt = s.charAt(i); 198 i++; 199 } 202 } 203 204 if (i < length) { 206 post.append(s.substring(i, length)); 207 } 208 } 209 210 213 protected String expFormat(double d) { 214 StringBuffer f = new StringBuffer (); 215 int e = 0; 216 double dd = d; 217 double factor = 1; 218 219 if (d != 0) { 220 while (dd > 10) { 221 e++; 222 factor /= 10; 223 dd /= 10; 224 } 225 while (dd < 1) { 226 e--; 227 factor *= 10; 228 dd *= 10; 229 } 230 } 231 if (((fmt == 'g') || (fmt == 'G')) && (e >= -4) && (e < precision)) { 232 return fixedFormat(d); 233 } 234 235 d *= factor; 236 f.append(fixedFormat(d)); 237 238 if (fmt == 'e' || fmt == 'g') { 239 f.append('e'); 240 } else { 241 f.append('E'); 242 } 243 244 StringBuffer p = new StringBuffer ("000"); 245 if (e >= 0) { 246 f.append('+'); 247 p.append(e); 248 } else { 249 f.append('-'); 250 p.append(-e); 251 } 252 253 char[] data = new char[3]; 254 p.getChars(p.length() - 3, p.length(), data, 0); 255 return f.append(data).toString(); 256 } 257 258 261 protected String fixedFormat(double d) { 262 boolean removeTrailing = (fmt == 'G' || fmt == 'g') && !alternate; 263 264 if (d > 0x7FFFFFFFFFFFFFFFL) { 266 return expFormat(d); 267 } 268 if (precision == 0) { 269 return (long) (d ) + (removeTrailing ? "" : "."); } 271 272 long whole = (long) d; 273 double fr = d - whole; 275 if (fr >= 1 || fr < 0) { 276 return expFormat(d); 277 } 278 279 double factor = 1; 280 StringBuffer leadingZeroesStr = new StringBuffer (); 281 282 for (int i = 1; i <= precision && factor <= 0x7FFFFFFFFFFFFFFFL; i++) { 283 factor *= 10; 284 leadingZeroesStr.append('0'); 285 } 286 287 long l = (long) (factor * fr ); if (l >= factor) { 289 l = 0; 290 whole++; 291 } 292 293 String z = leadingZeroesStr.toString() + l; 294 z = '.' + z.substring(z.length() - precision, z.length()); 295 296 if (removeTrailing) { 297 int t = z.length() - 1; 298 while (t >= 0 && z.charAt(t) == '0') { 299 t--; 300 } 301 if (t >= 0 && z.charAt(t) == '.') { 302 t--; 303 } 304 z = z.substring(0, t + 1); 305 } 306 return whole + z; 307 } 308 309 312 protected String pad(String value) { 313 String spaces = repeat(' ', width - value.length()); 314 if (leftAlign) { 315 return pre + value + spaces + post; 316 } else { 317 return pre + spaces + value + post; 318 } 319 } 320 321 324 protected static String repeat(char c, int n) { 325 if (n <= 0) { 326 return (""); 327 } 328 char[] buffer = new char[n]; 329 for (int i = 0; i < n; i++) { 330 buffer[i] = c; 331 } 332 return new String (buffer); 333 } 334 335 protected String sign(int s, String r) { 336 String p = ""; 337 338 if (s < 0) { 339 p = "-"; 340 } else if (s > 0) { 341 if (showPlus) { 342 p = "+"; 343 } else if (showSpace) { 344 p = " "; 345 } 346 } else { 347 if (fmt == 'o' && alternate && r.length() > 0 && r.charAt(0) != '0') { 348 p = "0"; 349 } else if (fmt == 'x' && alternate) { 350 p = "0x"; 351 } else if (fmt == 'X' && alternate) { 352 p = "0X"; 353 } 354 } 355 356 int w = 0; 357 358 if (leadingZeroes) { 359 w = width; 360 } else if ((fmt == 'u' || fmt == 'd' || fmt == 'i' || fmt == 'x' || fmt == 'X' || fmt == 'o') && precision > 0) { 361 w = precision; 362 } 363 364 if (countSignInLen) { 365 return p + repeat('0', w - p.length() - r.length()) + r; 366 } else { 367 return p + repeat('0', w - r.length()) + r; 368 } 369 } 370 371 375 protected String groupDigits(String value, int size, char separator) { 376 if (groupDigits == false) { 377 return value; 378 } 379 StringBuffer r = new StringBuffer (value.length() + 10); 380 int ndx = 0; 381 int len = value.length() - 1; 382 int mod = len % size; 383 while (ndx < len) { 384 r.append(value.charAt(ndx)); 385 if (mod == 0) { 386 r.append(separator); 387 mod = size; 388 } 389 mod--; 390 ndx++; 391 } 392 r.append(value.charAt(ndx)); 393 return r.toString(); 394 } 395 396 397 398 400 403 public String form(char value) { 404 if (fmt != 'c') { 405 throw new IllegalArgumentException ("Invalid character format: '" + fmt + "' is not 'c'."); 406 } 407 return pad(String.valueOf(value)); 408 } 409 410 413 public String form(boolean value) { 414 if (fmt == 'l') { 415 return pad(value ? "true" : "false"); 416 } 417 if (fmt == 'L') { 418 return pad(value ? "TRUE" : "FALSE"); 419 } 420 throw new IllegalArgumentException ("Invalid boolean format: '" + fmt + "' is not one of 'bB'."); 421 422 } 423 424 427 public String form(double x) { 428 String r; 429 430 if (precision < 0) { 431 precision = 6; 432 } 433 434 int s = 1; 435 if (x < 0) { 436 x = -x; 437 s = -1; 438 } 439 if (fmt == 'f') { 440 r = fixedFormat(x); 441 } else if (fmt == 'e' || fmt == 'E' || fmt == 'g' || fmt == 'G') { 442 r = expFormat(x); 443 } else { 444 throw new IllegalArgumentException ("Invalid floating format: '" + fmt + "' is not one of 'feEgG'."); 445 } 446 return pad(sign(s, r)); 447 } 448 449 452 public String form(long x) { 453 String r; 454 int s = 0; 455 456 switch (fmt) { 457 case 'd': 458 if (x < 0) { 459 r = Long.toString(x).substring(1); 460 s = -1; 461 } else { 462 r = Long.toString(x); 463 s = 1; 464 } 465 r = groupDigits(r, 3, ','); 466 break; 467 case 'i': 468 int xx = (int) x; 469 if (xx < 0) { 470 r = Integer.toString(xx).substring(1); 471 s = -1; 472 } else { 473 r = Integer.toString(xx); 474 s = 1; 475 } 476 r = groupDigits(r, 3, ','); 477 break; 478 case 'u': 479 if (x < 0) { 480 long xl = x & 0x7FFFFFFFFFFFFFFFL; 481 r = Long.toString(xl); 482 BigInteger bi = new BigInteger (r); 483 r = bi.add(bgInt).toString(); 484 } else { 485 r = Long.toString(x); 486 } 487 r = groupDigits(r, 3, ','); 488 s = 1; 489 break; 490 case 'o': 491 r = Long.toOctalString(x); 492 break; 493 case 'x': 494 r = Long.toHexString(x); 495 r = groupDigits(r, 4, ' '); 496 break; 497 case 'X': 498 r = Long.toHexString(x).toUpperCase(); 499 r = groupDigits(r, 4, ' '); 500 break; 501 case 'b': 502 r = Long.toBinaryString(x); 503 r = groupDigits(r, 8, ' '); 504 break; 505 case 'l': 506 r = (x == 0 ? "false" : "true"); 507 break; 508 case 'L': 509 r = (x == 0 ? "FALSE" : "TRUE"); 510 break; 511 default: 512 throw new IllegalArgumentException ("Invalid long format: '" + fmt + "' is not one of 'diuoxXblL'."); 513 } 514 515 return pad(sign(s, r)); 516 } 517 518 521 public String form(int x) { 522 String r; 523 int s = 0; 524 525 switch (fmt) { 526 case 'd': 527 case 'i': 528 if (x < 0) { 529 r = Integer.toString(x).substring(1); 530 s = -1; 531 } else { 532 r = Integer.toString(x); 533 s = 1; 534 } 535 r = groupDigits(r, 3, ','); 536 break; 537 case 'u': 538 long xl = x & 0x00000000FFFFFFFFL; 539 r = Long.toString(xl); 540 r = groupDigits(r, 3, ','); 541 s = 1; 542 break; 543 case 'o': 544 r = Integer.toOctalString(x); 545 break; 546 case 'x': 547 r = Integer.toHexString(x); 548 r = groupDigits(r, 4, ' '); 549 break; 550 case 'X': 551 r = Integer.toHexString(x).toUpperCase(); 552 r = groupDigits(r, 4, ' '); 553 break; 554 case 'b': 555 r = Integer.toBinaryString(x); 556 r = groupDigits(r, 8, ' '); 557 break; 558 case 'l': 559 r = (x == 0 ? "false" : "true"); 560 break; 561 case 'L': 562 r = (x == 0 ? "FALSE" : "TRUE"); 563 break; 564 default: 565 throw new IllegalArgumentException ("Invalid int format: '" + fmt + "' is not one of 'diuoxXblL'."); 566 } 567 return pad(sign(s, r)); 568 } 569 570 573 public String form(String s) { 574 if (fmt != 's') { 575 throw new IllegalArgumentException ("Invalid long format: '" + fmt + "' is not 's'."); 576 } 577 if (precision >= 0 && precision < s.length()) { 578 s = s.substring(0, precision); 579 } 580 581 return pad(s); 582 } 583 584 585 } 586 | Popular Tags |