1 7 8 package java.util; 9 10 import java.io.BufferedWriter ; 11 import java.io.Closeable ; 12 import java.io.IOException ; 13 import java.io.File ; 14 import java.io.FileOutputStream ; 15 import java.io.FileNotFoundException ; 16 import java.io.Flushable ; 17 import java.io.OutputStream ; 18 import java.io.OutputStreamWriter ; 19 import java.io.PrintStream ; 20 import java.io.UnsupportedEncodingException ; 21 import java.math.BigDecimal ; 22 import java.math.BigInteger ; 23 import java.math.MathContext ; 24 import java.nio.charset.Charset ; 25 import java.text.DateFormatSymbols ; 26 import java.text.DecimalFormat ; 27 import java.text.DecimalFormatSymbols ; 28 import java.text.NumberFormat ; 29 import java.util.Calendar ; 30 import java.util.Date ; 31 import java.util.Locale ; 32 import java.util.regex.Matcher ; 33 import java.util.regex.Pattern ; 34 35 import sun.misc.FpUtils; 36 import sun.misc.DoubleConsts; 37 import sun.misc.FormattedFloatingDecimal; 38 39 1804public final class Formatter implements Closeable , Flushable { 1805 private Appendable a; 1806 private Locale l; 1807 1808 private IOException lastException; 1809 1810 private char zero = '0'; 1811 private static double scaleUp; 1812 1813 private static final int MAX_FD_CHARS = 30; 1816 1817 private void init(Appendable a, Locale l) { 1819 this.a = a; 1820 this.l = l; 1821 setZero(); 1822 } 1823 1824 1834 public Formatter() { 1835 init(new StringBuilder (), Locale.getDefault()); 1836 } 1837 1838 1848 public Formatter(Appendable a) { 1849 init(a, Locale.getDefault()); 1850 } 1851 1852 1865 public Formatter(Locale l) { 1866 init(new StringBuilder (), l); 1867 } 1868 1869 1881 public Formatter(Appendable a, Locale l) { 1882 if (a == null) 1883 a = new StringBuilder (); 1884 init(a, l); 1885 } 1886 1887 1914 public Formatter(String fileName) throws FileNotFoundException { 1915 init(new BufferedWriter (new OutputStreamWriter (new FileOutputStream (fileName))), 1916 Locale.getDefault()); 1917 } 1918 1919 1949 public Formatter(String fileName, String csn) 1950 throws FileNotFoundException , UnsupportedEncodingException 1951 { 1952 this(fileName, csn, Locale.getDefault()); 1953 } 1954 1955 1988 public Formatter(String fileName, String csn, Locale l) 1989 throws FileNotFoundException , UnsupportedEncodingException 1990 { 1991 init(new BufferedWriter (new OutputStreamWriter (new FileOutputStream (fileName), csn)), 1992 l); 1993 } 1994 1995 2022 public Formatter(File file) throws FileNotFoundException { 2023 init(new BufferedWriter (new OutputStreamWriter (new FileOutputStream (file))), 2024 Locale.getDefault()); 2025 } 2026 2027 2057 public Formatter(File file, String csn) 2058 throws FileNotFoundException , UnsupportedEncodingException 2059 { 2060 this(file, csn, Locale.getDefault()); 2061 } 2062 2063 2096 public Formatter(File file, String csn, Locale l) 2097 throws FileNotFoundException , UnsupportedEncodingException 2098 { 2099 init(new BufferedWriter (new OutputStreamWriter (new FileOutputStream (file), csn)), 2100 l); 2101 } 2102 2103 2116 public Formatter(PrintStream ps) { 2117 if (ps == null) 2118 throw new NullPointerException (); 2119 init((Appendable )ps, Locale.getDefault()); 2120 } 2121 2122 2136 public Formatter(OutputStream os) { 2137 init(new BufferedWriter (new OutputStreamWriter (os)), 2138 Locale.getDefault()); 2139 } 2140 2141 2159 public Formatter(OutputStream os, String csn) 2160 throws UnsupportedEncodingException 2161 { 2162 this(os, csn, Locale.getDefault()); 2163 } 2164 2165 2185 public Formatter(OutputStream os, String csn, Locale l) 2186 throws UnsupportedEncodingException 2187 { 2188 init(new BufferedWriter (new OutputStreamWriter (os, csn)), l); 2189 } 2190 2191 private void setZero() { 2192 if ((l != null) && !l.equals(Locale.US)) { 2193 DecimalFormatSymbols dfs = new DecimalFormatSymbols (l); 2194 zero = dfs.getZeroDigit(); 2195 } 2196 } 2197 2198 2211 public Locale locale() { 2212 ensureOpen(); 2213 return l; 2214 } 2215 2216 2225 public Appendable out() { 2226 ensureOpen(); 2227 return a; 2228 } 2229 2230 2261 public String toString() { 2262 ensureOpen(); 2263 return a.toString(); 2264 } 2265 2266 2277 public void flush() { 2278 ensureOpen(); 2279 if (a instanceof Flushable ) { 2280 try { 2281 ((Flushable )a).flush(); 2282 } catch (IOException ioe) { 2283 lastException = ioe; 2284 } 2285 } 2286 } 2287 2288 2300 public void close() { 2301 if (a == null) 2302 return; 2303 try { 2304 if (a instanceof Closeable ) 2305 ((Closeable )a).close(); 2306 } catch (IOException ioe) { 2307 lastException = ioe; 2308 } finally { 2309 a = null; 2310 } 2311 } 2312 2313 private void ensureOpen() { 2314 if (a == null) 2315 throw new FormatterClosedException (); 2316 } 2317 2318 2328 public IOException ioException() { 2329 return lastException; 2330 } 2331 2332 2363 public Formatter format(String format, Object ... args) { 2364 return format(l, format, args); 2365 } 2366 2367 2403 public Formatter format(Locale l, String format, Object ... args) { 2404 ensureOpen(); 2405 2406 int last = -1; 2408 int lasto = -1; 2410 2411 FormatString[] fsa = parse(format); 2412 for (int i = 0; i < fsa.length; i++) { 2413 FormatString fs = fsa[i]; 2414 int index = fs.index(); 2415 try { 2416 switch (index) { 2417 case -2: fs.print(null, l); 2419 break; 2420 case -1: if (last < 0 || (args != null && last > args.length - 1)) 2422 throw new MissingFormatArgumentException (fs.toString()); 2423 fs.print((args == null ? null : args[last]), l); 2424 break; 2425 case 0: lasto++; 2427 last = lasto; 2428 if (args != null && lasto > args.length - 1) 2429 throw new MissingFormatArgumentException (fs.toString()); 2430 fs.print((args == null ? null : args[lasto]), l); 2431 break; 2432 default: last = index - 1; 2434 if (args != null && last > args.length - 1) 2435 throw new MissingFormatArgumentException (fs.toString()); 2436 fs.print((args == null ? null : args[last]), l); 2437 break; 2438 } 2439 } catch (IOException x) { 2440 lastException = x; 2441 } 2442 } 2443 return this; 2444 } 2445 2446 private static final String formatSpecifier 2448 = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])"; 2449 2450 private static Pattern fsPattern = Pattern.compile(formatSpecifier); 2451 2452 private FormatString[] parse(String s) { 2454 ArrayList al = new ArrayList (); 2455 Matcher m = fsPattern.matcher(s); 2456 int i = 0; 2457 while (i < s.length()) { 2458 if (m.find(i)) { 2459 if (m.start() != i) { 2463 checkText(s.substring(i, m.start())); 2465 al.add(new FixedString(s.substring(i, m.start()))); 2467 } 2468 2469 String [] sa = new String [6]; 2471 for (int j = 0; j < m.groupCount(); j++) 2472 { 2473 sa[j] = m.group(j + 1); 2474 } 2476 al.add(new FormatSpecifier(this, sa)); 2478 i = m.end(); 2479 } else { 2480 checkText(s.substring(i)); 2483 al.add(new FixedString(s.substring(i))); 2485 break; 2486 } 2487 } 2488 return (FormatString[]) al.toArray(new FormatString[0]); 2492 } 2493 2494 private void checkText(String s) { 2495 int idx; 2496 if ((idx = s.indexOf('%')) != -1) { 2499 char c = (idx > s.length() - 2 ? '%' : s.charAt(idx + 1)); 2500 throw new UnknownFormatConversionException (String.valueOf(c)); 2501 } 2502 } 2503 2504 private interface FormatString { 2505 int index(); 2506 void print(Object arg, Locale l) throws IOException ; 2507 String toString(); 2508 } 2509 2510 private class FixedString implements FormatString { 2511 private String s; 2512 FixedString(String s) { this.s = s; } 2513 public int index() { return -2; } 2514 public void print(Object arg, Locale l) 2515 throws IOException { a.append(s); } 2516 public String toString() { return s; } 2517 } 2518 2519 public enum BigDecimalLayoutForm { SCIENTIFIC, DECIMAL_FLOAT }; 2520 2521 private class FormatSpecifier implements FormatString { 2522 private int index = -1; 2523 private Flags f = Flags.NONE; 2524 private int width; 2525 private int precision; 2526 private boolean dt = false; 2527 private char c; 2528 2529 private Formatter formatter; 2530 2531 private String ls; 2533 2534 private int index(String s) { 2535 if (s != null) { 2536 try { 2537 index = Integer.parseInt(s.substring(0, s.length() - 1)); 2538 } catch (NumberFormatException x) { 2539 assert(false); 2540 } 2541 } else { 2542 index = 0; 2543 } 2544 return index; 2545 } 2546 2547 public int index() { 2548 return index; 2549 } 2550 2551 private Flags flags(String s) { 2552 f = Flags.parse(s); 2553 if (f.contains(Flags.PREVIOUS)) 2554 index = -1; 2555 return f; 2556 } 2557 2558 Flags flags() { 2559 return f; 2560 } 2561 2562 private int width(String s) { 2563 width = -1; 2564 if (s != null) { 2565 try { 2566 width = Integer.parseInt(s); 2567 if (width < 0) 2568 throw new IllegalFormatWidthException (width); 2569 } catch (NumberFormatException x) { 2570 assert(false); 2571 } 2572 } 2573 return width; 2574 } 2575 2576 int width() { 2577 return width; 2578 } 2579 2580 private int precision(String s) { 2581 precision = -1; 2582 if (s != null) { 2583 try { 2584 precision = Integer.parseInt(s.substring(1)); 2586 if (precision < 0) 2587 throw new IllegalFormatPrecisionException (precision); 2588 } catch (NumberFormatException x) { 2589 assert(false); 2590 } 2591 } 2592 return precision; 2593 } 2594 2595 int precision() { 2596 return precision; 2597 } 2598 2599 private char conversion(String s) { 2600 c = s.charAt(0); 2601 if (!dt) { 2602 if (!Conversion.isValid(c)) 2603 throw new UnknownFormatConversionException (String.valueOf(c)); 2604 if (Character.isUpperCase(c)) 2605 f.add(Flags.UPPERCASE); 2606 c = Character.toLowerCase(c); 2607 if (Conversion.isText(c)) 2608 index = -2; 2609 } 2610 return c; 2611 } 2612 2613 private char conversion() { 2614 return c; 2615 } 2616 2617 FormatSpecifier(Formatter formatter, String [] sa) { 2618 this.formatter = formatter; 2619 int idx = 0; 2620 2621 index(sa[idx++]); 2622 flags(sa[idx++]); 2623 width(sa[idx++]); 2624 precision(sa[idx++]); 2625 2626 if (sa[idx] != null) { 2627 dt = true; 2628 if (sa[idx].equals("T")) 2629 f.add(Flags.UPPERCASE); 2630 } 2631 conversion(sa[++idx]); 2632 2633 if (dt) 2634 checkDateTime(); 2635 else if (Conversion.isGeneral(c)) 2636 checkGeneral(); 2637 else if (c == Conversion.CHARACTER) 2638 checkCharacter(); 2639 else if (Conversion.isInteger(c)) 2640 checkInteger(); 2641 else if (Conversion.isFloat(c)) 2642 checkFloat(); 2643 else if (Conversion.isText(c)) 2644 checkText(); 2645 else 2646 throw new UnknownFormatConversionException (String.valueOf(c)); 2647 } 2648 2649 public void print(Object arg, Locale l) throws IOException { 2650 if (dt) { 2651 printDateTime(arg, l); 2652 return; 2653 } 2654 switch(c) { 2655 case Conversion.DECIMAL_INTEGER: 2656 case Conversion.OCTAL_INTEGER: 2657 case Conversion.HEXADECIMAL_INTEGER: 2658 printInteger(arg, l); 2659 break; 2660 case Conversion.SCIENTIFIC: 2661 case Conversion.GENERAL: 2662 case Conversion.DECIMAL_FLOAT: 2663 case Conversion.HEXADECIMAL_FLOAT: 2664 printFloat(arg, l); 2665 break; 2666 case Conversion.CHARACTER: 2667 printCharacter(arg); 2668 break; 2669 case Conversion.BOOLEAN: 2670 printBoolean(arg); 2671 break; 2672 case Conversion.STRING: 2673 printString(arg, l); 2674 break; 2675 case Conversion.HASHCODE: 2676 printHashCode(arg); 2677 break; 2678 case Conversion.LINE_SEPARATOR: 2679 if (ls == null) 2680 ls = System.getProperty("line.separator"); 2681 a.append(ls); 2682 break; 2683 case Conversion.PERCENT_SIGN: 2684 a.append('%'); 2685 break; 2686 default: 2687 assert false; 2688 } 2689 } 2690 2691 private void printInteger(Object arg, Locale l) throws IOException { 2692 if (arg == null) 2693 print("null"); 2694 else if (arg instanceof Byte ) 2695 print(((Byte )arg).byteValue(), l); 2696 else if (arg instanceof Short ) 2697 print(((Short )arg).shortValue(), l); 2698 else if (arg instanceof Integer ) 2699 print(((Integer )arg).intValue(), l); 2700 else if (arg instanceof Long ) 2701 print(((Long )arg).longValue(), l); 2702 else if (arg instanceof BigInteger ) 2703 print(((BigInteger )arg), l); 2704 else 2705 failConversion(c, arg); 2706 } 2707 2708 private void printFloat(Object arg, Locale l) throws IOException { 2709 if (arg == null) 2710 print("null"); 2711 else if (arg instanceof Float ) 2712 print(((Float )arg).floatValue(), l); 2713 else if (arg instanceof Double ) 2714 print(((Double )arg).doubleValue(), l); 2715 else if (arg instanceof BigDecimal ) 2716 print(((BigDecimal )arg), l); 2717 else 2718 failConversion(c, arg); 2719 } 2720 2721 private void printDateTime(Object arg, Locale l) throws IOException { 2722 if (arg == null) { 2723 print("null"); 2724 return; 2725 } 2726 Calendar cal = null; 2727 2728 if (arg instanceof Long ) { 2731 cal = Calendar.getInstance(l); 2734 cal.setTimeInMillis((Long )arg); 2735 } else if (arg instanceof Date ) { 2736 cal = Calendar.getInstance(l); 2739 cal.setTime((Date )arg); 2740 } else if (arg instanceof Calendar ) { 2741 cal = (Calendar ) ((Calendar )arg).clone(); 2742 cal.setLenient(true); 2743 } else { 2744 failConversion(c, arg); 2745 } 2746 print(cal, c, l); 2747 } 2748 2749 private void printCharacter(Object arg) throws IOException { 2750 if (arg == null) { 2751 print("null"); 2752 return; 2753 } 2754 String s = null; 2755 if (arg instanceof Character ) { 2756 s = ((Character )arg).toString(); 2757 } else if (arg instanceof Byte ) { 2758 byte i = ((Byte )arg).byteValue(); 2759 if (Character.isValidCodePoint(i)) 2760 s = new String (Character.toChars(i)); 2761 else 2762 throw new IllegalFormatCodePointException (i); 2763 } else if (arg instanceof Short ) { 2764 short i = ((Short )arg).shortValue(); 2765 if (Character.isValidCodePoint(i)) 2766 s = new String (Character.toChars(i)); 2767 else 2768 throw new IllegalFormatCodePointException (i); 2769 } else if (arg instanceof Integer ) { 2770 int i = ((Integer )arg).intValue(); 2771 if (Character.isValidCodePoint(i)) 2772 s = new String (Character.toChars(i)); 2773 else 2774 throw new IllegalFormatCodePointException (i); 2775 } else { 2776 failConversion(c, arg); 2777 } 2778 print(s); 2779 } 2780 2781 private void printString(Object arg, Locale l) throws IOException { 2782 if (arg == null) { 2783 print("null"); 2784 } else if (arg instanceof Formattable ) { 2785 Formatter fmt = formatter; 2786 if (formatter.locale() != l) 2787 fmt = new Formatter (formatter.out(), l); 2788 ((Formattable )arg).formatTo(fmt, f.valueOf(), width, precision); 2789 } else { 2790 print(arg.toString()); 2791 } 2792 } 2793 2794 private void printBoolean(Object arg) throws IOException { 2795 String s; 2796 if (arg != null) 2797 s = ((arg instanceof Boolean ) 2798 ? ((Boolean )arg).toString() 2799 : Boolean.toString(true)); 2800 else 2801 s = Boolean.toString(false); 2802 print(s); 2803 } 2804 2805 private void printHashCode(Object arg) throws IOException { 2806 String s = (arg == null 2807 ? "null" 2808 : Integer.toHexString(arg.hashCode())); 2809 print(s); 2810 } 2811 2812 private void print(String s) throws IOException { 2813 if (precision != -1 && precision < s.length()) 2814 s = s.substring(0, precision); 2815 if (f.contains(Flags.UPPERCASE)) 2816 s = s.toUpperCase(); 2817 a.append(justify(s)); 2818 } 2819 2820 private String justify(String s) { 2821 if (width == -1) 2822 return s; 2823 StringBuilder sb = new StringBuilder (); 2824 boolean pad = f.contains(Flags.LEFT_JUSTIFY); 2825 int sp = width - s.length(); 2826 if (!pad) 2827 for (int i = 0; i < sp; i++) sb.append(' '); 2828 sb.append(s); 2829 if (pad) 2830 for (int i = 0; i < sp; i++) sb.append(' '); 2831 return sb.toString(); 2832 } 2833 2834 public String toString() { 2835 StringBuilder sb = new StringBuilder ('%'); 2836 Flags dupf = f.dup().remove(Flags.UPPERCASE); 2838 sb.append(dupf.toString()); 2839 if (index > 0) 2840 sb.append(index).append('$'); 2841 if (width != -1) 2842 sb.append(width); 2843 if (precision != -1) 2844 sb.append('.').append(precision); 2845 if (dt) 2846 sb.append(f.contains(Flags.UPPERCASE) ? 'T' : 't'); 2847 sb.append(f.contains(Flags.UPPERCASE) 2848 ? Character.toUpperCase(c) : c); 2849 return sb.toString(); 2850 } 2851 2852 private void checkGeneral() { 2853 if ((c == Conversion.BOOLEAN || c == Conversion.HASHCODE) 2854 && f.contains(Flags.ALTERNATE)) 2855 failMismatch(Flags.ALTERNATE, c); 2856 if (width == -1 && f.contains(Flags.LEFT_JUSTIFY)) 2858 throw new MissingFormatWidthException (toString()); 2859 checkBadFlags(Flags.PLUS, Flags.LEADING_SPACE, Flags.ZERO_PAD, 2860 Flags.GROUP, Flags.PARENTHESES); 2861 } 2862 2863 private void checkDateTime() { 2864 if (precision != -1) 2865 throw new IllegalFormatPrecisionException (precision); 2866 if (!DateTime.isValid(c)) 2867 throw new UnknownFormatConversionException ("t" + c); 2868 checkBadFlags(Flags.ALTERNATE); 2869 if (width == -1 && f.contains(Flags.LEFT_JUSTIFY)) 2871 throw new MissingFormatWidthException (toString()); 2872 } 2873 2874 private void checkCharacter() { 2875 if (precision != -1) 2876 throw new IllegalFormatPrecisionException (precision); 2877 checkBadFlags(Flags.ALTERNATE); 2878 if (width == -1 && f.contains(Flags.LEFT_JUSTIFY)) 2880 throw new MissingFormatWidthException (toString()); 2881 } 2882 2883 private void checkInteger() { 2884 checkNumeric(); 2885 if (precision != -1) 2886 throw new IllegalFormatPrecisionException (precision); 2887 2888 if (c == Conversion.DECIMAL_INTEGER) 2889 checkBadFlags(Flags.ALTERNATE); 2890 else if (c == Conversion.OCTAL_INTEGER) 2891 checkBadFlags(Flags.GROUP); 2892 else 2893 checkBadFlags(Flags.GROUP); 2894 } 2895 2896 private void checkBadFlags(Flags ... badFlags) { 2897 for (int i = 0; i < badFlags.length; i++) 2898 if (f.contains(badFlags[i])) 2899 failMismatch(badFlags[i], c); 2900 } 2901 2902 private void checkFloat() { 2903 checkNumeric(); 2904 if (c == Conversion.DECIMAL_FLOAT) { 2905 } else if (c == Conversion.HEXADECIMAL_FLOAT) { 2906 checkBadFlags(Flags.PARENTHESES, Flags.GROUP); 2907 } else if (c == Conversion.SCIENTIFIC) { 2908 checkBadFlags(Flags.GROUP); 2909 } else if (c == Conversion.GENERAL) { 2910 checkBadFlags(Flags.ALTERNATE); 2911 } 2912 } 2913 2914 private void checkNumeric() { 2915 if (width != -1 && width < 0) 2916 throw new IllegalFormatWidthException (width); 2917 2918 if (precision != -1 && precision < 0) 2919 throw new IllegalFormatPrecisionException (precision); 2920 2921 if (width == -1 2923 && (f.contains(Flags.LEFT_JUSTIFY) || f.contains(Flags.ZERO_PAD))) 2924 throw new MissingFormatWidthException (toString()); 2925 2926 if ((f.contains(Flags.PLUS) && f.contains(Flags.LEADING_SPACE)) 2928 || (f.contains(Flags.LEFT_JUSTIFY) && f.contains(Flags.ZERO_PAD))) 2929 throw new IllegalFormatFlagsException (f.toString()); 2930 } 2931 2932 private void checkText() { 2933 if (precision != -1) 2934 throw new IllegalFormatPrecisionException (precision); 2935 switch (c) { 2936 case Conversion.PERCENT_SIGN: 2937 if (f.valueOf() != Flags.LEFT_JUSTIFY.valueOf() 2938 && f.valueOf() != Flags.NONE.valueOf()) 2939 throw new IllegalFormatFlagsException (f.toString()); 2940 if (width == -1 && f.contains(Flags.LEFT_JUSTIFY)) 2942 throw new MissingFormatWidthException (toString()); 2943 break; 2944 case Conversion.LINE_SEPARATOR: 2945 if (width != -1) 2946 throw new IllegalFormatWidthException (width); 2947 if (f.valueOf() != Flags.NONE.valueOf()) 2948 throw new IllegalFormatFlagsException (f.toString()); 2949 break; 2950 default: 2951 assert false; 2952 } 2953 } 2954 2955 private void print(byte value, Locale l) throws IOException { 2956 long v = value; 2957 if (value < 0 2958 && (c == Conversion.OCTAL_INTEGER 2959 || c == Conversion.HEXADECIMAL_INTEGER)) { 2960 v += (1L << 8); 2961 assert v >= 0 : v; 2962 } 2963 print(v, l); 2964 } 2965 2966 private void print(short value, Locale l) throws IOException { 2967 long v = value; 2968 if (value < 0 2969 && (c == Conversion.OCTAL_INTEGER 2970 || c == Conversion.HEXADECIMAL_INTEGER)) { 2971 v += (1L << 16); 2972 assert v >= 0 : v; 2973 } 2974 print(v, l); 2975 } 2976 2977 private void print(int value, Locale l) throws IOException { 2978 long v = value; 2979 if (value < 0 2980 && (c == Conversion.OCTAL_INTEGER 2981 || c == Conversion.HEXADECIMAL_INTEGER)) { 2982 v += (1L << 32); 2983 assert v >= 0 : v; 2984 } 2985 print(v, l); 2986 } 2987 2988 private void print(long value, Locale l) throws IOException { 2989 2990 StringBuilder sb = new StringBuilder (); 2991 2992 if (c == Conversion.DECIMAL_INTEGER) { 2993 boolean neg = value < 0; 2994 char[] va; 2995 if (value < 0) 2996 va = Long.toString(value, 10).substring(1).toCharArray(); 2997 else 2998 va = Long.toString(value, 10).toCharArray(); 2999 3000 leadingSign(sb, neg); 3002 3003 localizedMagnitude(sb, va, f, adjustWidth(width, f, neg), l); 3005 3006 trailingSign(sb, neg); 3008 } else if (c == Conversion.OCTAL_INTEGER) { 3009 checkBadFlags(Flags.PARENTHESES, Flags.LEADING_SPACE, 3010 Flags.PLUS); 3011 String s = Long.toOctalString(value); 3012 int len = (f.contains(Flags.ALTERNATE) 3013 ? s.length() + 1 3014 : s.length()); 3015 3016 if (f.contains(Flags.ALTERNATE)) 3018 sb.append('0'); 3019 if (f.contains(Flags.ZERO_PAD)) 3020 for (int i = 0; i < width - len; i++) sb.append('0'); 3021 sb.append(s); 3022 } else if (c == Conversion.HEXADECIMAL_INTEGER) { 3023 checkBadFlags(Flags.PARENTHESES, Flags.LEADING_SPACE, 3024 Flags.PLUS); 3025 String s = Long.toHexString(value); 3026 int len = (f.contains(Flags.ALTERNATE) 3027 ? s.length() + 2 3028 : s.length()); 3029 3030 if (f.contains(Flags.ALTERNATE)) 3032 sb.append(f.contains(Flags.UPPERCASE) ? "0X" : "0x"); 3033 if (f.contains(Flags.ZERO_PAD)) 3034 for (int i = 0; i < width - len; i++) sb.append('0'); 3035 if (f.contains(Flags.UPPERCASE)) 3036 s = s.toUpperCase(); 3037 sb.append(s); 3038 } 3039 3040 a.append(justify(sb.toString())); 3042 } 3043 3044 private StringBuilder leadingSign(StringBuilder sb, boolean neg) { 3046 if (!neg) { 3047 if (f.contains(Flags.PLUS)) { 3048 sb.append('+'); 3049 } else if (f.contains(Flags.LEADING_SPACE)) { 3050 sb.append(' '); 3051 } 3052 } else { 3053 if (f.contains(Flags.PARENTHESES)) 3054 sb.append('('); 3055 else 3056 sb.append('-'); 3057 } 3058 return sb; 3059 } 3060 3061 private StringBuilder trailingSign(StringBuilder sb, boolean neg) { 3063 if (neg && f.contains(Flags.PARENTHESES)) 3064 sb.append(')'); 3065 return sb; 3066 } 3067 3068 private void print(BigInteger value, Locale l) throws IOException { 3069 StringBuilder sb = new StringBuilder (); 3070 boolean neg = value.signum() == -1; 3071 BigInteger v = value.abs(); 3072 3073 leadingSign(sb, neg); 3075 3076 if (c == Conversion.DECIMAL_INTEGER) { 3078 char[] va = v.toString().toCharArray(); 3079 localizedMagnitude(sb, va, f, adjustWidth(width, f, neg), l); 3080 } else if (c == Conversion.OCTAL_INTEGER) { 3081 String s = v.toString(8); 3082 3083 int len = s.length() + sb.length(); 3084 if (neg && f.contains(Flags.PARENTHESES)) 3085 len++; 3086 3087 if (f.contains(Flags.ALTERNATE)) { 3089 len++; 3090 sb.append('0'); 3091 } 3092 if (f.contains(Flags.ZERO_PAD)) { 3093 for (int i = 0; i < width - len; i++) 3094 sb.append('0'); 3095 } 3096 sb.append(s); 3097 } else if (c == Conversion.HEXADECIMAL_INTEGER) { 3098 String s = v.toString(16); 3099 3100 int len = s.length() + sb.length(); 3101 if (neg && f.contains(Flags.PARENTHESES)) 3102 len++; 3103 3104 if (f.contains(Flags.ALTERNATE)) { 3106 len += 2; 3107 sb.append(f.contains(Flags.UPPERCASE) ? "0X" : "0x"); 3108 } 3109 if (f.contains(Flags.ZERO_PAD)) 3110 for (int i = 0; i < width - len; i++) 3111 sb.append('0'); 3112 if (f.contains(Flags.UPPERCASE)) 3113 s = s.toUpperCase(); 3114 sb.append(s); 3115 } 3116 3117 trailingSign(sb, (value.signum() == -1)); 3119 3120 a.append(justify(sb.toString())); 3122 } 3123 3124 private void print(float value, Locale l) throws IOException { 3125 print((double) value, l); 3126 } 3127 3128 private void print(double value, Locale l) throws IOException { 3129 StringBuilder sb = new StringBuilder (); 3130 boolean neg = Double.compare(value, 0.0) == -1; 3131 3132 if (!Double.isNaN(value)) { 3133 double v = Math.abs(value); 3134 3135 leadingSign(sb, neg); 3137 3138 if (!Double.isInfinite(v)) 3140 print(sb, v, l, f, c, precision, neg); 3141 else 3142 sb.append(f.contains(Flags.UPPERCASE) 3143 ? "INFINITY" : "Infinity"); 3144 3145 trailingSign(sb, neg); 3147 } else { 3148 sb.append(f.contains(Flags.UPPERCASE) ? "NAN" : "NaN"); 3149 } 3150 3151 a.append(justify(sb.toString())); 3153 } 3154 3155 private void print(StringBuilder sb, double value, Locale l, 3157 Flags f, char c, int precision, boolean neg) 3158 throws IOException 3159 { 3160 if (c == Conversion.SCIENTIFIC) { 3161 int prec = (precision == -1 ? 6 : precision); 3164 3165 FormattedFloatingDecimal fd 3166 = new FormattedFloatingDecimal(value, prec, 3167 FormattedFloatingDecimal.Form.SCIENTIFIC); 3168 3169 char[] v = new char[MAX_FD_CHARS]; 3170 int len = fd.getChars(v); 3171 3172 char[] mant = addZeros(mantissa(v, len), prec); 3173 3174 if (f.contains(Flags.ALTERNATE) && (prec == 0)) 3177 mant = addDot(mant); 3178 3179 char[] exp = (value == 0.0) 3180 ? new char[] {'+','0','0'} : exponent(v, len); 3181 3182 int newW = width; 3183 if (width != -1) 3184 newW = adjustWidth(width - exp.length - 1, f, neg); 3185 localizedMagnitude(sb, mant, f, newW, null); 3186 3187 sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e'); 3188 3189 Flags flags = f.dup().remove(Flags.GROUP); 3190 char sign = exp[0]; 3191 assert(sign == '+' || sign == '-'); 3192 sb.append(sign); 3193 3194 char[] tmp = new char[exp.length - 1]; 3195 System.arraycopy(exp, 1, tmp, 0, exp.length - 1); 3196 sb.append(localizedMagnitude(null, tmp, flags, -1, null)); 3197 } else if (c == Conversion.DECIMAL_FLOAT) { 3198 int prec = (precision == -1 ? 6 : precision); 3201 3202 FormattedFloatingDecimal fd 3203 = new FormattedFloatingDecimal(value, prec, 3204 FormattedFloatingDecimal.Form.DECIMAL_FLOAT); 3205 3206 char[] v = new char[MAX_FD_CHARS + 1 3208 + Math.abs(fd.getExponent())]; 3209 int len = fd.getChars(v); 3210 3211 char[] mant = addZeros(mantissa(v, len), prec); 3212 3213 if (f.contains(Flags.ALTERNATE) && (prec == 0)) 3216 mant = addDot(mant); 3217 3218 int newW = width; 3219 if (width != -1) 3220 newW = adjustWidth(width, f, neg); 3221 localizedMagnitude(sb, mant, f, newW, l); 3222 } else if (c == Conversion.GENERAL) { 3223 int prec = precision; 3224 if (precision == -1) 3225 prec = 6; 3226 else if (precision == 0) 3227 prec = 1; 3228 3229 FormattedFloatingDecimal fd 3230 = new FormattedFloatingDecimal(value, prec, 3231 FormattedFloatingDecimal.Form.GENERAL); 3232 3233 char[] v = new char[MAX_FD_CHARS + 1 3235 + Math.abs(fd.getExponent())]; 3236 int len = fd.getChars(v); 3237 3238 char[] exp = exponent(v, len); 3239 if (exp != null) { 3240 prec -= 1; 3241 } else { 3242 prec = prec - (value == 0 ? 0 : fd.getExponentRounded()) - 1; 3243 } 3244 3245 char[] mant = addZeros(mantissa(v, len), prec); 3246 if (f.contains(Flags.ALTERNATE) && (prec == 0)) 3249 mant = addDot(mant); 3250 3251 int newW = width; 3252 if (width != -1) { 3253 if (exp != null) 3254 newW = adjustWidth(width - exp.length - 1, f, neg); 3255 else 3256 newW = adjustWidth(width, f, neg); 3257 } 3258 localizedMagnitude(sb, mant, f, newW, null); 3259 3260 if (exp != null) { 3261 sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e'); 3262 3263 Flags flags = f.dup().remove(Flags.GROUP); 3264 char sign = exp[0]; 3265 assert(sign == '+' || sign == '-'); 3266 sb.append(sign); 3267 3268 char[] tmp = new char[exp.length - 1]; 3269 System.arraycopy(exp, 1, tmp, 0, exp.length - 1); 3270 sb.append(localizedMagnitude(null, tmp, flags, -1, null)); 3271 } 3272 } else if (c == Conversion.HEXADECIMAL_FLOAT) { 3273 int prec = precision; 3274 if (precision == -1) 3275 prec = 0; 3277 else if (precision == 0) 3278 prec = 1; 3279 3280 String s = hexDouble(value, prec); 3281 3282 char[] va; 3283 boolean upper = f.contains(Flags.UPPERCASE); 3284 sb.append(upper ? "0X" : "0x"); 3285 3286 if (f.contains(Flags.ZERO_PAD)) 3287 for (int i = 0; i < width - s.length() - 2; i++) 3288 sb.append('0'); 3289 3290 int idx = s.indexOf('p'); 3291 va = s.substring(0, idx).toCharArray(); 3292 if (upper) { 3293 String tmp = new String (va); 3294 tmp = tmp.toUpperCase(Locale.US); 3296 va = tmp.toCharArray(); 3297 } 3298 sb.append(prec != 0 ? addZeros(va, prec) : va); 3299 sb.append(upper ? 'P' : 'p'); 3300 sb.append(s.substring(idx+1)); 3301 } 3302 } 3303 3304 private char[] mantissa(char[] v, int len) { 3305 int i; 3306 for (i = 0; i < len; i++) { 3307 if (v[i] == 'e') 3308 break; 3309 } 3310 char[] tmp = new char[i]; 3311 System.arraycopy(v, 0, tmp, 0, i); 3312 return tmp; 3313 } 3314 3315 private char[] exponent(char[] v, int len) { 3316 int i; 3317 for (i = len - 1; i >= 0; i--) { 3318 if (v[i] == 'e') 3319 break; 3320 } 3321 if (i == -1) 3322 return null; 3323 char[] tmp = new char[len - i - 1]; 3324 System.arraycopy(v, i + 1, tmp, 0, len - i - 1); 3325 return tmp; 3326 } 3327 3328 private char[] addZeros(char[] v, int prec) { 3330 int i; 3333 for (i = 0; i < v.length; i++) { 3334 if (v[i] == '.') 3335 break; 3336 } 3337 boolean needDot = false; 3338 if (i == v.length) { 3339 needDot = true; 3340 } 3341 3342 int outPrec = v.length - i - (needDot ? 0 : 1); 3344 assert (outPrec <= prec); 3345 if (outPrec == prec) 3346 return v; 3347 3348 char[] tmp 3350 = new char[v.length + prec - outPrec + (needDot ? 1 : 0)]; 3351 System.arraycopy(v, 0, tmp, 0, v.length); 3352 3353 int start = v.length; 3355 if (needDot) { 3356 tmp[v.length] = '.'; 3357 start++; 3358 } 3359 3360 for (int j = start; j < tmp.length; j++) 3362 tmp[j] = '0'; 3363 3364 return tmp; 3365 } 3366 3367 private String hexDouble(double d, int prec) { 3369 if(!FpUtils.isFinite(d) || d == 0.0 || prec == 0 || prec >= 13) 3371 return Double.toHexString(d).substring(2); 3373 else { 3374 assert(prec >= 1 && prec <= 12); 3375 3376 int exponent = FpUtils.getExponent(d); 3377 boolean subnormal 3378 = (exponent == DoubleConsts.MIN_EXPONENT - 1); 3379 3380 if (subnormal) { 3383 scaleUp = FpUtils.scalb(1.0, 54); 3384 d *= scaleUp; 3385 exponent = FpUtils.getExponent(d); 3388 assert exponent >= DoubleConsts.MIN_EXPONENT && 3389 exponent <= DoubleConsts.MAX_EXPONENT: exponent; 3390 } 3391 3392 int precision = 1 + prec*4; 3393 int shiftDistance 3394 = DoubleConsts.SIGNIFICAND_WIDTH - precision; 3395 assert(shiftDistance >= 1 && shiftDistance < DoubleConsts.SIGNIFICAND_WIDTH); 3396 3397 long doppel = Double.doubleToLongBits(d); 3398 long newSignif 3400 = (doppel & (DoubleConsts.EXP_BIT_MASK 3401 | DoubleConsts.SIGNIF_BIT_MASK)) 3402 >> shiftDistance; 3403 long roundingBits = doppel & ~(~0L << shiftDistance); 3405 3406 3411 boolean leastZero = (newSignif & 0x1L) == 0L; 3412 boolean round 3413 = ((1L << (shiftDistance - 1) ) & roundingBits) != 0L; 3414 boolean sticky = shiftDistance > 1 && 3415 (~(1L<< (shiftDistance - 1)) & roundingBits) != 0; 3416 if((leastZero && round && sticky) || (!leastZero && round)) { 3417 newSignif++; 3418 } 3419 3420 long signBit = doppel & DoubleConsts.SIGN_BIT_MASK; 3421 newSignif = signBit | (newSignif << shiftDistance); 3422 double result = Double.longBitsToDouble(newSignif); 3423 3424 if (Double.isInfinite(result) ) { 3425 return "1.0p1024"; 3427 } else { 3428 String res = Double.toHexString(result).substring(2); 3429 if (!subnormal) 3430 return res; 3431 else { 3432 int idx = res.indexOf('p'); 3434 if (idx == -1) { 3435 assert false; 3437 return null; 3438 } else { 3439 String exp = res.substring(idx + 1); 3441 int iexp = Integer.parseInt(exp) -54; 3442 return res.substring(0, idx) + "p" 3443 + Integer.toString(iexp); 3444 } 3445 } 3446 } 3447 } 3448 } 3449 3450 private void print(BigDecimal value, Locale l) throws IOException { 3451 if (c == Conversion.HEXADECIMAL_FLOAT) 3452 failConversion(c, value); 3453 StringBuilder sb = new StringBuilder (); 3454 boolean neg = value.signum() == -1; 3455 BigDecimal v = value.abs(); 3456 leadingSign(sb, neg); 3458 3459 print(sb, v, l, f, c, precision, neg); 3461 3462 trailingSign(sb, neg); 3464 3465 a.append(justify(sb.toString())); 3467 } 3468 3469 private void print(StringBuilder sb, BigDecimal value, Locale l, 3471 Flags f, char c, int precision, boolean neg) 3472 throws IOException 3473 { 3474 if (c == Conversion.SCIENTIFIC) { 3475 int prec = (precision == -1 ? 6 : precision); 3477 int scale = value.scale(); 3478 int origPrec = value.precision(); 3479 int nzeros = 0; 3480 int compPrec; 3481 3482 if (prec > origPrec - 1) { 3483 compPrec = origPrec; 3484 nzeros = prec - (origPrec - 1); 3485 } else { 3486 compPrec = prec + 1; 3487 } 3488 3489 MathContext mc = new MathContext (compPrec); 3490 BigDecimal v 3491 = new BigDecimal (value.unscaledValue(), scale, mc); 3492 3493 BigDecimalLayout bdl 3494 = new BigDecimalLayout(v.unscaledValue(), v.scale(), 3495 BigDecimalLayoutForm.SCIENTIFIC); 3496 3497 char[] mant = bdl.mantissa(); 3498 3499 if ((origPrec == 1 || !bdl.hasDot()) 3505 && (nzeros > 0 || (f.contains(Flags.ALTERNATE)))) 3506 mant = addDot(mant); 3507 3508 mant = trailingZeros(mant, nzeros); 3511 3512 char[] exp = bdl.exponent(); 3513 int newW = width; 3514 if (width != -1) 3515 newW = adjustWidth(width - exp.length - 1, f, neg); 3516 localizedMagnitude(sb, mant, f, newW, null); 3517 3518 sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e'); 3519 3520 Flags flags = f.dup().remove(Flags.GROUP); 3521 char sign = exp[0]; 3522 assert(sign == '+' || sign == '-'); 3523 sb.append(exp[0]); 3524 3525 char[] tmp = new char[exp.length - 1]; 3526 System.arraycopy(exp, 1, tmp, 0, exp.length - 1); 3527 sb.append(localizedMagnitude(null, tmp, flags, -1, null)); 3528 } else if (c == Conversion.DECIMAL_FLOAT) { 3529 int prec = (precision == -1 ? 6 : precision); 3531 int scale = value.scale(); 3532 int origPrec = value.precision(); 3533 int nzeros = 0; 3534 int compPrec; 3535 if (scale < prec) { 3536 compPrec = origPrec; 3537 nzeros = prec - scale; 3538 } else { 3539 compPrec = origPrec - (scale - prec); 3540 } 3541 MathContext mc = new MathContext (compPrec); 3542 BigDecimal v 3543 = new BigDecimal (value.unscaledValue(), scale, mc); 3544 3545 BigDecimalLayout bdl 3546 = new BigDecimalLayout(v.unscaledValue(), v.scale(), 3547 BigDecimalLayoutForm.DECIMAL_FLOAT); 3548 3549 char mant[] = bdl.mantissa(); 3550 3551 if (scale == 0 && (f.contains(Flags.ALTERNATE) || nzeros > 0)) 3557 mant = addDot(bdl.mantissa()); 3558 3559 mant = trailingZeros(mant, nzeros); 3562 3563 localizedMagnitude(sb, mant, f, adjustWidth(width, f, neg), l); 3564 } else if (c == Conversion.GENERAL) { 3565 int prec = precision; 3566 if (precision == -1) 3567 prec = 6; 3568 else if (precision == 0) 3569 prec = 1; 3570 3571 BigDecimal tenToTheNegFour = BigDecimal.valueOf(1, 4); 3572 BigDecimal tenToThePrec = BigDecimal.valueOf(1, -prec); 3573 if ((value.equals(BigDecimal.ZERO)) 3574 || ((value.compareTo(tenToTheNegFour) != -1) 3575 && (value.compareTo(tenToThePrec) == -1))) { 3576 3577 int e = - value.scale() 3578 + (value.unscaledValue().toString().length() - 1); 3579 3580 prec = prec - e - 1; 3591 3592 print(sb, value, l, f, Conversion.DECIMAL_FLOAT, prec, 3593 neg); 3594 } else { 3595 print(sb, value, l, f, Conversion.SCIENTIFIC, prec - 1, neg); 3596 } 3597 } else if (c == Conversion.HEXADECIMAL_FLOAT) { 3598 assert false; 3601 } 3602 } 3603 3604 private class BigDecimalLayout { 3605 private StringBuilder mant; 3606 private StringBuilder exp; 3607 private boolean dot = false; 3608 3609 public BigDecimalLayout(BigInteger intVal, int scale, BigDecimalLayoutForm form) { 3610 layout(intVal, scale, form); 3611 } 3612 3613 public boolean hasDot() { 3614 return dot; 3615 } 3616 3617 public char[] layoutChars() { 3619 StringBuilder sb = new StringBuilder (mant); 3620 if (exp != null) { 3621 sb.append('E'); 3622 sb.append(exp); 3623 } 3624 return toCharArray(sb); 3625 } 3626 3627 public char[] mantissa() { 3628 return toCharArray(mant); 3629 } 3630 3631 public char[] exponent() { 3634 return toCharArray(exp); 3635 } 3636 3637 private char[] toCharArray(StringBuilder sb) { 3638 if (sb == null) 3639 return null; 3640 char[] result = new char[sb.length()]; 3641 sb.getChars(0, result.length, result, 0); 3642 return result; 3643 } 3644 3645 private void layout(BigInteger intVal, int scale, BigDecimalLayoutForm form) { 3646 char coeff[] = intVal.toString().toCharArray(); 3647 3648 mant = new StringBuilder (coeff.length + 14); 3654 3655 if (scale == 0) { 3656 int len = coeff.length; 3657 if (len > 1) { 3658 mant.append(coeff[0]); 3659 if (form == BigDecimalLayoutForm.SCIENTIFIC) { 3660 mant.append('.'); 3661 dot = true; 3662 mant.append(coeff, 1, len - 1); 3663 exp = new StringBuilder ("+"); 3664 if (len < 10) 3665 exp.append("0").append(len - 1); 3666 else 3667 exp.append(len - 1); 3668 } else { 3669 mant.append(coeff, 1, len - 1); 3670 } 3671 } else { 3672 mant.append(coeff); 3673 if (form == BigDecimalLayoutForm.SCIENTIFIC) 3674 exp = new StringBuilder ("+00"); 3675 } 3676 return; 3677 } 3678 long adjusted = -(long) scale + (coeff.length - 1); 3679 if (form == BigDecimalLayoutForm.DECIMAL_FLOAT) { 3680 int pad = scale - coeff.length; 3682 if (pad >= 0) { 3683 mant.append("0."); 3685 dot = true; 3686 for (; pad > 0 ; pad--) mant.append('0'); 3687 mant.append(coeff); 3688 } else { 3689 mant.append(coeff, 0, -pad); 3691 mant.append('.'); 3692 dot = true; 3693 mant.append(coeff, -pad, scale); 3694 } 3695 } else { 3696 mant.append(coeff[0]); 3698 if (coeff.length > 1) { 3699 mant.append('.'); 3700 dot = true; 3701 mant.append(coeff, 1, coeff.length-1); 3702 } 3703 exp = new StringBuilder (); 3704 if (adjusted != 0) { 3705 long abs = Math.abs(adjusted); 3706 exp.append(adjusted < 0 ? '-' : '+'); 3708 if (abs < 10) 3709 exp.append('0'); 3710 exp.append(abs); 3711 } else { 3712 exp.append("+00"); 3713 } 3714 } 3715 } 3716 } 3717 3718 private int adjustWidth(int width, Flags f, boolean neg) { 3719 int newW = width; 3720 if (newW != -1 && neg && f.contains(Flags.PARENTHESES)) 3721 newW--; 3722 return newW; 3723 } 3724 3725 private char[] addDot(char[] mant) { 3727 char[] tmp = mant; 3728 tmp = new char[mant.length + 1]; 3729 System.arraycopy(mant, 0, tmp, 0, mant.length); 3730 tmp[tmp.length - 1] = '.'; 3731 return tmp; 3732 } 3733 3734 private char[] trailingZeros(char[] mant, int nzeros) { 3737 char[] tmp = mant; 3738 if (nzeros > 0) { 3739 tmp = new char[mant.length + nzeros]; 3740 System.arraycopy(mant, 0, tmp, 0, mant.length); 3741 for (int i = mant.length; i < tmp.length; i++) 3742 tmp[i] = '0'; 3743 } 3744 return tmp; 3745 } 3746 3747 private void print(Calendar t, char c, Locale l) throws IOException 3748 { 3749 StringBuilder sb = new StringBuilder (); 3750 print(sb, t, c, l); 3751 3752 String s = justify(sb.toString()); 3754 if (f.contains(Flags.UPPERCASE)) 3755 s = s.toUpperCase(); 3756 3757 a.append(s); 3758 } 3759 3760 private Appendable print(StringBuilder sb, Calendar t, char c, 3761 Locale l) 3762 throws IOException 3763 { 3764 assert(width == -1); 3765 if (sb == null) 3766 sb = new StringBuilder (); 3767 switch (c) { 3768 case DateTime.HOUR_OF_DAY_0: case DateTime.HOUR_0: case DateTime.HOUR_OF_DAY: case DateTime.HOUR: { int i = t.get(Calendar.HOUR_OF_DAY); 3773 if (c == DateTime.HOUR_0 || c == DateTime.HOUR) 3774 i = (i == 0 || i == 12 ? 12 : i % 12); 3775 Flags flags = (c == DateTime.HOUR_OF_DAY_0 3776 || c == DateTime.HOUR_0 3777 ? Flags.ZERO_PAD 3778 : Flags.NONE); 3779 sb.append(localizedMagnitude(null, i, flags, 2, l)); 3780 break; 3781 } 3782 case DateTime.MINUTE: { int i = t.get(Calendar.MINUTE); 3784 Flags flags = Flags.ZERO_PAD; 3785 sb.append(localizedMagnitude(null, i, flags, 2, l)); 3786 break; 3787 } 3788 case DateTime.NANOSECOND: { int i = t.get(Calendar.MILLISECOND) * 1000000; 3790 Flags flags = Flags.ZERO_PAD; 3791 sb.append(localizedMagnitude(null, i, flags, 9, l)); 3792 break; 3793 } 3794 case DateTime.MILLISECOND: { int i = t.get(Calendar.MILLISECOND); 3796 Flags flags = Flags.ZERO_PAD; 3797 sb.append(localizedMagnitude(null, i, flags, 3, l)); 3798 break; 3799 } 3800 case DateTime.MILLISECOND_SINCE_EPOCH: { long i = t.getTimeInMillis(); 3802 Flags flags = Flags.NONE; 3803 sb.append(localizedMagnitude(null, i, flags, width, l)); 3804 break; 3805 } 3806 case DateTime.AM_PM: { String [] ampm = { "AM", "PM" }; 3809 if (l != null && l != Locale.US) { 3810 DateFormatSymbols dfs = new DateFormatSymbols (l); 3811 ampm = dfs.getAmPmStrings(); 3812 } 3813 String s = ampm[t.get(Calendar.AM_PM)]; 3814 sb.append(s.toLowerCase(l != null ? l : Locale.US)); 3815 break; 3816 } 3817 case DateTime.SECONDS_SINCE_EPOCH: { long i = t.getTimeInMillis() / 1000; 3819 Flags flags = Flags.NONE; 3820 sb.append(localizedMagnitude(null, i, flags, width, l)); 3821 break; 3822 } 3823 case DateTime.SECOND: { int i = t.get(Calendar.SECOND); 3825 Flags flags = Flags.ZERO_PAD; 3826 sb.append(localizedMagnitude(null, i, flags, 2, l)); 3827 break; 3828 } 3829 case DateTime.ZONE_NUMERIC: { int i = t.get(Calendar.ZONE_OFFSET); 3831 boolean neg = i < 0; 3832 sb.append(neg ? '-' : '+'); 3833 if (neg) 3834 i = -i; 3835 int min = i / 60000; 3836 int offset = (min / 60) * 100 + (min % 60); 3838 Flags flags = Flags.ZERO_PAD; 3839 3840 sb.append(localizedMagnitude(null, offset, flags, 4, l)); 3841 break; 3842 } 3843 case DateTime.ZONE: { TimeZone tz = t.getTimeZone(); 3845 sb.append(tz.getDisplayName((t.get(Calendar.DST_OFFSET) != 0), 3846 TimeZone.SHORT, 3847 l)); 3848 break; 3849 } 3850 3851 case DateTime.NAME_OF_DAY_ABBREV: case DateTime.NAME_OF_DAY: { int i = t.get(Calendar.DAY_OF_WEEK); 3855 Locale lt = ((l == null) ? Locale.US : l); 3856 DateFormatSymbols dfs = new DateFormatSymbols (lt); 3857 if (c == DateTime.NAME_OF_DAY) 3858 sb.append(dfs.getWeekdays()[i]); 3859 else 3860 sb.append(dfs.getShortWeekdays()[i]); 3861 break; 3862 } 3863 case DateTime.NAME_OF_MONTH_ABBREV: case DateTime.NAME_OF_MONTH_ABBREV_X: case DateTime.NAME_OF_MONTH: { int i = t.get(Calendar.MONTH); 3867 Locale lt = ((l == null) ? Locale.US : l); 3868 DateFormatSymbols dfs = new DateFormatSymbols (lt); 3869 if (c == DateTime.NAME_OF_MONTH) 3870 sb.append(dfs.getMonths()[i]); 3871 else 3872 sb.append(dfs.getShortMonths()[i]); 3873 break; 3874 } 3875 case DateTime.CENTURY: case DateTime.YEAR_2: case DateTime.YEAR_4: { int i = t.get(Calendar.YEAR); 3879 int size = 2; 3880 switch (c) { 3881 case DateTime.CENTURY: 3882 i /= 100; 3883 break; 3884 case DateTime.YEAR_2: 3885 i %= 100; 3886 break; 3887 case DateTime.YEAR_4: 3888 size = 4; 3889 break; 3890 } 3891 Flags flags = Flags.ZERO_PAD; 3892 sb.append(localizedMagnitude(null, i, flags, size, l)); 3893 break; 3894 } 3895 case DateTime.DAY_OF_MONTH_0: case DateTime.DAY_OF_MONTH: { int i = t.get(Calendar.DATE); 3898 Flags flags = (c == DateTime.DAY_OF_MONTH_0 3899 ? Flags.ZERO_PAD 3900 : Flags.NONE); 3901 sb.append(localizedMagnitude(null, i, flags, 2, l)); 3902 break; 3903 } 3904 case DateTime.DAY_OF_YEAR: { int i = t.get(Calendar.DAY_OF_YEAR); 3906 Flags flags = Flags.ZERO_PAD; 3907 sb.append(localizedMagnitude(null, i, flags, 3, l)); 3908 break; 3909 } 3910 case DateTime.MONTH: { int i = t.get(Calendar.MONTH) + 1; 3912 Flags flags = Flags.ZERO_PAD; 3913 sb.append(localizedMagnitude(null, i, flags, 2, l)); 3914 break; 3915 } 3916 3917 case DateTime.TIME: case DateTime.TIME_24_HOUR: { char sep = ':'; 3921 print(sb, t, DateTime.HOUR_OF_DAY_0, l).append(sep); 3922 print(sb, t, DateTime.MINUTE, l); 3923 if (c == DateTime.TIME) { 3924 sb.append(sep); 3925 print(sb, t, DateTime.SECOND, l); 3926 } 3927 break; 3928 } 3929 case DateTime.TIME_12_HOUR: { char sep = ':'; 3931 print(sb, t, DateTime.HOUR_0, l).append(sep); 3932 print(sb, t, DateTime.MINUTE, l).append(sep); 3933 print(sb, t, DateTime.SECOND, l).append(' '); 3934 StringBuilder tsb = new StringBuilder (); 3936 print(tsb, t, DateTime.AM_PM, l); 3937 sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US)); 3938 break; 3939 } 3940 case DateTime.DATE_TIME: { char sep = ' '; 3942 print(sb, t, DateTime.NAME_OF_DAY_ABBREV, l).append(sep); 3943 print(sb, t, DateTime.NAME_OF_MONTH_ABBREV, l).append(sep); 3944 print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep); 3945 print(sb, t, DateTime.TIME, l).append(sep); 3946 print(sb, t, DateTime.ZONE, l).append(sep); 3947 print(sb, t, DateTime.YEAR_4, l); 3948 break; 3949 } 3950 case DateTime.DATE: { char sep = '/'; 3952 print(sb, t, DateTime.MONTH, l).append(sep); 3953 print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep); 3954 print(sb, t, DateTime.YEAR_2, l); 3955 break; 3956 } 3957 case DateTime.ISO_STANDARD_DATE: { char sep = '-'; 3959 print(sb, t, DateTime.YEAR_4, l).append(sep); 3960 print(sb, t, DateTime.MONTH, l).append(sep); 3961 print(sb, t, DateTime.DAY_OF_MONTH_0, l); 3962 break; 3963 } 3964 default: 3965 assert false; 3966 } 3967 return sb; 3968 } 3969 3970 3972 private void failMismatch(Flags f, char c) { 3973 String fs = f.toString(); 3974 throw new FormatFlagsConversionMismatchException (fs, c); 3975 } 3976 3977 private void failConversion(char c, Object arg) { 3978 throw new IllegalFormatConversionException (c, arg.getClass()); 3979 } 3980 3981 private char getZero(Locale l) { 3982 if ((l != null) && !l.equals(locale())) { 3983 DecimalFormatSymbols dfs = new DecimalFormatSymbols (l); 3984 return dfs.getZeroDigit(); 3985 } 3986 return zero; 3987 } 3988 3989 private StringBuilder 3990 localizedMagnitude(StringBuilder sb, long value, Flags f, 3991 int width, Locale l) 3992 { 3993 char[] va = Long.toString(value, 10).toCharArray(); 3994 return localizedMagnitude(sb, va, f, width, l); 3995 } 3996 3997 private StringBuilder 3998 localizedMagnitude(StringBuilder sb, char[] value, Flags f, 3999 int width, Locale l) 4000 { 4001 if (sb == null) 4002 sb = new StringBuilder (); 4003 int begin = sb.length(); 4004 4005 char zero = getZero(l); 4006 4007 char grpSep = '\0'; 4009 int grpSize = -1; 4010 char decSep = '\0'; 4011 4012 int len = value.length; 4013 int dot = len; 4014 for (int j = 0; j < len; j++) { 4015 if (value[j] == '.') { 4016 dot = j; 4017 break; 4018 } 4019 } 4020 4021 if (dot < len) { 4022 if (l == null || l.equals(Locale.US)) { 4023 decSep = '.'; 4024 } else { 4025 DecimalFormatSymbols dfs = new DecimalFormatSymbols (l); 4026 decSep = dfs.getDecimalSeparator(); 4027 } 4028 } 4029 4030 if (f.contains(Flags.GROUP)) { 4031 if (l == null || l.equals(Locale.US)) { 4032 grpSep = ','; 4033 grpSize = 3; 4034 } else { 4035 DecimalFormatSymbols dfs = new DecimalFormatSymbols (l); 4036 grpSep = dfs.getGroupingSeparator(); 4037 DecimalFormat df = (DecimalFormat ) NumberFormat.getIntegerInstance(l); 4038 grpSize = df.getGroupingSize(); 4039 } 4040 } 4041 4042 for (int j = 0; j < len; j++) { 4044 if (j == dot) { 4045 sb.append(decSep); 4046 grpSep = '\0'; 4048 continue; 4049 } 4050 4051 char c = value[j]; 4052 sb.append((char) ((c - '0') + zero)); 4053 if (grpSep != '\0' && j != dot - 1 && ((dot - j) % grpSize == 1)) 4054 sb.append(grpSep); 4055 } 4056 4057 len = sb.length(); 4059 if (width != -1 && f.contains(Flags.ZERO_PAD)) 4060 for (int k = 0; k < width - len; k++) 4061 sb.insert(begin, zero); 4062 4063 return sb; 4064 } 4065 } 4066 4067 private static class Flags { 4068 private int flags; 4069 4070 static final Flags NONE = new Flags(0); 4072 static final Flags LEFT_JUSTIFY = new Flags(1<<0); static final Flags UPPERCASE = new Flags(1<<1); static final Flags ALTERNATE = new Flags(1<<2); 4077 static final Flags PLUS = new Flags(1<<3); static final Flags LEADING_SPACE = new Flags(1<<4); static final Flags ZERO_PAD = new Flags(1<<5); static final Flags GROUP = new Flags(1<<6); static final Flags PARENTHESES = new Flags(1<<7); 4084 static final Flags PREVIOUS = new Flags(1<<8); 4087 private Flags(int f) { 4088 flags = f; 4089 } 4090 4091 public int valueOf() { 4092 return flags; 4093 } 4094 4095 public boolean contains(Flags f) { 4096 return (flags & f.valueOf()) == f.valueOf(); 4097 } 4098 4099 public Flags dup() { 4100 return new Flags(flags); 4101 } 4102 4103 private Flags add(Flags f) { 4104 flags |= f.valueOf(); 4105 return this; 4106 } 4107 4108 public Flags remove(Flags f) { 4109 flags &= ~f.valueOf(); 4110 return this; 4111 } 4112 4113 public static Flags parse(String s) { 4114 char[] ca = s.toCharArray(); 4115 Flags f = new Flags(0); 4116 for (int i = 0; i < ca.length; i++) { 4117 Flags v = parse(ca[i]); 4118 if (f.contains(v)) 4119 throw new DuplicateFormatFlagsException (v.toString()); 4120 f.add(v); 4121 } 4122 return f; 4123 } 4124 4125 private static Flags parse(char c) { 4127 switch (c) { 4128 case '-': return LEFT_JUSTIFY; 4129 case '#': return ALTERNATE; 4130 case '+': return PLUS; 4131 case ' ': return LEADING_SPACE; 4132 case '0': return ZERO_PAD; 4133 case ',': return GROUP; 4134 case '(': return PARENTHESES; 4135 case '<': return PREVIOUS; 4136 default: 4137 throw new UnknownFormatFlagsException (String.valueOf(c)); 4138 } 4139 } 4140 4141 public static String toString(Flags f) { 4143 return f.toString(); 4144 } 4145 4146 public String toString() { 4147 StringBuilder sb = new StringBuilder (); 4148 if (contains(LEFT_JUSTIFY)) sb.append('-'); 4149 if (contains(UPPERCASE)) sb.append('^'); 4150 if (contains(ALTERNATE)) sb.append('#'); 4151 if (contains(PLUS)) sb.append('+'); 4152 if (contains(LEADING_SPACE)) sb.append(' '); 4153 if (contains(ZERO_PAD)) sb.append('0'); 4154 if (contains(GROUP)) sb.append(','); 4155 if (contains(PARENTHESES)) sb.append('('); 4156 if (contains(PREVIOUS)) sb.append('<'); 4157 return sb.toString(); 4158 } 4159 } 4160 4161 private static class Conversion { 4162 static final char DECIMAL_INTEGER = 'd'; 4165 static final char OCTAL_INTEGER = 'o'; 4166 static final char HEXADECIMAL_INTEGER = 'x'; 4167 static final char HEXADECIMAL_INTEGER_UPPER = 'X'; 4168 4169 static final char SCIENTIFIC = 'e'; 4172 static final char SCIENTIFIC_UPPER = 'E'; 4173 static final char GENERAL = 'g'; 4174 static final char GENERAL_UPPER = 'G'; 4175 static final char DECIMAL_FLOAT = 'f'; 4176 static final char HEXADECIMAL_FLOAT = 'a'; 4177 static final char HEXADECIMAL_FLOAT_UPPER = 'A'; 4178 4179 static final char CHARACTER = 'c'; 4182 static final char CHARACTER_UPPER = 'C'; 4183 4184 static final char DATE_TIME = 't'; 4186 static final char DATE_TIME_UPPER = 'T'; 4187 4188 static final char BOOLEAN = 'b'; 4191 static final char BOOLEAN_UPPER = 'B'; 4192 static final char STRING = 's'; 4195 static final char STRING_UPPER = 'S'; 4196 static final char HASHCODE = 'h'; 4198 static final char HASHCODE_UPPER = 'H'; 4199 4200 static final char LINE_SEPARATOR = 'n'; 4201 static final char PERCENT_SIGN = '%'; 4202 4203 static boolean isValid(char c) { 4204 return (isGeneral(c) || isInteger(c) || isFloat(c) || isText(c) 4205 || c == 't' || c == 'c'); 4206 } 4207 4208 static boolean isGeneral(char c) { 4210 switch (c) { 4211 case BOOLEAN: 4212 case BOOLEAN_UPPER: 4213 case STRING: 4214 case STRING_UPPER: 4215 case HASHCODE: 4216 case HASHCODE_UPPER: 4217 return true; 4218 default: 4219 return false; 4220 } 4221 } 4222 4223 static boolean isInteger(char c) { 4225 switch (c) { 4226 case DECIMAL_INTEGER: 4227 case OCTAL_INTEGER: 4228 case HEXADECIMAL_INTEGER: 4229 case HEXADECIMAL_INTEGER_UPPER: 4230 return true; 4231 default: 4232 return false; 4233 } 4234 } 4235 4236 static boolean isFloat(char c) { 4238 switch (c) { 4239 case SCIENTIFIC: 4240 case SCIENTIFIC_UPPER: 4241 case GENERAL: 4242 case GENERAL_UPPER: 4243 case DECIMAL_FLOAT: 4244 case HEXADECIMAL_FLOAT: 4245 case HEXADECIMAL_FLOAT_UPPER: 4246 return true; 4247 default: 4248 return false; 4249 } 4250 } 4251 4252 static boolean isText(char c) { 4254 switch (c) { 4255 case LINE_SEPARATOR: 4256 case PERCENT_SIGN: 4257 return true; 4258 default: 4259 return false; 4260 } 4261 } 4262 } 4263 4264 private static class DateTime { 4265 static final char HOUR_OF_DAY_0 = 'H'; static final char HOUR_0 = 'I'; static final char HOUR_OF_DAY = 'k'; static final char HOUR = 'l'; static final char MINUTE = 'M'; static final char NANOSECOND = 'N'; static final char MILLISECOND = 'L'; static final char MILLISECOND_SINCE_EPOCH = 'Q'; static final char AM_PM = 'p'; static final char SECONDS_SINCE_EPOCH = 's'; static final char SECOND = 'S'; static final char TIME = 'T'; static final char ZONE_NUMERIC = 'z'; static final char ZONE = 'Z'; 4280 static final char NAME_OF_DAY_ABBREV = 'a'; static final char NAME_OF_DAY = 'A'; static final char NAME_OF_MONTH_ABBREV = 'b'; static final char NAME_OF_MONTH = 'B'; static final char CENTURY = 'C'; static final char DAY_OF_MONTH_0 = 'd'; static final char DAY_OF_MONTH = 'e'; static final char NAME_OF_MONTH_ABBREV_X = 'h'; static final char DAY_OF_YEAR = 'j'; static final char MONTH = 'm'; static final char YEAR_2 = 'y'; static final char YEAR_4 = 'Y'; 4301 static final char TIME_12_HOUR = 'r'; static final char TIME_24_HOUR = 'R'; static final char DATE_TIME = 'c'; 4306 static final char DATE = 'D'; static final char ISO_STANDARD_DATE = 'F'; 4311 static boolean isValid(char c) { 4312 switch (c) { 4313 case HOUR_OF_DAY_0: 4314 case HOUR_0: 4315 case HOUR_OF_DAY: 4316 case HOUR: 4317 case MINUTE: 4318 case NANOSECOND: 4319 case MILLISECOND: 4320 case MILLISECOND_SINCE_EPOCH: 4321 case AM_PM: 4322 case SECONDS_SINCE_EPOCH: 4323 case SECOND: 4324 case TIME: 4325 case ZONE_NUMERIC: 4326 case ZONE: 4327 4328 case NAME_OF_DAY_ABBREV: 4330 case NAME_OF_DAY: 4331 case NAME_OF_MONTH_ABBREV: 4332 case NAME_OF_MONTH: 4333 case CENTURY: 4334 case DAY_OF_MONTH_0: 4335 case DAY_OF_MONTH: 4336 case NAME_OF_MONTH_ABBREV_X: 4339 case DAY_OF_YEAR: 4340 case MONTH: 4341 case YEAR_2: 4347 case YEAR_4: 4348 4349 case TIME_12_HOUR: 4351 case TIME_24_HOUR: 4352 case DATE_TIME: 4354 case DATE: 4355 case ISO_STANDARD_DATE: 4356 return true; 4358 default: 4359 return false; 4360 } 4361 } 4362 } 4363} 4364 | Popular Tags |