gcc/libjava/java/text/ChoiceFormat.java

313 lines
7.4 KiB
Java
Raw Normal View History

1999-04-07 22:42:40 +08:00
// ChoiceFormat.java - Formatter for `switch'-like string substitution.
/* Copyright (C) 1999, 2000 Free Software Foundation
1999-04-07 22:42:40 +08:00
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;
}
choiceFormats = new String[stringVec.size()];
stringVec.copyInto(choiceFormats);
1999-04-07 22:42:40 +08:00
choiceLimits = new double[limitVec.size()];
for (int i = 0; i < choiceLimits.length; ++i)
1999-04-07 22:42:40 +08:00
{
Double d = (Double) limitVec.elementAt(i);
choiceLimits[i] = d.doubleValue();
1999-04-07 22:42:40 +08:00
}
}
public ChoiceFormat (String newPattern)
{
super ();
applyPattern (newPattern);
}
public ChoiceFormat (double[] choiceLimits, String[] choiceFormats)
1999-04-07 22:42:40 +08:00
{
super ();
setChoices (choiceLimits, choiceFormats);
1999-04-07 22:42:40 +08:00
}
public Object clone ()
{
return new ChoiceFormat (choiceLimits, choiceFormats);
1999-04-07 22:42:40 +08:00
}
public boolean equals (Object obj)
{
if (! (obj instanceof ChoiceFormat))
return false;
ChoiceFormat cf = (ChoiceFormat) obj;
if (choiceLimits.length != cf.choiceLimits.length)
1999-04-07 22:42:40 +08:00
return false;
for (int i = choiceLimits.length - 1; i >= 0; --i)
1999-04-07 22:42:40 +08:00
{
if (choiceLimits[i] != cf.choiceLimits[i]
|| !choiceFormats[i].equals(cf.choiceFormats[i]))
1999-04-07 22:42:40 +08:00
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 (choiceLimits.length == 0)
1999-04-07 22:42:40 +08:00
return appendBuf;
int index = 0;
if (! Double.isNaN(num) && num >= choiceLimits[0])
1999-04-07 22:42:40 +08:00
{
for (; index < choiceLimits.length - 1; ++index)
1999-04-07 22:42:40 +08:00
{
if (choiceLimits[index] <= num
&& index != choiceLimits.length - 2
&& num < choiceLimits[index + 1])
1999-04-07 22:42:40 +08:00
break;
}
}
return appendBuf.append(choiceFormats[index]);
1999-04-07 22:42:40 +08:00
}
public Object[] getFormats ()
{
return (Object[]) choiceFormats.clone();
1999-04-07 22:42:40 +08:00
}
public double[] getLimits ()
{
return (double[]) choiceLimits.clone();
1999-04-07 22:42:40 +08:00
}
public int hashCode ()
{
int hash = 0;
for (int i = 0; i < choiceLimits.length; ++i)
1999-04-07 22:42:40 +08:00
{
long v = Double.doubleToLongBits(choiceLimits[i]);
1999-04-07 22:42:40 +08:00
hash ^= (v ^ (v >>> 32));
hash ^= choiceFormats[i].hashCode();
1999-04-07 22:42:40 +08:00
}
return hash;
}
public static final double nextDouble (double d)
{
return nextDouble (d, true);
}
public static double nextDouble (double d, boolean next)
1999-04-07 22:42:40 +08:00
{
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 < choiceLimits.length; ++i)
1999-04-07 22:42:40 +08:00
{
if (sourceStr.startsWith(choiceFormats[i], index))
1999-04-07 22:42:40 +08:00
{
pos.setIndex(index + choiceFormats[i].length());
return new Double (choiceLimits[i]);
1999-04-07 22:42:40 +08:00
}
}
pos.setErrorIndex(index);
return new Double (Double.NaN);
}
public static final double previousDouble (double d)
{
return nextDouble (d, false);
}
public void setChoices (double[] choiceLimits, String[] choiceFormats)
1999-04-07 22:42:40 +08:00
{
if (choiceLimits == null || choiceFormats == null)
throw new NullPointerException ();
if (choiceLimits.length != choiceFormats.length)
1999-04-07 22:42:40 +08:00
throw new IllegalArgumentException ();
this.choiceFormats = (String[]) choiceFormats.clone();
this.choiceLimits = (double[]) choiceLimits.clone();
1999-04-07 22:42:40 +08:00
}
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 < choiceLimits.length; ++i)
1999-04-07 22:42:40 +08:00
{
result.append(choiceLimits[i]);
1999-04-07 22:42:40 +08:00
result.append('#');
quoteString (result, choiceFormats[i]);
1999-04-07 22:42:40 +08:00
}
return result.toString();
}
// Formats and limits.
private String[] choiceFormats;
private double[] choiceLimits;
1999-04-07 22:42:40 +08:00
// 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;
private static final long serialVersionUID = 1795184449645032964L;
1999-04-07 22:42:40 +08:00
}