Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   *
   * Copyright (c) 2013-2014 sagyf Yang. The Four Group.
   */
  
  package com.github.sog.kit.format;
  
 
Fast simple and yet useful formatting.
 
 public class PrintfFormat {
 
     private static final BigInteger bgInt = new BigInteger("9223372036854775808");  // 2^63
     protected int           width;
     protected int           precision;
     protected StringBuilder pre;
     protected StringBuilder post;
     protected boolean       leadingZeroes;
     protected boolean       showPlus;
     protected boolean       alternate;
     protected boolean       showSpace;
     protected boolean       leftAlign;
     protected boolean       groupDigits;
     protected char          fmt;                    // one of cdeEfgGiosxXos
     protected boolean       countSignInLen;

    
Formats a number in a printf format, like C.

Parameters:
s the format string following printf format string The string has a prefix, a format code and a suffix. The prefix and suffix become part of the formatted output. The format code directs the formatting of the (single) parameter to be formatted. The code has the following structure
  • a % (required)

  • a modifier (optional)
    +
    forces display of + for positive numbers
    ~
    do not count leading + or - in length
    0
    show leading zeroes
    -
    align left in the field
    space
    prepend a space in front of positive numbers
    #
    use "alternate" format. Add 0 or 0x for octal or hexadecimal numbers; add 0b for binary numbers. Don't suppress trailing zeroes in general floating point format.
    ,
    groups decimal values by thousands (for 'diuxXb' formats)

  • an integer denoting field width (optional)

  • a period (.) followed by an integer denoting precision (optional)

  • a format descriptor (required)
    f
    floating point number in fixed format,
    e, E
    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,
    g, G
    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,.
    d, i
    signed long and integer in decimal,
    u
    unsigned long or integer in decimal,
    x
    unsigned long or integer in hexadecimal,
    o
    unsigned long or integer in octal,
    b
    unsigned long or integer in binary,
    s
    string,
    c
    character,
    l, L
    boolean in lower or upper case (for booleans and int/longs).
 
     public PrintfFormat(String s) {
         init(s, 0);
     }

    
 
     public PrintfFormat() {
     }

    
Returns new string created by repeating a single character.
 
     protected static String repeat(char cint n) {
         if (n <= 0) {
             return (.);
         }
         char[] buffer = new char[n];
         for (int i = 0; i < ni++) {
            buffer[i] = c;
        }
        return new String(buffer);
    }
    public PrintfFormat reinit(String s) {
        if ( == null) {
            init(s, 0);
        } else {
            init(s.length());
        }
        return this;
    }
    protected void init(String sint i) {
         = 0;
         = -1;
         = (i == 0 ? new StringBuilder() : new StringBuilder(s.substring(0, i)));
         = new StringBuilder();
         = false;
         = false;
         = false;
         = false;
         = false;
         = true;
         = ' ';
        int length = s.length();
        int parseState;                 // 0 = prefix, 1 = flags, 2 = width, 3 = precision, 4 = format, 5 = end
        // 0: parse string prefix upto first '%'.
        while (true) {
            if (i >= length) {
                throw new IllegalArgumentException("Format string requires '%'.");
            }
            char c = s.charAt(i);
            if (c != '%') {
                .append(c);
                i++;
                continue;
            }
            if (i >= length - 1) {
                throw new IllegalArgumentException("Format string can not end with '%'.");
            }
            if (s.charAt(i + 1) == '%') {       // double '%%'
                .append('%');
                i += 2;
                continue;
            }
            //parseState = 1;                 // single $ founded
            i++;
            break;
        }
        // 1: parse flags
        flagsloop:
        //while (parseState == 1) {
        while (true) {
            if (i >= length) {
                parseState = 5;
                break;
            }
            char c = s.charAt(i);
            switch (c) {
                case ' ':
                     = true;
                    break;
                case '-':
                     = true;
                    break;
                case '+':
                     = true;
                    break;
                case '0':
                     = true;
                    break;
                case '#':
                     = true;
                    break;
                case '~':
                     = false;
                    break;
                case ',':
                     = true;
                    break;
                default:
                    parseState = 2;
                    break flagsloop;
            }
            i++;
        }
        // 2: parse width
        while (parseState == 2) {
            if (i >= length) {
                parseState = 5;
                break;
            }
            char c = s.charAt(i);
            if ((c >= '0') && (c <= '9')) {
                 = ( * 10) + s.charAt(i) - '0';
                i++;
                continue;
            }
            if (s.charAt(i) == '.') {
                parseState = 3;
                 = 0;
                i++;
            } else {
                parseState = 4;
            }
            break;
        }
        // 3: parse precision
        while (parseState == 3) {
            if (i >= length) {
                parseState = 5;
                break;
            }
            char c = s.charAt(i);
            if ((c >= '0') && (c <= '9')) {
                 = ( * 10) + s.charAt(i) - '0';
                i++;
                continue;
            }
            parseState = 4;
            break;
        }
        // 4: parse format
        if (parseState == 4) {
            if (i < length) {
                 = s.charAt(i);
                i++;
//			} else {
//				parseState = 5;
            }
        }
        // append suffix
        if (i < length) {
            .append(s.substring(ilength));
        }
    }

    
Formats a double with exp format.
    protected String expFormat(double d) {
        StringBuilder f = new StringBuilder();
        int e = 0;
        double dd = d;
        double factor = 1;
        if (d != 0) {
            while (dd > 10) {
                e++;
                factor /= 10;
                dd /= 10;
            }
            while (dd < 1) {
                e--;
                factor *= 10;
                dd *= 10;
            }
        }
        if ((( == 'g') || ( == 'G')) && (e >= -4) && (e < )) {
            return fixedFormat(d);
        }
        d *= factor;
        f.append(fixedFormat(d));
        if ( == 'e' ||  == 'g') {
            f.append('e');
        } else {
            f.append('E');
        }
        StringBuilder p = new StringBuilder("000");
        if (e >= 0) {
            f.append('+');
            p.append(e);
        } else {
            f.append('-');
            p.append(-e);
        }
        char[] data = new char[3];
        p.getChars(p.length() - 3, p.length(), data, 0);
        return f.append(data).toString();
    }

    
Formats a double with fixed format.
    protected String fixedFormat(double d) {
        boolean removeTrailing = ( == 'G' ||  == 'g') && !;
        // remove trailing zeroes and decimal point
        if (d > 0x7FFFFFFFFFFFFFFFL) {
            return expFormat(d);
        }
        if ( == 0) {
            return Long.toString(Math.round(d));
        }
        long whole = (longd;
        double fr = d - whole// fractional part
        if (fr >= 1 || fr < 0) {
            return expFormat(d);
        }
        double factor = 1;
        StringBuilder leadingZeroesStr = new StringBuilder();
        for (int i = 1; i <=  && factor <= 0x7FFFFFFFFFFFFFFFL; i++) {
            factor *= 10;
            leadingZeroesStr.append('0');
        }
        long l = Math.round(factor * fr);
        if (l >= factor) {
            l = 0;
            whole++;
        }
        String z = leadingZeroesStr.toString() + l;
        z = '.' + z.substring(z.length() - z.length());
        if (removeTrailing) {
            int t = z.length() - 1;
            while (t >= 0 && z.charAt(t) == '0') {
                t--;
            }
            if (t >= 0 && z.charAt(t) == '.') {
                t--;
            }
            z = z.substring(0, t + 1);
        }
        return whole + z;
    }

    
Pads the value with spaces and adds prefix and suffix.
    protected String pad(String value) {
        String spaces = repeat(' ' - value.length());
        if () {
            return  + value + spaces + ;
        } else {
            return  + spaces + value + ;
        }
    }
    private String getAltPrefixFor(char fmtString currentPrefix) {
        switch (fmt) {
            case 'x':
                return "0x";
            case 'X':
                return "0X";
            case 'b':
                return "0b";
            case 'B':
                return "0B";
            default:
                return currentPrefix;
        }
    }
    protected String sign(int sString r) {
        String p = .;
        if (s < 0) {
            p = .;
        } else if (s > 0) {
            if () {
                p = .;
            } else if () {
                p = .;
            }
        } else {
            if () {
                if ( == 'o' && r.length() > 0 && r.charAt(0) != '0') {
                    p = "0";
                } else {
                    p = getAltPrefixFor(p);
                }
            }
        }
        int w = 0;
        if () {
            w = ;
        } else if (( == 'u' ||  == 'd' ||  == 'i' ||  == 'x' ||  == 'X' ||  == 'o') &&  > 0) {
            w = ;
        }
        if () {
            return p + repeat('0'w - p.length() - r.length()) + r;
        } else {
            return p + repeat('0'w - r.length()) + r;
        }
    }

    
Groups numbers by inserting 'separator' after every group of 'size' digits, starting from the right.
    protected String groupDigits(String valueint sizechar separator) {
        if (!) {
            return value;
        }
        StringBuilder r = new StringBuilder(value.length() + 10);
        int ndx = 0;
        int len = value.length() - 1;
        int mod = len % size;
        while (ndx < len) {
            r.append(value.charAt(ndx));
            if (mod == 0) {
                r.append(separator);
                mod = size;
            }
            mod--;
            ndx++;
        }
        r.append(value.charAt(ndx));
        return r.toString();
    }
    // ---------------------------------------------------------------- public form methods

    
Formats a character into a string (like sprintf in C).
    public String form(char value) {
        if ( != 'c') {
            throw new IllegalArgumentException("Invalid format: '" +  + "' is not 'c'.");
        }
        return pad(String.valueOf(value));
    }

    
Formats a boolean into a string (like sprintf in C).
    public String form(boolean value) {
        if ( == 'l') {
            return pad(value ? "true" : "false");
        }
        if ( == 'L') {
            return pad(value ? "TRUE" : "FALSE");
        }
        throw new IllegalArgumentException("Invalid format: '" +  + "' is not one of 'bB'.");
    }

    
Formats a double into a string (like sprintf in C).
    public String form(double x) {
        String r;
        if ( < 0) {
             = 6;
        }
        int s = 1;
        if (x < 0) {
            x = -x;
            s = -1;
        }
        if ( == 'f') {
            r = fixedFormat(x);
        } else if ( == 'e' ||  == 'E' ||  == 'g' ||  == 'G') {
            r = expFormat(x);
        } else {
            throw new IllegalArgumentException("Invalid format: '" +  + "' is not one of 'feEgG'.");
        }
        return pad(sign(sr));
    }

    
Formats a long integer into a string (like sprintf in C).
    public String form(long x) {
        String r;
        int s = 0;
        switch () {
            case 'd':
                if (x < 0) {
                    r = Long.toString(x).substring(1);
                    s = -1;
                } else {
                    r = Long.toString(x);
                    s = 1;
                }
                r = groupDigits(r, 3, ',');
                break;
            case 'i':
                int xx = (intx;
                if (xx < 0) {
                    r = Integer.toString(xx).substring(1);
                    s = -1;
                } else {
                    r = Integer.toString(xx);
                    s = 1;
                }
                r = groupDigits(r, 3, ',');
                break;
            case 'u':
                if (x < 0) {
                    long xl = x & 0x7FFFFFFFFFFFFFFFL;
                    r = Long.toString(xl);
                    BigInteger bi = new BigInteger(r);
                    r = bi.add().toString();
                } else {
                    r = Long.toString(x);
                }
                r = groupDigits(r, 3, ',');
                s = 1;
                break;
            case 'o':
                r = Long.toOctalString(x);
                break;
            case 'x':
                r = Long.toHexString(x);
                r = groupDigits(r, 4, ' ');
                break;
            case 'X':
                r = Long.toHexString(x).toUpperCase();
                r = groupDigits(r, 4, ' ');
                break;
            case 'b':
            case 'B':
                r = Long.toBinaryString(x);
                r = groupDigits(r, 8, ' ');
                break;
            case 'l':
                r = (x == 0 ? "false" : "true");
                break;
            case 'L':
                r = (x == 0 ? "FALSE" : "TRUE");
                break;
            default:
                throw new IllegalArgumentException("Invalid format: '" +  + "' is not one of 'diuoxXblL'.");
        }
        return pad(sign(sr));
    }

    
Formats an integer into a string (like sprintf in C).
    public String form(int x) {
        String r;
        int s = 0;
        switch () {
            case 'd':
            case 'i':
                if (x < 0) {
                    r = Integer.toString(x).substring(1);
                    s = -1;
                } else {
                    r = Integer.toString(x);
                    s = 1;
                }
                r = groupDigits(r, 3, ',');
                break;
            case 'u':
                long xl = x & 0x00000000FFFFFFFFL;
                r = Long.toString(xl);
                r = groupDigits(r, 3, ',');
                s = 1;
                break;
            case 'o':
                r = Integer.toOctalString(x);
                break;
            case 'x':
                r = Integer.toHexString(x);
                r = groupDigits(r, 4, ' ');
                break;
            case 'X':
                r = Integer.toHexString(x).toUpperCase();
                r = groupDigits(r, 4, ' ');
                break;
            case 'b':
            case 'B':
                r = Integer.toBinaryString(x);
                r = groupDigits(r, 8, ' ');
                break;
            case 'l':
                r = (x == 0 ? "false" : "true");
                break;
            case 'L':
                r = (x == 0 ? "FALSE" : "TRUE");
                break;
            default:
                throw new IllegalArgumentException("Invalid format: '" +  + "' is not one of 'diuoxXblL'.");
        }
        return pad(sign(sr));
    }

    
Formats a byte into a string (like sprintf in C).
    public String form(byte b) {
        return formInt(b, 0xFF);
    }

    
Formats a short into a string (like sprintf in C).
    public String form(short s) {
        return formInt(s, 0xFFFF);
    }

    
Formatter for both byte and short values.
    private String formInt(int valueint unsignedMask) {
        String r;
        int s = 0;
        switch () {
            case 'd':
            case 'i':
                if (value < 0) {
                    r = Integer.toString(value).substring(1);
                    s = -1;
                } else {
                    r = Integer.toString(value);
                    s = 1;
                }
                r = groupDigits(r, 3, ',');
                break;
            case 'u':
                int xl = value & unsignedMask;
                r = Integer.toString(xl);
                r = groupDigits(r, 3, ',');
                s = 1;
                break;
            case 'o':
                r = Integer.toOctalString(value & unsignedMask);
                break;
            case 'x':
                r = Integer.toHexString(value & unsignedMask);
                r = groupDigits(r, 4, ' ');
                break;
            case 'X':
                r = Integer.toHexString(value & unsignedMask).toUpperCase();
                r = groupDigits(r, 4, ' ');
                break;
            case 'b':
            case 'B':
                r = Integer.toBinaryString(value & unsignedMask);
                r = groupDigits(r, 8, ' ');
                break;
            case 'l':
                r = (value == 0 ? "false" : "true");
                break;
            case 'L':
                r = (value == 0 ? "FALSE" : "TRUE");
                break;
            default:
                throw new IllegalArgumentException("Invalid format: '" +  + "' is not one of 'diuoxXblL'.");
        }
        return pad(sign(sr));
    }

    
Formats a string into a larger string (like sprintf in C).
    public String form(String s) {
        if ( != 's') {
            throw new IllegalArgumentException("Invalid format: '" +  + "' is not 's'.");
        }
        if ( >= 0 &&  < s.length()) {
            s = s.substring(0, );
        }
        return pad(s);
    }
New to GrepCode? Check out our FAQ X