All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openscience.cdk.tools.FormatStringBuffer Maven / Gradle / Ivy

There is a newer version: 2.9
Show newest version
/* Copyright (C) 2002  Antti S. Brax
 *
 *  FormatStringBuffer: printf style output formatter for Java
 *  All rights reserved.
 *
 *  Downloaded from: http://www.cs.helsinki.fi/u/abrax/HACK/JAVA/PRINTF.html
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *  - Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *
 *  - The names of the contributors may not be used to endorse or promote
 *  products derived from this software without specific prior written
 *  permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.openscience.cdk.tools;


import java.text.DecimalFormat;
import java.text.NumberFormat;

/**
 * A class for formatting output similar to the C printf command.
 *
 * 

Some features provided by ANSI C-standard conformant printfs * are not supported because of language constraints. * *

Supported conversion specifiers are: 'c', 'd', 'e', 'E', 'f', 'g' * (works like 'f'), 'i', 'o', 's', 'x' and 'X'. * *

Supported conversion flags are: '#', '0', '-', ' ' (a space) and '+'. * *

Support for conversion flag '*' is under development. * * @author Antti S. Brax ([email protected], base implementation) * @author Fred Long (flong(AT)skcc.org, implemented 'e', 'E' and 'g') * @version 1.7 * @cdk.module standard * @cdk.githash * @cdk.license BSD */ public class FormatStringBuffer { // ==================================================================== // /** Pad with zero instead of space. */ private static final int ZEROPAD = 1; /** Unsigned/signed long. */ //private static final int SIGN = 2; /** Show plus sign. */ private static final int PLUS = 4; /** Space if plus. */ private static final int SPACE = 8; /** Left justified. */ private static final int LEFT = 16; /** Prepend hex digits with '0x' and octal with '0' */ private static final int SPECIAL = 32; /** Use upper case hex digits. */ private static final int LARGE = 64; /** Use scientific notation */ private static final int SCI = 128; /** Use upper case E */ private static final int UPPER = 256; /** Use grouping character */ private static final int GROUPING = 512; // ==================================================================== // /** Format a char. */ private static final int CHAR = 0; /** Format a String. */ private static final int STRING = 1; /** Format a decimal number. */ private static final int DECIMAL = 2; /** Format a floating point number. */ private static final int FLOAT = 3; // ==================================================================== // /** The format string. */ private String format = null; /** The buffer. */ private StringBuffer buffer = null; /** The current index. */ private int index = 0; // ==================================================================== // /** * Create a new FormatStringBuffer. * * @param format the format string. */ public FormatStringBuffer(String format) { reset(format); } /** * Reset this FormatStringBuffer. * * @param format the format string. */ public FormatStringBuffer reset(String format) { reset(); this.format = format; return this; } /** * Reset this FormatStringBuffer with the format string * given in the constructor or last call to reset(String). * This is automatically called after toString(). */ public FormatStringBuffer reset() { this.buffer = new StringBuffer(); this.index = 0; return this; } // ==================================================================== // /** * Get the next format token from the format string. Copy every * character from format to buffer between * index and the next format token. */ private Format getFormat() { char ch; while (index < format.length()) { if ((ch = format.charAt(index)) != '%') { buffer.append(ch); index++; continue; } Format fmt = new Format(); // Process flags. boolean repeat = true; while (repeat) { if (index + 1 >= format.length()) throw new IllegalArgumentException("Malformed format"); switch (ch = format.charAt(++index)) { // Skip the first '%' case '-': fmt.flags |= LEFT; break; case '+': fmt.flags |= PLUS; break; case ' ': fmt.flags |= SPACE; break; case '#': fmt.flags |= SPECIAL; break; case '0': fmt.flags |= ZEROPAD; break; case '\'': fmt.flags |= GROUPING; break; default: repeat = false; break; } } // Get field width. if (Character.isDigit(ch)) { // Explicit number. fmt.fieldWidth = skipDigits(); } if (index >= format.length()) throw new IllegalArgumentException("Malformed format"); // Get precision. if ((ch = format.charAt(index)) == '.') { if (++index >= format.length()) throw new IllegalArgumentException("Malformed format"); fmt.precision = skipDigits(); if (fmt.precision < 0) { fmt.precision = 0; } } if (index >= format.length()) throw new IllegalArgumentException("Malformed format"); switch (ch = format.charAt(index++)) { case 'c': fmt.type = CHAR; return fmt; case 's': fmt.type = STRING; return fmt; case '%': buffer.append('%'); continue; // Octal, hexadecimal and decimal. case 'o': fmt.type = DECIMAL; fmt.base = 8; return fmt; case 'X': fmt.flags |= LARGE; case 'x': fmt.type = DECIMAL; fmt.base = 16; return fmt; case 'd': case 'i': fmt.type = DECIMAL; return fmt; // Floating point case 'f': case 'g': fmt.type = FLOAT; return fmt; case 'e': fmt.type = FLOAT; fmt.flags |= SCI; return fmt; case 'E': fmt.type = FLOAT; fmt.flags |= SCI; fmt.flags |= UPPER; return fmt; default: buffer.append('%'); buffer.append(ch); continue; } } return null; } /** * Skip digits and return the number they form. */ private int skipDigits() { char ch; int i = 0; while (index < format.length()) { if (Character.isDigit(ch = format.charAt(index))) { index++; i = i * 10 + Character.digit(ch, 10); } else { break; } } return i; } // ==================================================================== // /** * Format a char. */ public FormatStringBuffer format(char ch) { Format fmt = getFormat(); if (fmt.type != CHAR) throw new IllegalArgumentException("Expected a char format"); if ((fmt.flags & LEFT) != LEFT) while (--fmt.fieldWidth > 0) buffer.append(' '); buffer.append(ch); while (--fmt.fieldWidth > 0) buffer.append(' '); return this; } /** * Format a float. */ public FormatStringBuffer format(float flt) { return format((double) flt); } /** * Format a double. */ public FormatStringBuffer format(double dbl) { Format fmt = getFormat(); if (fmt.type != FLOAT) throw new IllegalArgumentException("Expected a float format"); NumberFormat nf; if ((fmt.flags & SCI) > 0) { nf = new DecimalFormat("0.#E00"); } else { nf = NumberFormat.getInstance(); } nf.setGroupingUsed((fmt.flags & GROUPING) != 0); if (fmt.precision != -1) { nf.setMaximumFractionDigits(fmt.precision); nf.setMinimumFractionDigits(fmt.precision); } else { nf.setMaximumFractionDigits(Integer.MAX_VALUE); nf.setMinimumFractionDigits(1); } String str = nf.format(dbl); if ((fmt.flags & SCI) == SCI && (fmt.flags & UPPER) == 0) { str = str.replace('E', 'e'); } if ((fmt.flags & PLUS) == PLUS && dbl >= 0.0) str = "+" + str; int len = str.length(); if ((fmt.flags & LEFT) != LEFT) while (len < fmt.fieldWidth--) buffer.append(' '); for (int i = 0; i < len; ++i) buffer.append(str.charAt(i)); while (len < fmt.fieldWidth--) buffer.append(' '); return this; } /** * Format a float. */ public FormatStringBuffer format(int i) { return format((long) i); } /** * Format a float. */ public FormatStringBuffer format(long l) { Format fmt = getFormat(); if (fmt.type != DECIMAL) throw new IllegalArgumentException("Expected a float format"); // Decide padding character. char pad = ' '; if ((fmt.flags & ZEROPAD) == ZEROPAD) { pad = '0'; } // Convert number to String. String str; String prefix = ""; switch (fmt.base) { case 8: str = Long.toOctalString(l); if ((fmt.flags & SPECIAL) == SPECIAL) { fmt.fieldWidth -= 1; prefix = "0"; } break; case 16: str = Long.toHexString(l); if ((fmt.flags & SPECIAL) == SPECIAL) { fmt.fieldWidth -= 2; prefix = "0x"; } break; default: str = String.valueOf(Math.abs(l)); break; } if ((fmt.flags & LARGE) == LARGE) { str = str.toUpperCase(); prefix = prefix.toUpperCase(); } int len = str.length(); if (l < 0 || (fmt.flags & PLUS) == PLUS) { fmt.fieldWidth--; } // Place the sign character first if zero padding. if ((fmt.flags & ZEROPAD) == ZEROPAD) { if (l < 0 && fmt.base == 10) { buffer.append('-'); } else if ((fmt.flags & PLUS) == PLUS && fmt.base == 10) { buffer.append('+'); } buffer.append(prefix); } // Pad. if ((fmt.flags & LEFT) != LEFT) while (len < fmt.fieldWidth--) buffer.append(pad); // Place the sign character now if not zero padding. if ((fmt.flags & ZEROPAD) != ZEROPAD) { if (l < 0 && fmt.base == 10) { buffer.append('-'); } else if ((fmt.flags & PLUS) == PLUS && fmt.base == 10) { buffer.append('+'); } buffer.append(prefix); } for (int i = 0; i < len; ++i) buffer.append(str.charAt(i)); while (len < fmt.fieldWidth--) buffer.append(' '); return this; } /** * Format a String. */ public FormatStringBuffer format(String str) { if (str == null) str = ""; Format fmt = getFormat(); if (fmt.type != STRING) throw new IllegalArgumentException("Expected a String format"); int len = str.length(); if (fmt.precision != -1 && len > fmt.precision) len = fmt.precision; if ((fmt.flags & LEFT) != LEFT) while (len < fmt.fieldWidth--) buffer.append(' '); for (int i = 0; i < len; ++i) buffer.append(str.charAt(i)); while (len < fmt.fieldWidth--) buffer.append(' '); return this; } // ==================================================================== // /** * Get the result of the formatting. reset() is automatically * called from this method. */ @Override public String toString() { if (index < format.length()) buffer.append(format.substring(index)); String str = buffer.toString(); this.reset(); return str; } // ==================================================================== // /** * A container class for several format parameters. */ private class Format { public int flags = 0; public int fieldWidth = -1; public int precision = -1; public int type = -1; public int base = 10; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy