1 // ChoiceFormat.java - Formatter for `switch'-like string substitution.
3 /* Copyright (C) 1999 Cygnus Solutions
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
13 import java
.util
.Vector
;
16 * @author Tom Tromey <tromey@cygnus.com>
19 /* Written using "Java Class Libraries", 2nd edition, plus online
20 * API docs for JDK 1.2 from http://www.javasoft.com.
21 * Status: Believed complete and correct to 1.1.
24 public class ChoiceFormat
extends NumberFormat
26 // Note: we assume the same kind of quoting rules apply here.
27 // This isn't explicitly documented. But for instance we accept
28 // '#' as a literal hash in a format string.
29 public void applyPattern (String newPattern
)
31 int index
= 0, max
= newPattern
.length();
32 Vector stringVec
= new Vector ();
33 Vector limitVec
= new Vector ();
34 StringBuffer buf
= new StringBuffer ();
38 // Find end of double.
42 char c
= newPattern
.charAt(index
);
43 if (c
== '#' || c
== '\u2064' || c
== '<')
49 throw new IllegalArgumentException ("unexpected end of text");
50 Double d
= new Double (newPattern
.substring(dstart
, index
));
52 if (newPattern
.charAt(index
) == '<')
53 d
= new Double (nextDouble (d
.doubleValue()));
55 limitVec
.addElement(d
);
62 char c
= newPattern
.charAt(index
);
63 if (c
== '\'' && index
< max
+ 1
64 && newPattern
.charAt(index
+ 1) == '\'')
69 else if (c
== '\'' && index
< max
+ 2)
71 buf
.append(newPattern
.charAt(index
+ 1));
81 stringVec
.addElement(buf
.toString());
87 strings
= new String
[stringVec
.size()];
88 stringVec
.copyInto(strings
);
90 limits
= new double[limitVec
.size()];
91 for (int i
= 0; i
< limits
.length
; ++i
)
93 Double d
= (Double
) limitVec
.elementAt(i
);
94 limits
[i
] = d
.doubleValue();
98 public ChoiceFormat (String newPattern
)
101 applyPattern (newPattern
);
104 public ChoiceFormat (double[] limits
, String
[] strings
)
107 setChoices (limits
, strings
);
110 public Object
clone ()
112 return new ChoiceFormat (limits
, strings
);
115 public boolean equals (Object obj
)
117 if (! (obj
instanceof ChoiceFormat
))
119 ChoiceFormat cf
= (ChoiceFormat
) obj
;
120 if (limits
.length
!= cf
.limits
.length
)
122 for (int i
= limits
.length
- 1; i
>= 0; --i
)
124 if (limits
[i
] != cf
.limits
[i
]
125 || !strings
[i
].equals(cf
.strings
[i
]))
131 public StringBuffer
format (long num
, StringBuffer appendBuf
,
134 return format ((double) num
, appendBuf
, pos
);
137 public StringBuffer
format (double num
, StringBuffer appendBuf
,
140 if (limits
.length
== 0)
144 if (! Double
.isNaN(num
) && num
>= limits
[0])
146 for (; index
< limits
.length
- 1; ++index
)
148 if (limits
[index
] <= num
149 && index
!= limits
.length
- 2
150 && num
< limits
[index
+ 1])
155 return appendBuf
.append(strings
[index
]);
158 public Object
[] getFormats ()
160 return (Object
[]) strings
.clone();
163 public double[] getLimits ()
165 return (double[]) limits
.clone();
168 public int hashCode ()
171 for (int i
= 0; i
< limits
.length
; ++i
)
173 long v
= Double
.doubleToLongBits(limits
[i
]);
174 hash ^
= (v ^
(v
>>> 32));
175 hash ^
= strings
[i
].hashCode();
180 public static final double nextDouble (double d
)
182 return nextDouble (d
, true);
185 public static final double nextDouble (double d
, boolean next
)
187 if (Double
.isInfinite(d
) || Double
.isNaN(d
))
190 long bits
= Double
.doubleToLongBits(d
);
192 long mantMask
= (1L << mantissaBits
) - 1;
193 long mantissa
= bits
& mantMask
;
195 long expMask
= (1L << exponentBits
) - 1;
196 long exponent
= (bits
>>> mantissaBits
) & expMask
;
198 if (next ^
(bits
< 0)) // Increment magnitude
200 if (mantissa
== (1L << mantissaBits
) - 1)
205 // Check for absolute overflow.
206 if (exponent
>= (1L << mantissaBits
))
207 return (bits
> 0) ? Double
.POSITIVE_INFINITY
208 : Double
.NEGATIVE_INFINITY
;
213 else // Decrement magnitude
215 if (exponent
== 0L && mantissa
== 0L)
217 // The only case where there is a change of sign
218 return next ? Double
.MIN_VALUE
: -Double
.MIN_VALUE
;
224 mantissa
= (1L << mantissaBits
) - 1;
232 long result
= bits
< 0 ?
1 : 0;
233 result
= (result
<< exponentBits
) | exponent
;
234 result
= (result
<< mantissaBits
) | mantissa
;
235 return Double
.longBitsToDouble(result
);
238 public Number
parse (String sourceStr
, ParsePosition pos
)
240 int index
= pos
.getIndex();
241 for (int i
= 0; i
< limits
.length
; ++i
)
243 if (sourceStr
.startsWith(strings
[i
], index
))
245 pos
.setIndex(index
+ strings
[i
].length());
246 return new Double (limits
[i
]);
249 pos
.setErrorIndex(index
);
250 return new Double (Double
.NaN
);
253 public static final double previousDouble (double d
)
255 return nextDouble (d
, false);
258 public void setChoices (double[] limits
, String
[] strings
)
260 if (limits
== null || strings
== null)
261 throw new NullPointerException ();
262 if (limits
.length
!= strings
.length
)
263 throw new IllegalArgumentException ();
264 this.strings
= (String
[]) strings
.clone();
265 this.limits
= (double[]) limits
.clone();
268 private final void quoteString (StringBuffer dest
, String text
)
270 int max
= text
.length();
271 for (int i
= 0; i
< max
; ++i
)
273 char c
= text
.charAt(i
);
279 else if (c
== '#' || c
== '|' || c
== '\u2064' || c
== '<')
290 public String
toPattern ()
292 StringBuffer result
= new StringBuffer ();
293 for (int i
= 0; i
< limits
.length
; ++i
)
295 result
.append(limits
[i
]);
297 quoteString (result
, strings
[i
]);
299 return result
.toString();
302 // Formats and limits.
303 private String
[] strings
;
304 private double[] limits
;
306 // Number of mantissa bits in double.
307 private static final int mantissaBits
= 52;
308 // Number of exponent bits in a double.
309 private static final int exponentBits
= 11;