Home | History | Annotate | Download | only in i18n
      1 /*
      2  * Copyright (C) 2015, International Business Machines
      3  * Corporation and others.  All Rights Reserved.
      4  *
      5  * file name: digitaffixesandpadding.cpp
      6  */
      7 
      8 #include "unicode/utypes.h"
      9 
     10 #if !UCONFIG_NO_FORMATTING
     11 
     12 #include "unicode/plurrule.h"
     13 #include "charstr.h"
     14 #include "digitaffix.h"
     15 #include "digitaffixesandpadding.h"
     16 #include "digitlst.h"
     17 #include "uassert.h"
     18 #include "valueformatter.h"
     19 #include "visibledigits.h"
     20 
     21 U_NAMESPACE_BEGIN
     22 
     23 UBool
     24 DigitAffixesAndPadding::needsPluralRules() const {
     25     return (
     26             fPositivePrefix.hasMultipleVariants() ||
     27             fPositiveSuffix.hasMultipleVariants() ||
     28             fNegativePrefix.hasMultipleVariants() ||
     29             fNegativeSuffix.hasMultipleVariants());
     30 }
     31 
     32 UnicodeString &
     33 DigitAffixesAndPadding::formatInt32(
     34         int32_t value,
     35         const ValueFormatter &formatter,
     36         FieldPositionHandler &handler,
     37         const PluralRules *optPluralRules,
     38         UnicodeString &appendTo,
     39         UErrorCode &status) const {
     40     if (U_FAILURE(status)) {
     41         return appendTo;
     42     }
     43     if (optPluralRules != NULL || fWidth > 0 || !formatter.isFastFormattable(value)) {
     44         VisibleDigitsWithExponent digits;
     45         formatter.toVisibleDigitsWithExponent(
     46                 (int64_t) value, digits, status);
     47         return format(
     48                 digits,
     49                 formatter,
     50                 handler,
     51                 optPluralRules,
     52                 appendTo,
     53                 status);
     54     }
     55     UBool bPositive = value >= 0;
     56     const DigitAffix *prefix = bPositive ? &fPositivePrefix.getOtherVariant() : &fNegativePrefix.getOtherVariant();
     57     const DigitAffix *suffix = bPositive ? &fPositiveSuffix.getOtherVariant() : &fNegativeSuffix.getOtherVariant();
     58     if (value < 0) {
     59         value = -value;
     60     }
     61     prefix->format(handler, appendTo);
     62     formatter.formatInt32(value, handler, appendTo);
     63     return suffix->format(handler, appendTo);
     64 }
     65 
     66 static UnicodeString &
     67 formatAffix(
     68         const DigitAffix *affix,
     69         FieldPositionHandler &handler,
     70         UnicodeString &appendTo) {
     71     if (affix) {
     72         affix->format(handler, appendTo);
     73     }
     74     return appendTo;
     75 }
     76 
     77 static int32_t
     78 countAffixChar32(const DigitAffix *affix) {
     79     if (affix) {
     80         return affix->countChar32();
     81     }
     82     return 0;
     83 }
     84 
     85 UnicodeString &
     86 DigitAffixesAndPadding::format(
     87         const VisibleDigitsWithExponent &digits,
     88         const ValueFormatter &formatter,
     89         FieldPositionHandler &handler,
     90         const PluralRules *optPluralRules,
     91         UnicodeString &appendTo,
     92         UErrorCode &status) const {
     93     if (U_FAILURE(status)) {
     94         return appendTo;
     95     }
     96     const DigitAffix *prefix = NULL;
     97     const DigitAffix *suffix = NULL;
     98     if (!digits.isNaN()) {
     99         UBool bPositive = !digits.isNegative();
    100         const PluralAffix *pluralPrefix = bPositive ? &fPositivePrefix : &fNegativePrefix;
    101         const PluralAffix *pluralSuffix = bPositive ? &fPositiveSuffix : &fNegativeSuffix;
    102         if (optPluralRules == NULL || digits.isInfinite()) {
    103             prefix = &pluralPrefix->getOtherVariant();
    104             suffix = &pluralSuffix->getOtherVariant();
    105         } else {
    106             UnicodeString count(optPluralRules->select(digits));
    107             prefix = &pluralPrefix->getByCategory(count);
    108             suffix = &pluralSuffix->getByCategory(count);
    109         }
    110     }
    111     if (fWidth <= 0) {
    112         formatAffix(prefix, handler, appendTo);
    113         formatter.format(digits, handler, appendTo);
    114         return formatAffix(suffix, handler, appendTo);
    115     }
    116     int32_t codePointCount = countAffixChar32(prefix) + formatter.countChar32(digits) + countAffixChar32(suffix);
    117     int32_t paddingCount = fWidth - codePointCount;
    118     switch (fPadPosition) {
    119     case kPadBeforePrefix:
    120         appendPadding(paddingCount, appendTo);
    121         formatAffix(prefix, handler, appendTo);
    122         formatter.format(digits, handler, appendTo);
    123         return formatAffix(suffix, handler, appendTo);
    124     case kPadAfterPrefix:
    125         formatAffix(prefix, handler, appendTo);
    126         appendPadding(paddingCount, appendTo);
    127         formatter.format(digits, handler, appendTo);
    128         return formatAffix(suffix, handler, appendTo);
    129     case kPadBeforeSuffix:
    130         formatAffix(prefix, handler, appendTo);
    131         formatter.format(digits, handler, appendTo);
    132         appendPadding(paddingCount, appendTo);
    133         return formatAffix(suffix, handler, appendTo);
    134     case kPadAfterSuffix:
    135         formatAffix(prefix, handler, appendTo);
    136         formatter.format(digits, handler, appendTo);
    137         formatAffix(suffix, handler, appendTo);
    138         return appendPadding(paddingCount, appendTo);
    139     default:
    140         U_ASSERT(FALSE);
    141         return appendTo;
    142     }
    143 }
    144 
    145 UnicodeString &
    146 DigitAffixesAndPadding::format(
    147         DigitList &value,
    148         const ValueFormatter &formatter,
    149         FieldPositionHandler &handler,
    150         const PluralRules *optPluralRules,
    151         UnicodeString &appendTo,
    152         UErrorCode &status) const {
    153     VisibleDigitsWithExponent digits;
    154     formatter.toVisibleDigitsWithExponent(
    155             value, digits, status);
    156     if (U_FAILURE(status)) {
    157         return appendTo;
    158     }
    159     return format(
    160             digits, formatter, handler, optPluralRules, appendTo, status);
    161 }
    162 
    163 UnicodeString &
    164 DigitAffixesAndPadding::appendPadding(int32_t paddingCount, UnicodeString &appendTo) const {
    165     for (int32_t i = 0; i < paddingCount; ++i) {
    166         appendTo.append(fPadChar);
    167     }
    168     return appendTo;
    169 }
    170 
    171 
    172 U_NAMESPACE_END
    173 #endif /* #if !UCONFIG_NO_FORMATTING */
    174