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: < becomes &lt;, * > becomes &gt; & becomes &amp; * ' becomes &#039, " becomes &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 + -
显示快捷键?