home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / main.bin / DigitList.java < prev    next >
Text File  |  1997-10-01  |  10KB  |  255 lines

  1. /*
  2.  * @(#)DigitList.java    1.10 97/07/15
  3.  *
  4.  * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  5.  * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  6.  *
  7.  * Portions copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
  8.  *
  9.  *   The original version of this source code and documentation is copyrighted
  10.  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  11.  * materials are provided under terms of a License Agreement between Taligent
  12.  * and Sun. This technology is protected by multiple US and International
  13.  * patents. This notice and attribution to Taligent may not be removed.
  14.  *   Taligent is a registered trademark of Taligent, Inc.
  15.  *
  16.  * Permission to use, copy, modify, and distribute this software
  17.  * and its documentation for NON-COMMERCIAL purposes and without
  18.  * fee is hereby granted provided that this copyright notice
  19.  * appears in all copies. Please refer to the file "copyright.html"
  20.  * for further important copyright and licensing information.
  21.  *
  22.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  23.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  24.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  25.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  26.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  27.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  28.  *
  29.  */
  30.  
  31. package java.text;
  32.  
  33. /**
  34.  * Digit List. Private to Decimal Format
  35.  * @see  Locale
  36.  * @see  Format
  37.  * @see  NumberFormat
  38.  * @see  DecimalFormat
  39.  * @see  ChoiceFormat
  40.  * @see  MessageFormat
  41.  * @version      1.10 07/15/97
  42.  * @author       Mark Davis
  43.  */
  44. final class DigitList implements Cloneable {
  45.     /**
  46.      * The fields can be set directly.
  47.      */
  48.     public static final int MAX_COUNT = 19;
  49.     public int decimalAt = 0;
  50.     public int count = 0;
  51.     public byte[] digits = new byte[MAX_COUNT];
  52.  
  53.     /**
  54.      * Clears out the digits.
  55.      * Use before appending them.
  56.      * Typically, you set a series of digits with append, then at the point
  57.      * you hit the decimal point, you set myDigitList.decimalAt = myDigitList.count;
  58.      * then go on appending digits.
  59.      */
  60.     public void clear () {
  61.         decimalAt = 0;
  62.         count = 0;
  63.     }
  64.     /**
  65.      * Appends digits to the list. Ignores all digits over 20,
  66.      * since they are not significant for either longs or doubles.
  67.      */
  68.     public void append (int digit) {
  69.         if (count < MAX_COUNT)
  70.             digits[count] = (byte) digit;
  71.         ++count;
  72.     }
  73.     /**
  74.      * Utility routine to get the value of the digit list
  75.      * If (count == 0) this throws a NumberFormatException, which
  76.      * mimics Long.parseLong().
  77.      * FIXME shouldn't this use Double.valueOf()??
  78.      * INTEGRATION WITH JAVA: REWRITE IN NATIVE
  79.      */
  80.     public final double getDouble() {
  81.         // for now, simple implementation; later, do proper IEEE native stuff
  82.         StringBuffer temp = new StringBuffer(count);
  83.         if (count > MAX_COUNT)
  84.             count = MAX_COUNT;
  85.         for (int i = 0; i < count; ++i)
  86.             temp.append((char)(digits[i]));
  87.         long value = Long.parseLong(temp.toString());
  88.         return (value * Math.pow(10, decimalAt - count));
  89.     }
  90.  
  91.     /**
  92.      * Utility routine to get the value of the digit list
  93.      * If (count == 0) this throws a NumberFormatException, which
  94.      * mimics Long.parseLong().
  95.      * INTEGRATION WITH JAVA: REWRITE IN NATIVE
  96.      */
  97.     public final long getLong() {
  98.         // for now, simple implementation; later, do proper IEEE native stuff
  99.         StringBuffer temp = new StringBuffer(count);
  100.         for (int i = 0; i < count; ++i)
  101.             temp.append((char)(digits[i]));
  102.         return Long.parseLong(temp.toString());
  103.     }
  104.  
  105.     private int fixNumber(double toBeFixed, StringBuffer buffer, int p) {
  106.         int correction = 0;
  107.         double logValue1 = 0.0, logValue2 = 0.0;
  108.         int i = 0;
  109.         StringBuffer temp = null;
  110.         Double aValue = null;
  111.         double result = toBeFixed;
  112.         logValue1 = Math.log(result);
  113.         logValue2 = Math.log(10);
  114.         double value = logValue1 / logValue2;
  115.         correction = (int)(value - MAX_COUNT);
  116.         while (result > Long.MAX_VALUE) {
  117.             result /= 10;
  118.             i++;
  119.         }
  120.         String digitsList = Long.toString((long)result);
  121.         int n = digitsList.length() - 1;
  122.         for (; n >= 0; n--) {
  123.             if (digitsList.charAt(n) != '0')
  124.                 break;
  125.         }
  126.         for (int j = 0; j < n+1; j++) {
  127.             buffer.append(digitsList.charAt(j));
  128.             digits[j] = (byte) digitsList.charAt(j);
  129.         }
  130.         decimalAt = (int)(i - correction + value - p);
  131.         return n+1;
  132.     }
  133.  
  134.     /**
  135.      * Utility routine to set the value of the digit list from a double
  136.      * Note: input must not be Inf, -Inf, or Nan.
  137.      * INTEGRATION WITH JAVA: REWRITE IN NATIVE
  138.      */
  139.     public final void set(double source, int maxDecimalCount) {
  140. //        if (maxDecimalCount > MAX_COUNT) maxDecimalCount = MAX_COUNT;
  141.         // for now, simple implementation; later, do proper IEEE stuff
  142.         int i = 0;
  143.         double sourceDouble = (source * Math.pow(10, maxDecimalCount));
  144.         long temp = Math.round(sourceDouble);
  145.         boolean skipCheck = false;
  146.         StringBuffer stringDigits = new StringBuffer(MAX_COUNT);
  147.         if (temp < 0) {
  148.             count = fixNumber(sourceDouble, stringDigits, maxDecimalCount);
  149.             skipCheck = true;
  150.         }
  151.         if (!skipCheck) {
  152.             stringDigits.append(Long.toString(temp));
  153.             while ((temp > 0) && (temp < Math.pow(10, maxDecimalCount-1))) {
  154.                 stringDigits.insert(0, '0');
  155.                 temp *= 10;
  156.             }
  157.             for (i = stringDigits.length() - 1; i >= 0; --i) { // strip trailing zeros
  158.                 if (stringDigits.charAt(i) != '0') break;
  159.                 maxDecimalCount--;
  160.             }
  161.             count = i+1;
  162.             for (int j = 0; j < count; ++j)
  163.                 digits[j] = (byte) stringDigits.charAt(j);
  164.             decimalAt = count - maxDecimalCount;
  165.         }
  166.         if (decimalAt < 0) decimalAt = 0;
  167.     }
  168.     /**
  169.      * Utility routine to set the value of the digit list from a long
  170.      * INTEGRATION WITH JAVA: REWRITE IN NATIVE
  171.      */
  172.     public final void set(long source) {
  173.         // for now, simple implementation; later, do proper IEEE stuff
  174. //        String stringDigits = Long.toString(source);
  175.         String stringDigits;
  176.  
  177.         // This method does not expect a negative number. However,
  178.         // "source" can be a Long.MIN_VALUE (-9223372036854775808),
  179.         // if the number being formatted is a Long.MIN_VALUE. -- CLH, 12/19/96
  180.         if (source == Long.MIN_VALUE) {
  181.             source = - (source + 1);
  182.             stringDigits = Long.toString(source).substring(0, MAX_COUNT-1);
  183.             char lastDigit = Long.toString(source).charAt(MAX_COUNT-1);
  184.             long actualDigit = Character.digit(lastDigit, 10) + 1;
  185.             if (actualDigit <= 9)
  186.                 stringDigits = stringDigits + Long.toString(actualDigit);
  187.             else
  188.                 // Not likely to happen!
  189.                 throw new InternalError("Internal NumberFormat error!");
  190.         }
  191.         else
  192.             stringDigits = Long.toString(source);
  193.  
  194.         if (stringDigits.length() > MAX_COUNT) {
  195.             stringDigits = stringDigits.substring(0, MAX_COUNT);
  196.         }
  197.         int i;
  198.         int maxDecimalCount = 0;
  199.         for (i = stringDigits.length() - 1; i >= 0; --i) { // strip trailing zeros
  200.             if (stringDigits.charAt(i) != '0') break;
  201.             maxDecimalCount--;
  202.         }
  203.         count = i+1;
  204.         for (int j = 0; j < count; ++j)
  205.             digits[j] = (byte) stringDigits.charAt(j);
  206.         decimalAt = count - maxDecimalCount;
  207.         if (decimalAt < 0) decimalAt = 0;
  208.     }
  209.     /**
  210.      * Standard override; no change in semantics.
  211.      */
  212.     public Object clone() {
  213.         try {
  214.             return (DigitList) super.clone();
  215.         } catch (CloneNotSupportedException e) {
  216.             throw new InternalError();
  217.         }
  218.     };
  219.     /**
  220.      * equality test between two digit lists.
  221.      */
  222.     public boolean equals(Object obj) {
  223.         if (this == obj)                      // quick check
  224.             return true;
  225.         if (!(obj instanceof DigitList))         // (1) same object?
  226.             return false;
  227.         DigitList other = (DigitList) obj;
  228.         if (hashCode() != other.hashCode())
  229.             return false;       // quick check
  230.         if (!(count == other.count))
  231.             return false;
  232.         if (!(digits.length == other.digits.length))
  233.             return false;
  234.         for (int i = 0; i < digits.length; i++)
  235.             if (digits[i] != other.digits[i])
  236.                 return false;
  237.         if (decimalAt != other.decimalAt)
  238.             return false;
  239.         return true;
  240.     }
  241.  
  242.     /**
  243.      * Generates the hash code for the digit list.
  244.      */
  245.     public int hashCode() {
  246.         int hashcode = 0;
  247.         for (int i = 0; i < digits.length; i++) {
  248.             short mostSignificant = (short)(((int)digits[i]) >> 16);
  249.             short leastSignificant = digits[i];
  250.             hashcode ^= mostSignificant ^ leastSignificant;
  251.         }
  252.         return hashcode;
  253.     }
  254. }
  255.