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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [text/] [ChoiceFormat.java] - Blame information for rev 14

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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