sprintf.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 807 行 · 第 1/2 页

JAVA
807
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the *   Free SoftwareFoundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Sam */package com.caucho.util;public class Sprintf {  private static final L10N L = new L10N(Sprintf.class);  /** copied then modified from com.caucho.es.Printf */  private final static int ALT = 0x01;  private final static int ZERO_FILL = 0x02;  private final static int POS_PLUS = 0x04;  private final static int POS_SPACE = 0x08;  private final static int LALIGN = 0x10;  private final static int BIG = 0x20;  private final static int NO_TRAIL_ZERO = 0x40;  private final static int JAVAESCAPE = 0x80;  private final static int CSVESCAPE = 0x100;  private final static int XMLESCAPE = 0x200;  private static char []digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',                                  'a', 'b', 'c', 'd', 'e', 'f'};  private static char []bigDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',                                     'A', 'B', 'C', 'D', 'E', 'F'};  /**   * An implementation of the classic sprintf.<p>   *   * `sprintf' accepts a series of arguments, applies to each a format    * specifier  from `format', and returns the formatted data as a string.   * `format' is a string containing two types of objects:  ordinary   * characters (other than `%'), which are copied unchanged to the output, and   * conversion specifications, each of which is introduced by `%'. (To include   * `%' in the output, use `%%' in the format string). <p>   *   * A conversion specification has the following form:   *   * <pre>%[FLAGS][WIDTH][.PREC][TYPE]</pre>   *   * TYPE is required, the rest are optional.   *   * The following TYPE's are supported:   *   * <table>   * <tr><td>%%<td>a percent sign   * <tr><td>%c<td>a character with the given number   * <tr><td>%s<td>a string, a null string becomes "#null"   * <tr><td>%z<td>a string, a null string becomes the empty string ""   * <tr><td>%d<td>a signed integer, in decimal   * <tr><td>%o<td>an integer, in octal   * <tr><td>%u<td>an integer, in decimal   * <tr><td>%x<td>an integer, in hexadecimal   * <tr><td>%X<td>an integer, in hexadecimal using upper-case letters   * <tr><td>%e<td>a floating-point number, in scientific notation   * <tr><td>%E<td>a floating-point number, like %e with an upper-case "E"   * <tr><td>%f<td>a floating-point number, in fixed decimal notation   * <tr><td>%g<td>a floating-point number, in %e or %f notation   * <tr><td>%G<td>a floating-point number, like %g with an upper-case "E"   * <tr><td>%p<td>a pointer (outputs a value like the default of toString())   * </table>   *   * Intepret the word `integer' to mean the java type long.     * Since java does not support unsigned integers, all integers are treated    * the same.<p>   *    * The following optional FLAGS are supported:   * <table>   * <tr><td>0<td>If the TYPE character is an integer leading zeroes are used    *              to pad the field width instead of spaces (following any    *              indication of sign or base).   *   * <tr><td>+<td>Include a `+' with positive numbers.   *   * <tr><td>(a space)<td>use a space placeholder for the `+' that would result   *                      from a positive number   * <tr><td>-<td>The result of is left justified, and the right is padded with   *              blanks until the result is `WIDTH' in length.  If you do not    *              use this flag, the result is right justified, and padded on    *              the left.   * <tr><td>#<td>an alternate display is used, for `x' and `X' a   *              non-zero result will have an "0x" prefix; for floating    *              point numbers the result will always contain a decimal point.   *   * <tr><td>j<td>escape a string suitable for a Java string, or a CSV file.    *              The following escapes are applied: " becomes \",    *              newline becomes \n, return becomes \r, \ becomes \\.   *   * <tr><td>v<td>escape a string suitable for CSV files, the same as `j'   *              with an additional <code>"</code> placed at the beginning    *              and ending of the string   *   * <tr><td>m<td>escape a string suitable for a XML file.  The following   *              escapes are applied: &lt; becomes &amp;lt;,    *              &gt; becomes &amp;gt; &amp; becomes &amp;amp;   *              ' becomes &amp;#039, " becomes &amp;034;   * </table>   *   * The optional WIDTH argument specifies a minium width for the field.   * Spaces are used unless the `0' FLAG was used to indicate 0 padding.<p>   *   * The optional PREC argument is introduced with a `.', and gives the    * maximum number of characters to print; or the minimum   * number of digits to print for integer and hex values; or the maximum    * number of significant digits for `g' and `G'; or the number of digits    * to print after the decimal point for floating points.<p>   */  public static String sprintf(String format, Object[] args)  {    String ret;    CharBuffer cb = CharBuffer.allocate();    try {      sprintf(cb,format,args);    }    finally {      ret = cb.close();    }    return ret;  }  public static String sprintf(String format, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9)  {    return sprintf(format, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 } );  }  public static String sprintf(String format, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8)  {    return sprintf(format, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 } );  }  public static String sprintf(String format, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7)  {    return sprintf(format, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 } );  }  public static String sprintf(String format, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6)  {    return sprintf(format, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6 } );  }  public static String sprintf(String format, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)  {    return sprintf(format, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5 } );  }  public static String sprintf(String format, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4)  {    return sprintf(format, new Object[] { arg0, arg1, arg2, arg3, arg4 } );  }  public static String sprintf(String format, Object arg0, Object arg1, Object arg2, Object arg3)  {    return sprintf(format, new Object[] { arg0, arg1, arg2, arg3 } );  }  public static String sprintf(String format, Object arg0, Object arg1, Object arg2)  {    return sprintf(format, new Object[] { arg0, arg1, arg2 } );  }  public static String sprintf(String format, Object arg0, Object arg1)  {    return sprintf(format, new Object[] { arg0, arg1 } );  }  public static String sprintf(String format, Object arg0)  {    return sprintf(format, new Object[] { arg0 } );  }  public static CharBuffer sprintf(CharBuffer result,                                   String format,                                   Object ... args)  {    int length = args.length;    int arg = 0;    int len = format.length();    for (int i = 0; i < len; i++) {      int ch;      int start = i;      if ((ch = format.charAt(i)) != '%') {        result.append((char) ch);        continue;      }      int flags = 0;    loop:      while (++i < len) {        switch ((ch = format.charAt(i))) {        case '0': flags |= ZERO_FILL; break;        case '+': flags |= POS_PLUS; break;        case ' ': flags |= POS_SPACE; break;        case '#': flags |= ALT; break;        case '-': flags |= LALIGN; break;        case 'j': flags |= JAVAESCAPE; break;        case 'v': flags |= JAVAESCAPE; flags |= CSVESCAPE; break;        case 'm': flags |= XMLESCAPE; break;        default: break loop;        }      }      int width = 0;      for (; i < len && (ch = format.charAt(i)) >= '0' && ch <= '9'; i++) {        width = 10 * width + ch - '0';      }      if (i >= len) {        fixBits(result, format, start, i);        break;      }      int prec = 0;      if (ch == '.') {        while (++i < len && (ch = format.charAt(i)) >= '0' && ch <= '9') {          prec = 10 * prec + ch - '0';        }      } else        prec = -1;      if (i >= len) {        fixBits(result, format, start, i);        break;      }      switch (ch) {      case '%':        result.append((char) '%');        break;      case 'd':      case 'D':      case 'i':      case 'u':      case 'U':        if (arg >= length)          missing(arg);        formatInteger(result, toLong(args[arg++]), width, prec, flags, 10);        break;      case 'o':      case 'O':        if (arg >= length)          missing(arg);        formatInteger(result, toLong(args[arg++]), width, prec, flags, 8);        break;      case 'X':        flags |= BIG;      case 'x':        if (arg >= length)          missing(arg);        formatInteger(result, toLong(args[arg++]), width, prec, flags, 16);        break;      case 'E':      case 'G':        flags |= BIG;      case 'f':      case 'e':      case 'g':        if (arg >= length)          missing(arg);        formatDouble(result, toDouble(args[arg++]), width, prec, flags, ch);        break;      case 'c':        if (arg >= length)          missing(arg);        formatChar(result, toLong(args[arg++]), width, flags);        break;      case 's':        if (arg >= length)          missing(arg);        formatString(result, toString(args[arg++],"#null"), prec, width, flags);        break;      case 'z':        if (arg >= length)          missing(arg);        formatString(result, toString(args[arg++],""), prec, width, flags);        break;      case 'p':        if (arg >= length)          missing(arg);        // like the default for toString()        Object o  = args[arg++];        result.append(o.getClass().getName());        result.append('@');        result.append(Integer.toHexString(o.hashCode()));      default:        fixBits(result, format, start, i + 1);        break;      }    }    return result;  }  private static void missing(int arg)  {    throw new IllegalArgumentException(L.l("missing sprintf argument {0}",arg));  }  public static void formatDouble(CharBuffer cb, double value,                                  int prec, int flags, int type)  {    String raw = Double.toString(value);    int expt = 0;    int i = 0;    CharBuffer digits = new CharBuffer();    int ch = raw.charAt(i);    boolean seenDigit = false;    // XXX: locale screws us?    for (; i < raw.length(); i++) {      if ((ch = raw.charAt(i)) == '.' || ch == 'e' || ch == 'E')        break;      else if (! seenDigit && ch == '0') {      }      else {        seenDigit = true;        digits.append((char) ch);        expt++;      }    }    if (ch == '.')      i++;    for (; i < raw.length(); i++) {      ch = raw.charAt(i);      if (! seenDigit && ch == '0') {        expt--;      } else if (ch >= '0' && ch <= '9') {        digits.append((char) ch);        seenDigit = true;      }      else {        int sign = 1;        i++;        if ((ch = raw.charAt(i)) == '+') {          i++;        }        else if (ch == '-') {          i++;          sign = -1;        }        int e = 0;        for (; i < raw.length() && (ch = raw.charAt(i)) >= '0' && ch <= '9';             i++) {          e = 10 * e + ch - '0';        }        expt += sign * e;        break;      }    }    if (! seenDigit)      expt = 1;    while (digits.length() > 0 && digits.charAt(digits.length() - 1) == '0')      digits.setLength(digits.length() - 1);    if (type == 'f') {      if (roundDigits(digits, expt + prec)) {        expt++;      }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?