OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [java/] [text/] [ChoiceFormat.java] - Blame information for rev 771

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 771 jeremybenn
/* ChoiceFormat.java -- Format over a range of numbers
2
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
3
   Free Software Foundation, Inc.
4
 
5
This file is part of GNU Classpath.
6
 
7
GNU Classpath is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
10
any later version.
11
 
12
GNU Classpath is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GNU Classpath; see the file COPYING.  If not, write to the
19
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301 USA.
21
 
22
Linking this library statically or dynamically with other modules is
23
making a combined work based on this library.  Thus, the terms and
24
conditions of the GNU General Public License cover the whole
25
combination.
26
 
27
As a special exception, the copyright holders of this library give you
28
permission to link this library with independent modules to produce an
29
executable, regardless of the license terms of these independent
30
modules, and to copy and distribute the resulting executable under
31
terms of your choice, provided that you also meet, for each linked
32
independent module, the terms and conditions of the license of that
33
module.  An independent module is a module which is not derived from
34
or based on this library.  If you modify this library, you may extend
35
this exception to your version of the library, but you are not
36
obligated to do so.  If you do not wish to do so, delete this
37
exception statement from your version. */
38
 
39
 
40
package java.text;
41
 
42
import gnu.java.lang.CPStringBuilder;
43
 
44
import java.util.Vector;
45
 
46
/**
47
 * This class allows a format to be specified based on a range of numbers.
48
 * To use this class, first specify two lists of formats and range terminators.
49
 * These lists must be arrays of equal length.  The format of index
50
 * <code>i</code> will be selected for value <code>X</code> if
51
 * <code>terminator[i] &lt;= X &lt; limit[i + 1]</code>.  If the value X is not
52
 * included in any range, then either the first or last format will be
53
 * used depending on whether the value X falls outside the range.
54
 * <p>
55
 * This sounds complicated, but that is because I did a poor job of
56
 * explaining it.  Consider the following example:
57
 * <p>
58
 *
59
<pre>terminators = { 1, ChoiceFormat.nextDouble(1) }
60
formats = { "file", "files" }</pre>
61
 *
62
 * <p>
63
 * In this case if the actual number tested is one or less, then the word
64
 * "file" is used as the format value.  If the number tested is greater than
65
 * one, then "files" is used.  This allows plurals to be handled
66
 * gracefully.  Note the use of the method <code>nextDouble</code>.  This
67
 * method selects the next highest double number than its argument.  This
68
 * effectively makes any double greater than 1.0 cause the "files" string
69
 * to be selected.  (Note that all terminator values are specified as
70
 * doubles.
71
 * <p>
72
 * Note that in order for this class to work properly, the range terminator
73
 * array must be sorted in ascending order and the format string array
74
 * must be the same length as the terminator array.
75
 *
76
 * @author Tom Tromey (tromey@cygnus.com)
77
 * @author Aaron M. Renn (arenn@urbanophile.com)
78
 * @date March 9, 1999
79
 */
80
/* Written using "Java Class Libraries", 2nd edition, plus online
81
 * API docs for JDK 1.2 from http://www.javasoft.com.
82
 * Status:  Believed complete and correct to 1.1.
83
 */
84
public class ChoiceFormat extends NumberFormat
85
{
86
  /**
87
   * This method sets new range terminators and format strings for this
88
   * object based on the specified pattern. This pattern is of the form
89
   * "term#string|term#string...".  For example "1#Sunday|2#Monday|#Tuesday".
90
   *
91
   * @param newPattern The pattern of terminators and format strings.
92
   *
93
   * @exception IllegalArgumentException If the pattern is not valid
94
   */
95
  public void applyPattern (String newPattern)
96
  {
97
    // Note: we assume the same kind of quoting rules apply here.
98
    // This isn't explicitly documented.  But for instance we accept
99
    // '#' as a literal hash in a format string.
100
    int index = 0, max = newPattern.length();
101
    Vector stringVec = new Vector ();
102
    Vector limitVec = new Vector ();
103
    final CPStringBuilder buf = new CPStringBuilder ();
104
 
105
    while (true)
106
      {
107
        // Find end of double.
108
        int dstart = index;
109
        while (index < max)
110
          {
111
            char c = newPattern.charAt(index);
112
            if (c == '#' || c == '\u2064' || c == '<')
113
              break;
114
            ++index;
115
          }
116
 
117
        if (index == max)
118
          throw new IllegalArgumentException ("unexpected end of text");
119
        Double d = Double.valueOf (newPattern.substring(dstart, index));
120
 
121
        if (newPattern.charAt(index) == '<')
122
          d = Double.valueOf (nextDouble (d.doubleValue()));
123
 
124
        limitVec.addElement(d);
125
 
126
        // Scan text.
127
        ++index;
128
        buf.setLength(0);
129
        while (index < max)
130
          {
131
            char c = newPattern.charAt(index);
132
            if (c == '\'' && index < max + 1
133
                && newPattern.charAt(index + 1) == '\'')
134
              {
135
                buf.append(c);
136
                ++index;
137
              }
138
            else if (c == '\'' && index < max + 2)
139
              {
140
                buf.append(newPattern.charAt(index + 1));
141
                index += 2;
142
              }
143
            else if (c == '|')
144
              break;
145
            else
146
              buf.append(c);
147
            ++index;
148
          }
149
 
150
        stringVec.addElement(buf.toString());
151
        if (index == max)
152
          break;
153
        ++index;
154
      }
155
 
156
    choiceFormats = new String[stringVec.size()];
157
    stringVec.copyInto(choiceFormats);
158
 
159
    choiceLimits = new double[limitVec.size()];
160
    for (int i = 0; i < choiceLimits.length; ++i)
161
      {
162
        Double d = (Double) limitVec.elementAt(i);
163
        choiceLimits[i] = d.doubleValue();
164
      }
165
  }
166
 
167
  /**
168
   * This method initializes a new instance of <code>ChoiceFormat</code> that
169
   * generates its range terminator and format string arrays from the
170
   * specified pattern.  This pattern is of the form
171
   * "term#string|term#string...".  For example "1#Sunday|2#Monday|#Tuesday".
172
   * This is the same pattern type used by the <code>applyPattern</code>
173
   * method.
174
   *
175
   * @param newPattern The pattern of terminators and format strings.
176
   *
177
   * @exception IllegalArgumentException If the pattern is not valid
178
   */
179
  public ChoiceFormat (String newPattern)
180
  {
181
    super ();
182
    applyPattern (newPattern);
183
  }
184
 
185
  /**
186
   * This method initializes a new instance of <code>ChoiceFormat</code> that
187
   * will use the specified range terminators and format strings.
188
   *
189
   * @param choiceLimits The array of range terminators
190
   * @param choiceFormats The array of format strings
191
   */
192
  public ChoiceFormat (double[] choiceLimits, String[] choiceFormats)
193
  {
194
    super ();
195
    setChoices (choiceLimits, choiceFormats);
196
  }
197
 
198
  /**
199
   * This method tests this object for equality with the specified
200
   * object.  This will be true if and only if:
201
   * <ul>
202
   * <li>The specified object is not <code>null</code>.</li>
203
   * <li>The specified object is an instance of <code>ChoiceFormat</code>.</li>
204
   * <li>The termination ranges and format strings are identical to
205
   *     this object's. </li>
206
   * </ul>
207
   *
208
   * @param obj The object to test for equality against.
209
   *
210
   * @return <code>true</code> if the specified object is equal to
211
   * this one, <code>false</code> otherwise.
212
   */
213
  public boolean equals (Object obj)
214
  {
215
    if (! (obj instanceof ChoiceFormat))
216
      return false;
217
    ChoiceFormat cf = (ChoiceFormat) obj;
218
    if (choiceLimits.length != cf.choiceLimits.length)
219
      return false;
220
    for (int i = choiceLimits.length - 1; i >= 0; --i)
221
      {
222
        if (choiceLimits[i] != cf.choiceLimits[i]
223
            || !choiceFormats[i].equals(cf.choiceFormats[i]))
224
          return false;
225
      }
226
    return true;
227
  }
228
 
229
  /**
230
   * This method appends the appropriate format string to the specified
231
   * <code>StringBuffer</code> based on the supplied <code>long</code>
232
   * argument.
233
   *
234
   * @param num The number used for determine (based on the range
235
   *               terminators) which format string to append.
236
   * @param appendBuf The <code>StringBuffer</code> to append the format string
237
   *                  to.
238
   * @param pos Unused.
239
   *
240
   * @return The <code>StringBuffer</code> with the format string appended.
241
   */
242
  public StringBuffer format (long num, StringBuffer appendBuf,
243
                              FieldPosition pos)
244
  {
245
    return format ((double) num, appendBuf, pos);
246
  }
247
 
248
  /**
249
   * This method appends the appropriate format string to the specified
250
   * <code>StringBuffer</code> based on the supplied <code>double</code>
251
   * argument.
252
   *
253
   * @param num The number used for determine (based on the range
254
   *               terminators) which format string to append.
255
   * @param appendBuf The <code>StringBuffer</code> to append the format string to.
256
   * @param pos Unused.
257
   *
258
   * @return The <code>StringBuffer</code> with the format string appended.
259
   */
260
  public StringBuffer format (double num, StringBuffer appendBuf,
261
                              FieldPosition pos)
262
  {
263
    if (choiceLimits.length == 0)
264
      return appendBuf;
265
 
266
    int index = 0;
267
    if (! Double.isNaN(num) && num >= choiceLimits[0])
268
      {
269
        for (; index < choiceLimits.length - 1; ++index)
270
          {
271
            if (choiceLimits[index] <= num && num < choiceLimits[index + 1])
272
              break;
273
          }
274
      }
275
 
276
    return appendBuf.append(choiceFormats[index]);
277
  }
278
 
279
  /**
280
   * This method returns the list of format strings in use.
281
   *
282
   * @return The list of format objects.
283
   */
284
  public Object[] getFormats ()
285
  {
286
    return (Object[]) choiceFormats.clone();
287
  }
288
 
289
  /**
290
   * This method returns the list of range terminators in use.
291
   *
292
   * @return The list of range terminators.
293
   */
294
  public double[] getLimits ()
295
  {
296
    return (double[]) choiceLimits.clone();
297
  }
298
 
299
  /**
300
   * This method returns a hash value for this object
301
   *
302
   * @return A hash value for this object.
303
   */
304
  public int hashCode ()
305
  {
306
    int hash = 0;
307
    for (int i = 0; i < choiceLimits.length; ++i)
308
      {
309
        long v = Double.doubleToLongBits(choiceLimits[i]);
310
        hash ^= (v ^ (v >>> 32));
311
        hash ^= choiceFormats[i].hashCode();
312
      }
313
    return hash;
314
  }
315
 
316
  /**
317
   * This method returns the lowest possible double greater than the
318
   * specified double.  If the specified double value is equal to
319
   * <code>Double.NaN</code> then that is the value returned.
320
   *
321
   * @param d The specified double
322
   *
323
   * @return The lowest double value greater than the specified double.
324
   */
325
  public static final double nextDouble (double d)
326
  {
327
    return nextDouble (d, true);
328
  }
329
 
330
  /**
331
   * This method returns a double that is either the next highest double
332
   * or next lowest double compared to the specified double depending on the
333
   * value of the passed boolean parameter.  If the boolean parameter is
334
   * <code>true</code>, then the lowest possible double greater than the
335
   * specified double will be returned.  Otherwise the highest possible
336
   * double less than the specified double will be returned.
337
   *
338
   * @param d The specified double
339
   * @param next <code>true</code> to return the next highest
340
   *                 double, <code>false</code> otherwise.
341
   *
342
   * @return The next highest or lowest double value.
343
   */
344
  public static double nextDouble (double d, boolean next)
345
  {
346
    if (Double.isInfinite(d) || Double.isNaN(d))
347
      return d;
348
 
349
    long bits = Double.doubleToLongBits(d);
350
 
351
    long mantMask = (1L << mantissaBits) - 1;
352
    long mantissa = bits & mantMask;
353
 
354
    long expMask = (1L << exponentBits) - 1;
355
    long exponent = (bits >>> mantissaBits) & expMask;
356
 
357
    if (next ^ (bits < 0)) // Increment magnitude
358
      {
359
        if (mantissa == (1L << mantissaBits) - 1)
360
          {
361
            mantissa = 0L;
362
            exponent++;
363
 
364
            // Check for absolute overflow.
365
            if (exponent >= (1L << mantissaBits))
366
              return (bits > 0) ? Double.POSITIVE_INFINITY
367
                : Double.NEGATIVE_INFINITY;
368
          }
369
        else
370
          mantissa++;
371
      }
372
    else // Decrement magnitude
373
      {
374
        if (exponent == 0L && mantissa == 0L)
375
          {
376
            // The only case where there is a change of sign
377
            return next ? Double.MIN_VALUE : -Double.MIN_VALUE;
378
          }
379
        else
380
          {
381
            if (mantissa == 0L)
382
              {
383
                mantissa = (1L << mantissaBits) - 1;
384
                exponent--;
385
              }
386
            else
387
              mantissa--;
388
          }
389
      }
390
 
391
    long result = bits < 0 ? 1 : 0;
392
    result = (result << exponentBits) | exponent;
393
    result = (result << mantissaBits) | mantissa;
394
    return Double.longBitsToDouble(result);
395
  }
396
 
397
  /**
398
   * I'm not sure what this method is really supposed to do, as it is
399
   * not documented.
400
   */
401
  public Number parse (String sourceStr, ParsePosition pos)
402
  {
403
    int index = pos.getIndex();
404
    for (int i = 0; i < choiceLimits.length; ++i)
405
      {
406
        if (sourceStr.startsWith(choiceFormats[i], index))
407
          {
408
            pos.setIndex(index + choiceFormats[i].length());
409
            return Double.valueOf (choiceLimits[i]);
410
          }
411
      }
412
    pos.setErrorIndex(index);
413
    return Double.valueOf (Double.NaN);
414
  }
415
 
416
  /**
417
   * This method returns the highest possible double less than the
418
   * specified double.  If the specified double value is equal to
419
   * <code>Double.NaN</code> then that is the value returned.
420
   *
421
   * @param d The specified double
422
   *
423
   * @return The highest double value less than the specified double.
424
   */
425
  public static final double previousDouble (double d)
426
  {
427
    return nextDouble (d, false);
428
  }
429
 
430
  /**
431
   * This method sets new range terminators and format strings for this
432
   * object.
433
   *
434
   * @param choiceLimits The new range terminators
435
   * @param choiceFormats The new choice formats
436
   */
437
  public void setChoices (double[] choiceLimits, String[] choiceFormats)
438
  {
439
    if (choiceLimits == null || choiceFormats == null)
440
      throw new NullPointerException ();
441
    if (choiceLimits.length != choiceFormats.length)
442
      throw new IllegalArgumentException ();
443
    this.choiceFormats = (String[]) choiceFormats.clone();
444
    this.choiceLimits = (double[]) choiceLimits.clone();
445
  }
446
 
447
  private void quoteString (CPStringBuilder dest, String text)
448
  {
449
    int max = text.length();
450
    for (int i = 0; i < max; ++i)
451
      {
452
        char c = text.charAt(i);
453
        if (c == '\'')
454
          {
455
            dest.append(c);
456
            dest.append(c);
457
          }
458
        else if (c == '#' || c == '|' || c == '\u2064' || c == '<')
459
          {
460
            dest.append('\'');
461
            dest.append(c);
462
            dest.append('\'');
463
          }
464
        else
465
          dest.append(c);
466
      }
467
  }
468
 
469
  /**
470
   * This method returns the range terminator list and format string list
471
   * as a <code>String</code> suitable for using with the
472
   * <code>applyPattern</code> method.
473
   *
474
   * @return A pattern string for this object
475
   */
476
  public String toPattern ()
477
  {
478
    CPStringBuilder result = new CPStringBuilder ();
479
    for (int i = 0; i < choiceLimits.length; ++i)
480
      {
481
        result.append(choiceLimits[i]);
482
        result.append('#');
483
        quoteString (result, choiceFormats[i]);
484
      }
485
    return result.toString();
486
  }
487
 
488
  /**
489
   * This is the list of format strings.  Note that this variable is
490
   * specified by the serialization spec of this class.
491
   */
492
  private String[] choiceFormats;
493
 
494
  /**
495
   * This is the list of range terminator values.  Note that this variable is
496
   * specified by the serialization spec of this class.
497
   */
498
  private double[] choiceLimits;
499
 
500
  // Number of mantissa bits in double.
501
  private static final int mantissaBits = 52;
502
  // Number of exponent bits in a double.
503
  private static final int exponentBits = 11;
504
 
505
  private static final long serialVersionUID = 1795184449645032964L;
506
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.