diff options
Diffstat (limited to 'libjava/java/text/ChoiceFormat.java')
-rw-r--r-- | libjava/java/text/ChoiceFormat.java | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/libjava/java/text/ChoiceFormat.java b/libjava/java/text/ChoiceFormat.java new file mode 100644 index 00000000000..bed62a75e53 --- /dev/null +++ b/libjava/java/text/ChoiceFormat.java @@ -0,0 +1,310 @@ +// ChoiceFormat.java - Formatter for `switch'-like string substitution. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.text; + +import java.util.Vector; + +/** + * @author Tom Tromey <tromey@cygnus.com> + * @date March 9, 1999 + */ +/* Written using "Java Class Libraries", 2nd edition, plus online + * API docs for JDK 1.2 from http://www.javasoft.com. + * Status: Believed complete and correct to 1.1. + */ + +public class ChoiceFormat extends NumberFormat +{ + // Note: we assume the same kind of quoting rules apply here. + // This isn't explicitly documented. But for instance we accept + // '#' as a literal hash in a format string. + public void applyPattern (String newPattern) + { + int index = 0, max = newPattern.length(); + Vector stringVec = new Vector (); + Vector limitVec = new Vector (); + StringBuffer buf = new StringBuffer (); + + while (true) + { + // Find end of double. + int dstart = index; + while (index < max) + { + char c = newPattern.charAt(index); + if (c == '#' || c == '\u2064' || c == '<') + break; + ++index; + } + + if (index == max) + throw new IllegalArgumentException ("unexpected end of text"); + Double d = new Double (newPattern.substring(dstart, index)); + + if (newPattern.charAt(index) == '<') + d = new Double (nextDouble (d.doubleValue())); + + limitVec.addElement(d); + + // Scan text. + ++index; + buf.setLength(0); + while (index < max) + { + char c = newPattern.charAt(index); + if (c == '\'' && index < max + 1 + && newPattern.charAt(index + 1) == '\'') + { + buf.append(c); + ++index; + } + else if (c == '\'' && index < max + 2) + { + buf.append(newPattern.charAt(index + 1)); + index += 2; + } + else if (c == '|') + break; + else + buf.append(c); + ++index; + } + + stringVec.addElement(buf.toString()); + if (index == max) + break; + ++index; + } + + strings = new String[stringVec.size()]; + stringVec.copyInto(strings); + + limits = new double[limitVec.size()]; + for (int i = 0; i < limits.length; ++i) + { + Double d = (Double) limitVec.elementAt(i); + limits[i] = d.doubleValue(); + } + } + + public ChoiceFormat (String newPattern) + { + super (); + applyPattern (newPattern); + } + + public ChoiceFormat (double[] limits, String[] strings) + { + super (); + setChoices (limits, strings); + } + + public Object clone () + { + return new ChoiceFormat (limits, strings); + } + + public boolean equals (Object obj) + { + if (! (obj instanceof ChoiceFormat)) + return false; + ChoiceFormat cf = (ChoiceFormat) obj; + if (limits.length != cf.limits.length) + return false; + for (int i = limits.length - 1; i >= 0; --i) + { + if (limits[i] != cf.limits[i] + || !strings[i].equals(cf.strings[i])) + return false; + } + return true; + } + + public StringBuffer format (long num, StringBuffer appendBuf, + FieldPosition pos) + { + return format ((double) num, appendBuf, pos); + } + + public StringBuffer format (double num, StringBuffer appendBuf, + FieldPosition pos) + { + if (limits.length == 0) + return appendBuf; + + int index = 0; + if (! Double.isNaN(num) && num >= limits[0]) + { + for (; index < limits.length - 1; ++index) + { + if (limits[index] <= num + && index != limits.length - 2 + && num < limits[index + 1]) + break; + } + } + + return appendBuf.append(strings[index]); + } + + public Object[] getFormats () + { + return (Object[]) strings.clone(); + } + + public double[] getLimits () + { + return (double[]) limits.clone(); + } + + public int hashCode () + { + int hash = 0; + for (int i = 0; i < limits.length; ++i) + { + long v = Double.doubleToLongBits(limits[i]); + hash ^= (v ^ (v >>> 32)); + hash ^= strings[i].hashCode(); + } + return hash; + } + + public static final double nextDouble (double d) + { + return nextDouble (d, true); + } + + public static final double nextDouble (double d, boolean next) + { + if (Double.isInfinite(d) || Double.isNaN(d)) + return d; + + long bits = Double.doubleToLongBits(d); + + long mantMask = (1L << mantissaBits) - 1; + long mantissa = bits & mantMask; + + long expMask = (1L << exponentBits) - 1; + long exponent = (bits >>> mantissaBits) & expMask; + + if (next ^ (bits < 0)) // Increment magnitude + { + if (mantissa == (1L << mantissaBits) - 1) + { + mantissa = 0L; + exponent++; + + // Check for absolute overflow. + if (exponent >= (1L << mantissaBits)) + return (bits > 0) ? Double.POSITIVE_INFINITY + : Double.NEGATIVE_INFINITY; + } + else + mantissa++; + } + else // Decrement magnitude + { + if (exponent == 0L && mantissa == 0L) + { + // The only case where there is a change of sign + return next ? Double.MIN_VALUE : -Double.MIN_VALUE; + } + else + { + if (mantissa == 0L) + { + mantissa = (1L << mantissaBits) - 1; + exponent--; + } + else + mantissa--; + } + } + + long result = bits < 0 ? 1 : 0; + result = (result << exponentBits) | exponent; + result = (result << mantissaBits) | mantissa; + return Double.longBitsToDouble(result); + } + + public Number parse (String sourceStr, ParsePosition pos) + { + int index = pos.getIndex(); + for (int i = 0; i < limits.length; ++i) + { + if (sourceStr.startsWith(strings[i], index)) + { + pos.setIndex(index + strings[i].length()); + return new Double (limits[i]); + } + } + pos.setErrorIndex(index); + return new Double (Double.NaN); + } + + public static final double previousDouble (double d) + { + return nextDouble (d, false); + } + + public void setChoices (double[] limits, String[] strings) + { + if (limits == null || strings == null) + throw new NullPointerException (); + if (limits.length != strings.length) + throw new IllegalArgumentException (); + this.strings = (String[]) strings.clone(); + this.limits = (double[]) limits.clone(); + } + + private final void quoteString (StringBuffer dest, String text) + { + int max = text.length(); + for (int i = 0; i < max; ++i) + { + char c = text.charAt(i); + if (c == '\'') + { + dest.append(c); + dest.append(c); + } + else if (c == '#' || c == '|' || c == '\u2064' || c == '<') + { + dest.append('\''); + dest.append(c); + dest.append('\''); + } + else + dest.append(c); + } + } + + public String toPattern () + { + StringBuffer result = new StringBuffer (); + for (int i = 0; i < limits.length; ++i) + { + result.append(limits[i]); + result.append('#'); + quoteString (result, strings[i]); + } + return result.toString(); + } + + // Formats and limits. + private String[] strings; + private double[] limits; + + // Number of mantissa bits in double. + private static final int mantissaBits = 52; + // Number of exponent bits in a double. + private static final int exponentBits = 11; +} |