Home | History | Annotate | Download | only in i18n
      1 /*
      2 ******************************************************************************
      3 *
      4 *   Copyright (C) 1997-2007, International Business Machines
      5 *   Corporation and others.  All Rights Reserved.
      6 *
      7 ******************************************************************************
      8 *
      9 * File DIGITLST.H
     10 *
     11 * Modification History:
     12 *
     13 *   Date        Name        Description
     14 *   02/25/97    aliu        Converted from java.
     15 *   03/21/97    clhuang     Updated per C++ implementation.
     16 *   04/15/97    aliu        Changed MAX_COUNT to DBL_DIG.  Changed Digit to char.
     17 *   09/09/97    aliu        Adapted for exponential notation support.
     18 *   08/02/98    stephen     Added nearest/even rounding
     19 *   06/29/99    stephen     Made LONG_DIGITS a macro to satisfy SUN compiler
     20 *   07/09/99    stephen     Removed kMaxCount (unused, for HP compiler)
     21 ******************************************************************************
     22 */
     23 
     24 #ifndef DIGITLST_H
     25 #define DIGITLST_H
     26 
     27 #include "unicode/uobject.h"
     28 
     29 #if !UCONFIG_NO_FORMATTING
     30 #include "unicode/decimfmt.h"
     31 #include <float.h>
     32 
     33 // Decimal digits in a 64-bit int
     34 //#define LONG_DIGITS 19
     35 #define INT64_DIGITS 19
     36 
     37 typedef enum EDigitListValues {
     38     MAX_DBL_DIGITS = DBL_DIG,
     39     MAX_I64_DIGITS = INT64_DIGITS,
     40     MAX_DIGITS = MAX_I64_DIGITS,
     41     MAX_EXPONENT = DBL_DIG,
     42     DIGIT_PADDING = 3,
     43 
     44      // "+." + fDigits + "e" + fDecimalAt
     45     MAX_DEC_DIGITS = MAX_DIGITS + DIGIT_PADDING + MAX_EXPONENT
     46 } EDigitListValues;
     47 
     48 U_NAMESPACE_BEGIN
     49 
     50 /**
     51  * Digit List utility class. Private to DecimalFormat.  Handles the transcoding
     52  * between numeric values and strings of characters.  Only handles
     53  * non-negative numbers.  The division of labor between DigitList and
     54  * DecimalFormat is that DigitList handles the radix 10 representation
     55  * issues; DecimalFormat handles the locale-specific issues such as
     56  * positive/negative, grouping, decimal point, currency, and so on.
     57  * <P>
     58  * A DigitList is really a representation of a floating point value.
     59  * It may be an integer value; we assume that a double has sufficient
     60  * precision to represent all digits of a long.
     61  * <P>
     62  * The DigitList representation consists of a string of characters,
     63  * which are the digits radix 10, from '0' to '9'.  It also has a radix
     64  * 10 exponent associated with it.  The value represented by a DigitList
     65  * object can be computed by mulitplying the fraction f, where 0 <= f < 1,
     66  * derived by placing all the digits of the list to the right of the
     67  * decimal point, by 10^exponent.
     68  */
     69 class DigitList : public UMemory { // Declare external to make compiler happy
     70 public:
     71     DigitList();
     72     ~DigitList();
     73 
     74     /* copy constructor
     75      * @param DigitList The object to be copied.
     76      * @return the newly created object.
     77      */
     78     DigitList(const DigitList&); // copy constructor
     79 
     80     /* assignment operator
     81      * @param DigitList The object to be copied.
     82      * @return the newly created object.
     83      */
     84     DigitList& operator=(const DigitList&);  // assignment operator
     85 
     86     /**
     87      * Return true if another object is semantically equal to this one.
     88      * @param other The DigitList to be compared for equality
     89      * @return true if another object is semantically equal to this one.
     90      * return false otherwise.
     91      */
     92     UBool operator==(const DigitList& other) const;
     93 
     94 private:
     95     /**
     96      * Commented out due to lack of usage and low code coverage.
     97      */
     98     inline UBool operator!=(const DigitList& other) const;
     99 public:
    100 
    101     /**
    102      * Clears out the digits.
    103      * Use before appending them.
    104      * Typically, you set a series of digits with append, then at the point
    105      * you hit the decimal point, you set myDigitList.fDecimalAt = myDigitList.fCount;
    106      * then go on appending digits.
    107      */
    108     void clear(void);
    109 
    110     /**
    111      * Appends digits to the list. Ignores all digits beyond the first DBL_DIG,
    112      * since they are not significant for either longs or doubles.
    113      * @param digit The digit to be appended.
    114      */
    115     inline void append(char digit);
    116 
    117     /**
    118      * Utility routine to get the value of the digit list
    119      * Returns 0.0 if zero length.
    120      * @return the value of the digit list.
    121      */
    122     double getDouble(void) /*const*/;
    123 
    124     /**
    125      * Utility routine to get the value of the digit list
    126      * Make sure that fitsIntoLong() is called before calling this function.
    127      * Returns 0 if zero length.
    128      * @return the value of the digit list, return 0 if it is zero length
    129      */
    130     int32_t getLong(void) /*const*/;
    131 
    132     /**
    133      * Utility routine to get the value of the digit list
    134      * Make sure that fitsIntoInt64() is called before calling this function.
    135      * Returns 0 if zero length.
    136      * @return the value of the digit list, return 0 if it is zero length
    137      */
    138     int64_t getInt64(void) /*const*/;
    139 
    140     /**
    141      * Return true if the number represented by this object can fit into
    142      * a long.
    143      * @param ignoreNegativeZero True if negative zero is ignored.
    144      * @return true if the number represented by this object can fit into
    145      * a long, return false otherwise.
    146      */
    147     UBool fitsIntoLong(UBool ignoreNegativeZero) /*const*/;
    148 
    149     /**
    150      * Return true if the number represented by this object can fit into
    151      * an int64_t.
    152      * @param ignoreNegativeZero True if negative zero is ignored.
    153      * @return true if the number represented by this object can fit into
    154      * a long, return false otherwise.
    155      */
    156     UBool fitsIntoInt64(UBool ignoreNegativeZero) /*const*/;
    157 
    158     /**
    159      * Utility routine to set the value of the digit list from a double
    160      * Input must be non-negative, and must not be Inf, -Inf, or NaN.
    161      * The maximum fraction digits helps us round properly.
    162      * @param source The value to be set
    163      * @param maximunDigits The maximum number of digits to be shown
    164      * @param fixedPoint True if the point is fixed
    165      */
    166     void set(double source, int32_t maximumDigits, UBool fixedPoint = TRUE);
    167 
    168     /**
    169      * Utility routine to set the value of the digit list from a long.
    170      * If a non-zero maximumDigits is specified, no more than that number of
    171      * significant digits will be produced.
    172      * @param source The value to be set
    173      * @param maximunDigits The maximum number of digits to be shown
    174      */
    175     void set(int32_t source, int32_t maximumDigits = 0);
    176 
    177     /**
    178      * Utility routine to set the value of the digit list from an int64.
    179      * If a non-zero maximumDigits is specified, no more than that number of
    180      * significant digits will be produced.
    181      * @param source The value to be set
    182      * @param maximunDigits The maximum number of digits to be shown
    183      */
    184     void set(int64_t source, int32_t maximumDigits = 0);
    185 
    186     /**
    187      * Return true if this is a representation of zero.
    188      * @return true if this is a representation of zero.
    189      */
    190     UBool isZero(void) const;
    191 
    192     /**
    193      * Return true if this is a representation of LONG_MIN.  You must use
    194      * this method to determine if this is so; you cannot check directly,
    195      * because a special format is used to handle this.
    196      */
    197     // This code is unused.
    198     //UBool isLONG_MIN(void) const;
    199 
    200 public:
    201     /**
    202      * These data members are intentionally public and can be set directly.
    203      *<P>
    204      * The value represented is given by placing the decimal point before
    205      * fDigits[fDecimalAt].  If fDecimalAt is < 0, then leading zeros between
    206      * the decimal point and the first nonzero digit are implied.  If fDecimalAt
    207      * is > fCount, then trailing zeros between the fDigits[fCount-1] and the
    208      * decimal point are implied.
    209      * <P>
    210      * Equivalently, the represented value is given by f * 10^fDecimalAt.  Here
    211      * f is a value 0.1 <= f < 1 arrived at by placing the digits in fDigits to
    212      * the right of the decimal.
    213      * <P>
    214      * DigitList is normalized, so if it is non-zero, fDigits[0] is non-zero.  We
    215      * don't allow denormalized numbers because our exponent is effectively of
    216      * unlimited magnitude.  The fCount value contains the number of significant
    217      * digits present in fDigits[].
    218      * <P>
    219      * Zero is represented by any DigitList with fCount == 0 or with each fDigits[i]
    220      * for all i <= fCount == '0'.
    221      */
    222     int32_t                         fDecimalAt;
    223     int32_t                         fCount;
    224     UBool                           fIsPositive;
    225     char                            *fDigits;
    226     DecimalFormat::ERoundingMode    fRoundingMode;
    227 
    228 private:
    229 
    230     /* One character before fDigits for the decimal*/
    231     char        fDecimalDigits[MAX_DEC_DIGITS + 1];
    232 
    233     /**
    234      * Round the representation to the given number of digits.
    235      * @param maximumDigits The maximum number of digits to be shown.
    236      * Upon return, count will be less than or equal to maximumDigits.
    237      */
    238     void round(int32_t maximumDigits);
    239 
    240     UBool shouldRoundUp(int32_t maximumDigits) const;
    241 };
    242 
    243 // -------------------------------------
    244 // Appends the digit to the digit list if it's not out of scope.
    245 // Ignores the digit, otherwise.
    246 
    247 inline void
    248 DigitList::append(char digit)
    249 {
    250     // Ignore digits which exceed the precision we can represent
    251     if (fCount < MAX_DIGITS)
    252         fDigits[fCount++] = digit;
    253 }
    254 
    255 #if 0
    256 inline UBool
    257 DigitList::operator!=(const DigitList& other) const {
    258     return !operator==(other);
    259 }
    260 #endif
    261 
    262 U_NAMESPACE_END
    263 
    264 #endif // #if !UCONFIG_NO_FORMATTING
    265 #endif // _DIGITLST
    266 
    267 //eof
    268