LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - digitformatter.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 202 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // © 2016 and later: Unicode, Inc. and others.
       2             : // License & terms of use: http://www.unicode.org/copyright.html
       3             : /*
       4             :  * Copyright (C) 2015, International Business Machines
       5             :  * Corporation and others.  All Rights Reserved.
       6             :  *
       7             :  * file name: digitformatter.cpp
       8             :  */
       9             : 
      10             : #include "unicode/utypes.h"
      11             : 
      12             : #if !UCONFIG_NO_FORMATTING
      13             : 
      14             : #include "unicode/dcfmtsym.h"
      15             : #include "unicode/unum.h"
      16             : 
      17             : #include "digitformatter.h"
      18             : #include "digitgrouping.h"
      19             : #include "digitinterval.h"
      20             : #include "digitlst.h"
      21             : #include "fphdlimp.h"
      22             : #include "smallintformatter.h"
      23             : #include "unistrappender.h"
      24             : #include "visibledigits.h"
      25             : 
      26             : U_NAMESPACE_BEGIN
      27             : 
      28           0 : DigitFormatter::DigitFormatter()
      29             :         : fGroupingSeparator(",", -1, US_INV), fDecimal(".", -1, US_INV),
      30             :           fNegativeSign("-", -1, US_INV), fPositiveSign("+", -1, US_INV),
      31           0 :           fIsStandardDigits(TRUE), fExponent("E", -1, US_INV) {
      32           0 :     for (int32_t i = 0; i < 10; ++i) {
      33           0 :         fLocalizedDigits[i] = (UChar32) (0x30 + i);
      34             :     }
      35           0 :     fInfinity.setTo(UnicodeString("Inf", -1, US_INV), UNUM_INTEGER_FIELD);
      36           0 :     fNan.setTo(UnicodeString("Nan", -1, US_INV), UNUM_INTEGER_FIELD);
      37           0 : }
      38             : 
      39           0 : DigitFormatter::DigitFormatter(const DecimalFormatSymbols &symbols) {
      40           0 :     setDecimalFormatSymbols(symbols);
      41           0 : }
      42             : 
      43             : void
      44           0 : DigitFormatter::setOtherDecimalFormatSymbols(
      45             :         const DecimalFormatSymbols &symbols) {
      46           0 :     fLocalizedDigits[0] = symbols.getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
      47           0 :     fLocalizedDigits[1] = symbols.getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol).char32At(0);
      48           0 :     fLocalizedDigits[2] = symbols.getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol).char32At(0);
      49           0 :     fLocalizedDigits[3] = symbols.getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol).char32At(0);
      50           0 :     fLocalizedDigits[4] = symbols.getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol).char32At(0);
      51           0 :     fLocalizedDigits[5] = symbols.getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol).char32At(0);
      52           0 :     fLocalizedDigits[6] = symbols.getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol).char32At(0);
      53           0 :     fLocalizedDigits[7] = symbols.getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol).char32At(0);
      54           0 :     fLocalizedDigits[8] = symbols.getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol).char32At(0);
      55           0 :     fLocalizedDigits[9] = symbols.getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol).char32At(0);
      56           0 :     fIsStandardDigits = isStandardDigits();
      57           0 :     fNegativeSign = symbols.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
      58           0 :     fPositiveSign = symbols.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
      59           0 :     fInfinity.setTo(symbols.getConstSymbol(DecimalFormatSymbols::kInfinitySymbol), UNUM_INTEGER_FIELD);
      60           0 :     fNan.setTo(symbols.getConstSymbol(DecimalFormatSymbols::kNaNSymbol), UNUM_INTEGER_FIELD);
      61           0 :     fExponent = symbols.getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
      62           0 : }
      63             : 
      64             : void
      65           0 : DigitFormatter::setDecimalFormatSymbolsForMonetary(
      66             :         const DecimalFormatSymbols &symbols) {
      67           0 :     setOtherDecimalFormatSymbols(symbols);
      68           0 :     fGroupingSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
      69           0 :     fDecimal = symbols.getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
      70           0 : }
      71             : 
      72             : void
      73           0 : DigitFormatter::setDecimalFormatSymbols(
      74             :         const DecimalFormatSymbols &symbols) {
      75           0 :     setOtherDecimalFormatSymbols(symbols);
      76           0 :     fGroupingSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
      77           0 :     fDecimal = symbols.getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
      78           0 : }
      79             : 
      80           0 : static void appendField(
      81             :         int32_t fieldId,
      82             :         const UnicodeString &value,
      83             :         FieldPositionHandler &handler,
      84             :         UnicodeString &appendTo) {
      85           0 :     int32_t currentLength = appendTo.length();
      86           0 :     appendTo.append(value);
      87           0 :     handler.addAttribute(
      88             :             fieldId,
      89             :             currentLength,
      90           0 :             appendTo.length());
      91           0 : }
      92             : 
      93           0 : int32_t DigitFormatter::countChar32(
      94             :         const DigitGrouping &grouping,
      95             :         const DigitInterval &interval,
      96             :         const DigitFormatterOptions &options) const {
      97           0 :     int32_t result = interval.length();
      98             : 
      99             :     // We always emit '0' in lieu of no digits.
     100           0 :     if (result == 0) {
     101           0 :         result = 1;
     102             :     }
     103           0 :     if (options.fAlwaysShowDecimal || interval.getLeastSignificantInclusive() < 0) {
     104           0 :         result += fDecimal.countChar32();
     105             :     }
     106           0 :     result += grouping.getSeparatorCount(interval.getIntDigitCount()) * fGroupingSeparator.countChar32();
     107           0 :     return result;
     108             : }
     109             : 
     110             : int32_t
     111           0 : DigitFormatter::countChar32(
     112             :         const VisibleDigits &digits,
     113             :         const DigitGrouping &grouping,
     114             :         const DigitFormatterOptions &options) const {
     115           0 :     if (digits.isNaN()) {
     116           0 :         return countChar32ForNaN();
     117             :     }   
     118           0 :     if (digits.isInfinite()) {
     119           0 :         return countChar32ForInfinity();
     120             :     }   
     121           0 :     return countChar32(
     122             :             grouping,
     123             :             digits.getInterval(),
     124           0 :             options);
     125             : }
     126             : 
     127             : int32_t
     128           0 : DigitFormatter::countChar32(
     129             :         const VisibleDigitsWithExponent &digits,
     130             :         const SciFormatterOptions &options) const {
     131           0 :     if (digits.isNaN()) {
     132           0 :         return countChar32ForNaN();
     133             :     }
     134           0 :     if (digits.isInfinite()) {
     135           0 :         return countChar32ForInfinity();
     136             :     }
     137           0 :     const VisibleDigits *exponent = digits.getExponent();
     138           0 :     if (exponent == NULL) {
     139           0 :         DigitGrouping grouping;
     140           0 :         return countChar32(
     141             :                 grouping,
     142           0 :                 digits.getMantissa().getInterval(),
     143           0 :                 options.fMantissa);
     144             :     }
     145           0 :     return countChar32(
     146           0 :             *exponent, digits.getMantissa().getInterval(), options);
     147             : }
     148             : 
     149             : int32_t
     150           0 : DigitFormatter::countChar32(
     151             :         const VisibleDigits &exponent,
     152             :         const DigitInterval &mantissaInterval,
     153             :         const SciFormatterOptions &options) const {
     154           0 :     DigitGrouping grouping;
     155           0 :     int32_t count = countChar32(
     156           0 :             grouping, mantissaInterval, options.fMantissa);
     157           0 :     count += fExponent.countChar32();
     158           0 :     count += countChar32ForExponent(
     159             :             exponent, options.fExponent);
     160           0 :     return count;
     161             : }
     162             : 
     163           0 : UnicodeString &DigitFormatter::format(
     164             :         const VisibleDigits &digits,
     165             :         const DigitGrouping &grouping,
     166             :         const DigitFormatterOptions &options,
     167             :         FieldPositionHandler &handler,
     168             :         UnicodeString &appendTo) const {
     169           0 :     if (digits.isNaN()) {
     170           0 :         return formatNaN(handler, appendTo);
     171             :     }
     172           0 :     if (digits.isInfinite()) {
     173           0 :         return formatInfinity(handler, appendTo);
     174             :     }
     175             : 
     176           0 :     const DigitInterval &interval = digits.getInterval();
     177           0 :     int32_t digitsLeftOfDecimal = interval.getMostSignificantExclusive();
     178           0 :     int32_t lastDigitPos = interval.getLeastSignificantInclusive();
     179           0 :     int32_t intBegin = appendTo.length();
     180             :     int32_t fracBegin;
     181             : 
     182             :     // Emit "0" instead of empty string.
     183           0 :     if (digitsLeftOfDecimal == 0 && lastDigitPos == 0) {
     184           0 :         appendTo.append(fLocalizedDigits[0]);
     185           0 :         handler.addAttribute(UNUM_INTEGER_FIELD, intBegin, appendTo.length());
     186           0 :         if (options.fAlwaysShowDecimal) {
     187           0 :             appendField(
     188             :                     UNUM_DECIMAL_SEPARATOR_FIELD,
     189             :                     fDecimal,
     190             :                     handler,
     191           0 :                     appendTo);
     192             :         }
     193           0 :         return appendTo;
     194             :     }
     195             :     {
     196           0 :         UnicodeStringAppender appender(appendTo);
     197           0 :         for (int32_t i = interval.getMostSignificantExclusive() - 1;
     198           0 :                 i >= interval.getLeastSignificantInclusive(); --i) {
     199           0 :             if (i == -1) {
     200           0 :                 appender.flush();
     201           0 :                 appendField(
     202             :                         UNUM_DECIMAL_SEPARATOR_FIELD,
     203             :                         fDecimal,
     204             :                         handler,
     205           0 :                         appendTo);
     206           0 :                 fracBegin = appendTo.length();
     207             :             }
     208           0 :             appender.append(fLocalizedDigits[digits.getDigitByExponent(i)]);
     209           0 :             if (grouping.isSeparatorAt(digitsLeftOfDecimal, i)) {
     210           0 :                 appender.flush();
     211           0 :                 appendField(
     212             :                         UNUM_GROUPING_SEPARATOR_FIELD,
     213             :                         fGroupingSeparator,
     214             :                         handler,
     215           0 :                         appendTo);
     216             :             }
     217           0 :             if (i == 0) {
     218           0 :                 appender.flush();
     219           0 :                 if (digitsLeftOfDecimal > 0) {
     220           0 :                     handler.addAttribute(UNUM_INTEGER_FIELD, intBegin, appendTo.length());
     221             :                 }
     222             :             }
     223             :         }
     224           0 :         if (options.fAlwaysShowDecimal && lastDigitPos == 0) {
     225           0 :             appender.flush();
     226           0 :             appendField(
     227             :                     UNUM_DECIMAL_SEPARATOR_FIELD,
     228             :                     fDecimal,
     229             :                     handler,
     230           0 :                     appendTo);
     231             :         }
     232             :     }
     233             :     // lastDigitPos is never > 0 so we are guaranteed that kIntegerField
     234             :     // is already added.
     235           0 :     if (lastDigitPos < 0) {
     236           0 :         handler.addAttribute(UNUM_FRACTION_FIELD, fracBegin, appendTo.length());
     237             :     }
     238           0 :     return appendTo;
     239             : }
     240             : 
     241             : UnicodeString &
     242           0 : DigitFormatter::format(
     243             :         const VisibleDigitsWithExponent &digits,
     244             :         const SciFormatterOptions &options,
     245             :         FieldPositionHandler &handler,
     246             :         UnicodeString &appendTo) const {
     247           0 :     DigitGrouping grouping;
     248             :     format(
     249             :             digits.getMantissa(),
     250             :             grouping,
     251             :             options.fMantissa,
     252             :             handler,
     253           0 :             appendTo);
     254           0 :     const VisibleDigits *exponent = digits.getExponent();
     255           0 :     if (exponent == NULL) {
     256           0 :         return appendTo;
     257             :     }
     258           0 :     int32_t expBegin = appendTo.length();
     259           0 :     appendTo.append(fExponent);
     260           0 :     handler.addAttribute(
     261           0 :             UNUM_EXPONENT_SYMBOL_FIELD, expBegin, appendTo.length());
     262             :     return formatExponent(
     263             :             *exponent,
     264             :             options.fExponent,
     265             :             UNUM_EXPONENT_SIGN_FIELD,
     266             :             UNUM_EXPONENT_FIELD,
     267             :             handler,
     268           0 :             appendTo);
     269             : }
     270             : 
     271           0 : static int32_t formatInt(
     272             :         int32_t value, uint8_t *digits) {
     273           0 :     int32_t idx = 0;
     274           0 :     while (value > 0) {
     275           0 :         digits[idx++] = (uint8_t) (value % 10);
     276           0 :         value /= 10;
     277             :     }
     278           0 :     return idx;
     279             : }
     280             : 
     281             : UnicodeString &
     282           0 : DigitFormatter::formatDigits(
     283             :         const uint8_t *digits,
     284             :         int32_t count,
     285             :         const IntDigitCountRange &range,
     286             :         int32_t intField,
     287             :         FieldPositionHandler &handler,
     288             :         UnicodeString &appendTo) const {
     289           0 :     int32_t i = range.pin(count) - 1;
     290           0 :     int32_t begin = appendTo.length();
     291             : 
     292             :     // Always emit '0' as placeholder for empty string.
     293           0 :     if (i == -1) {
     294           0 :         appendTo.append(fLocalizedDigits[0]);
     295           0 :         handler.addAttribute(intField, begin, appendTo.length());
     296           0 :         return appendTo;
     297             :     }
     298             :     {
     299           0 :         UnicodeStringAppender appender(appendTo);
     300           0 :         for (; i >= count; --i) {
     301           0 :             appender.append(fLocalizedDigits[0]);
     302             :         }
     303           0 :         for (; i >= 0; --i) {
     304           0 :             appender.append(fLocalizedDigits[digits[i]]);
     305             :         }
     306             :     }
     307           0 :     handler.addAttribute(intField, begin, appendTo.length());
     308           0 :     return appendTo;
     309             : }
     310             : 
     311             : UnicodeString &
     312           0 : DigitFormatter::formatExponent(
     313             :         const VisibleDigits &digits,
     314             :         const DigitFormatterIntOptions &options,
     315             :         int32_t signField,
     316             :         int32_t intField,
     317             :         FieldPositionHandler &handler,
     318             :         UnicodeString &appendTo) const {
     319           0 :     UBool neg = digits.isNegative();
     320           0 :     if (neg || options.fAlwaysShowSign) {
     321           0 :         appendField(
     322             :                 signField,
     323             :                 neg ? fNegativeSign : fPositiveSign,
     324             :                 handler,
     325           0 :                 appendTo);
     326             :     }
     327           0 :     int32_t begin = appendTo.length();
     328           0 :     DigitGrouping grouping;
     329           0 :     DigitFormatterOptions expOptions;
     330           0 :     FieldPosition fpos(FieldPosition::DONT_CARE);
     331           0 :     FieldPositionOnlyHandler noHandler(fpos);
     332             :     format(
     333             :             digits,
     334             :             grouping,
     335             :             expOptions,
     336             :             noHandler,
     337           0 :             appendTo);
     338           0 :     handler.addAttribute(intField, begin, appendTo.length());
     339           0 :     return appendTo;
     340             : }
     341             : 
     342             : int32_t
     343           0 : DigitFormatter::countChar32ForExponent(
     344             :         const VisibleDigits &exponent,
     345             :         const DigitFormatterIntOptions &options) const {
     346           0 :     int32_t result = 0;
     347           0 :     UBool neg = exponent.isNegative();
     348           0 :     if (neg || options.fAlwaysShowSign) {
     349           0 :         result += neg ? fNegativeSign.countChar32() : fPositiveSign.countChar32();
     350             :     }
     351           0 :     DigitGrouping grouping;
     352           0 :     DigitFormatterOptions expOptions;
     353           0 :     result += countChar32(grouping, exponent.getInterval(), expOptions);
     354           0 :     return result;
     355             : }
     356             : 
     357             : UnicodeString &
     358           0 : DigitFormatter::formatPositiveInt32(
     359             :         int32_t positiveValue,
     360             :         const IntDigitCountRange &range,
     361             :         FieldPositionHandler &handler,
     362             :         UnicodeString &appendTo) const {
     363             :     // super fast path
     364           0 :     if (fIsStandardDigits && SmallIntFormatter::canFormat(positiveValue, range)) {
     365           0 :         int32_t begin = appendTo.length();
     366           0 :         SmallIntFormatter::format(positiveValue, range, appendTo);
     367           0 :         handler.addAttribute(UNUM_INTEGER_FIELD, begin, appendTo.length());
     368           0 :         return appendTo;
     369             :     }
     370             :     uint8_t digits[10];
     371           0 :     int32_t count = formatInt(positiveValue, digits);
     372             :     return formatDigits(
     373             :             digits,
     374             :             count,
     375             :             range,
     376             :             UNUM_INTEGER_FIELD,
     377             :             handler,
     378           0 :             appendTo);
     379             : }
     380             : 
     381           0 : UBool DigitFormatter::isStandardDigits() const {
     382           0 :     UChar32 cdigit = 0x30;
     383           0 :     for (int32_t i = 0; i < UPRV_LENGTHOF(fLocalizedDigits); ++i) {
     384           0 :         if (fLocalizedDigits[i] != cdigit) {
     385           0 :             return FALSE;
     386             :         }
     387           0 :         ++cdigit;
     388             :     }
     389           0 :     return TRUE;
     390             : }
     391             : 
     392             : UBool
     393           0 : DigitFormatter::equals(const DigitFormatter &rhs) const {
     394           0 :     UBool result = (fGroupingSeparator == rhs.fGroupingSeparator) &&
     395           0 :                    (fDecimal == rhs.fDecimal) &&
     396           0 :                    (fNegativeSign == rhs.fNegativeSign) &&
     397           0 :                    (fPositiveSign == rhs.fPositiveSign) &&
     398           0 :                    (fInfinity.equals(rhs.fInfinity)) &&
     399           0 :                    (fNan.equals(rhs.fNan)) &&
     400           0 :                    (fIsStandardDigits == rhs.fIsStandardDigits) &&
     401           0 :                    (fExponent == rhs.fExponent);
     402             : 
     403           0 :     if (!result) {
     404           0 :         return FALSE;
     405             :     }
     406           0 :     for (int32_t i = 0; i < UPRV_LENGTHOF(fLocalizedDigits); ++i) {
     407           0 :         if (fLocalizedDigits[i] != rhs.fLocalizedDigits[i]) {
     408           0 :             return FALSE;
     409             :         }
     410             :     }
     411           0 :     return TRUE;
     412             : }
     413             : 
     414             : 
     415             : U_NAMESPACE_END
     416             : 
     417             : #endif /* #if !UCONFIG_NO_FORMATTING */

Generated by: LCOV version 1.13