tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

number_simple.cpp (7201B)


      1 // © 2017 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 
      4 #include "unicode/utypes.h"
      5 
      6 #if !UCONFIG_NO_FORMATTING
      7 
      8 #include "unicode/numberformatter.h"
      9 #include "unicode/simplenumberformatter.h"
     10 #include "number_formatimpl.h"
     11 #include "number_utils.h"
     12 #include "number_patternmodifier.h"
     13 #include "number_utypes.h"
     14 
     15 using namespace icu;
     16 using namespace icu::number;
     17 using namespace icu::number::impl;
     18 
     19 
     20 SimpleNumber
     21 SimpleNumber::forInt64(int64_t value, UErrorCode& status) {
     22    if (U_FAILURE(status)) {
     23        return {};
     24    }
     25    auto* results = new UFormattedNumberData();
     26    if (results == nullptr) {
     27        status = U_MEMORY_ALLOCATION_ERROR;
     28        return {};
     29    }
     30    results->quantity.setToLong(value);
     31    return SimpleNumber(results, status);
     32 }
     33 
     34 SimpleNumber::SimpleNumber(UFormattedNumberData* data, UErrorCode& status) : fData(data) {
     35    if (U_FAILURE(status)) {
     36        return;
     37    }
     38    if (fData == nullptr) {
     39        status = U_ILLEGAL_ARGUMENT_ERROR;
     40        return;
     41    }
     42    if (fData->quantity.isNegative()) {
     43        fSign = UNUM_SIMPLE_NUMBER_MINUS_SIGN;
     44    } else {
     45        fSign = UNUM_SIMPLE_NUMBER_NO_SIGN;
     46    }
     47 }
     48 
     49 void SimpleNumber::cleanup() {
     50    delete fData;
     51    fData = nullptr;
     52 }
     53 
     54 void SimpleNumber::multiplyByPowerOfTen(int32_t power, UErrorCode& status) {
     55    if (U_FAILURE(status)) {
     56        return;
     57    }
     58    if (fData == nullptr) {
     59        status = U_INVALID_STATE_ERROR;
     60        return;
     61    }
     62    fData->quantity.adjustMagnitude(power);
     63 }
     64 
     65 void SimpleNumber::roundTo(int32_t position, UNumberFormatRoundingMode roundingMode, UErrorCode& status) {
     66    if (U_FAILURE(status)) {
     67        return;
     68    }
     69    if (fData == nullptr) {
     70        status = U_INVALID_STATE_ERROR;
     71        return;
     72    }
     73    fData->quantity.roundToMagnitude(position, roundingMode, status);
     74 }
     75 
     76 void SimpleNumber::setMinimumIntegerDigits(uint32_t position, UErrorCode& status) {
     77    if (U_FAILURE(status)) {
     78        return;
     79    }
     80    if (fData == nullptr) {
     81        status = U_INVALID_STATE_ERROR;
     82        return;
     83    }
     84    fData->quantity.decreaseMinIntegerTo(position);
     85    fData->quantity.increaseMinIntegerTo(position);
     86 }
     87 
     88 void SimpleNumber::setMinimumFractionDigits(uint32_t position, UErrorCode& status) {
     89    if (U_FAILURE(status)) {
     90        return;
     91    }
     92    if (fData == nullptr) {
     93        status = U_INVALID_STATE_ERROR;
     94        return;
     95    }
     96    fData->quantity.setMinFraction(position);
     97 }
     98 
     99 void SimpleNumber::setMaximumIntegerDigits(uint32_t position, UErrorCode& status) {
    100    if (U_FAILURE(status)) {
    101        return;
    102    }
    103    if (fData == nullptr) {
    104        status = U_INVALID_STATE_ERROR;
    105        return;
    106    }
    107    fData->quantity.decreaseMinIntegerTo(position);
    108    fData->quantity.applyMaxInteger(position);
    109 }
    110 
    111 void SimpleNumber::setSign(USimpleNumberSign sign, UErrorCode& status) {
    112    if (U_FAILURE(status)) {
    113        return;
    114    }
    115    if (fData == nullptr) {
    116        status = U_INVALID_STATE_ERROR;
    117        return;
    118    }
    119    fSign = sign;
    120 }
    121 
    122 
    123 void SimpleNumberFormatter::cleanup() {
    124    delete fOwnedSymbols;
    125    delete fMicros;
    126    delete fPatternModifier;
    127    fOwnedSymbols = nullptr;
    128    fMicros = nullptr;
    129    fPatternModifier = nullptr;
    130 }
    131 
    132 SimpleNumberFormatter SimpleNumberFormatter::forLocale(const icu::Locale &locale, UErrorCode &status) {
    133    return SimpleNumberFormatter::forLocaleAndGroupingStrategy(locale, UNUM_GROUPING_AUTO, status);
    134 }
    135 
    136 SimpleNumberFormatter SimpleNumberFormatter::forLocaleAndGroupingStrategy(
    137        const icu::Locale &locale,
    138        UNumberGroupingStrategy groupingStrategy,
    139        UErrorCode &status) {
    140    SimpleNumberFormatter retval;
    141    retval.fOwnedSymbols = new DecimalFormatSymbols(locale, status);
    142    if (U_FAILURE(status)) {
    143        return retval;
    144    }
    145    if (retval.fOwnedSymbols == nullptr) {
    146        status = U_MEMORY_ALLOCATION_ERROR;
    147        return retval;
    148    }
    149    retval.initialize(locale, *retval.fOwnedSymbols, groupingStrategy, status);
    150    return retval;
    151 }
    152 
    153 
    154 SimpleNumberFormatter SimpleNumberFormatter::forLocaleAndSymbolsAndGroupingStrategy(
    155        const icu::Locale &locale,
    156        const DecimalFormatSymbols &symbols,
    157        UNumberGroupingStrategy groupingStrategy,
    158        UErrorCode &status) {
    159    SimpleNumberFormatter retval;
    160    retval.initialize(locale, symbols, groupingStrategy, status);
    161    return retval;
    162 }
    163 
    164 
    165 void SimpleNumberFormatter::initialize(
    166        const icu::Locale &locale,
    167        const DecimalFormatSymbols &symbols,
    168        UNumberGroupingStrategy groupingStrategy,
    169        UErrorCode &status) {
    170    if (U_FAILURE(status)) {
    171        return;
    172    }
    173 
    174    fMicros = new SimpleMicroProps();
    175    if (fMicros == nullptr) {
    176        status = U_MEMORY_ALLOCATION_ERROR;
    177        return;
    178    }
    179    fMicros->symbols = &symbols;
    180 
    181    const auto* pattern = utils::getPatternForStyle(
    182        locale,
    183        symbols.getNumberingSystemName(),
    184        CLDR_PATTERN_STYLE_DECIMAL,
    185        status);
    186    if (U_FAILURE(status)) {
    187        return;
    188    }
    189 
    190    ParsedPatternInfo patternInfo;
    191    PatternParser::parseToPatternInfo(UnicodeString(pattern), patternInfo, status);
    192    if (U_FAILURE(status)) {
    193        return;
    194    }
    195 
    196    auto grouper = Grouper::forStrategy(groupingStrategy);
    197    grouper.setLocaleData(patternInfo, locale);
    198    fMicros->grouping = grouper;
    199 
    200    MutablePatternModifier patternModifier(false);
    201    patternModifier.setPatternInfo(&patternInfo, kUndefinedField);
    202    patternModifier.setPatternAttributes(UNUM_SIGN_EXCEPT_ZERO, false, false);
    203    patternModifier.setSymbols(fMicros->symbols, {}, UNUM_UNIT_WIDTH_SHORT, nullptr, status);
    204 
    205    fPatternModifier = new AdoptingSignumModifierStore(patternModifier.createImmutableForPlural(StandardPlural::COUNT, status));
    206 
    207    fGroupingStrategy = groupingStrategy;
    208 }
    209 
    210 FormattedNumber SimpleNumberFormatter::format(SimpleNumber value, UErrorCode &status) const {
    211    formatImpl(value.fData, value.fSign, status);
    212 
    213    // Do not save the results object if we encountered a failure.
    214    if (U_SUCCESS(status)) {
    215        auto* temp = value.fData;
    216        value.fData = nullptr;
    217        return FormattedNumber(temp);
    218    } else {
    219        return FormattedNumber(status);
    220    }
    221 }
    222 
    223 void SimpleNumberFormatter::formatImpl(UFormattedNumberData* data, USimpleNumberSign sign, UErrorCode &status) const {
    224    if (U_FAILURE(status)) {
    225        return;
    226    }
    227    if (data == nullptr) {
    228        status = U_ILLEGAL_ARGUMENT_ERROR;
    229        return;
    230    }
    231    if (fPatternModifier == nullptr || fMicros == nullptr) {
    232        status = U_INVALID_STATE_ERROR;
    233        return;
    234    }
    235 
    236    Signum signum;
    237    if (sign == UNUM_SIMPLE_NUMBER_MINUS_SIGN) {
    238        signum = SIGNUM_NEG;
    239    } else if (sign == UNUM_SIMPLE_NUMBER_PLUS_SIGN) {
    240        signum = SIGNUM_POS;
    241    } else {
    242        signum = SIGNUM_POS_ZERO;
    243    }
    244 
    245    const Modifier* modifier = (*fPatternModifier)[signum];
    246    auto length = NumberFormatterImpl::writeNumber(
    247        *fMicros,
    248        data->quantity,
    249        data->getStringRef(),
    250        0,
    251        status);
    252    length += modifier->apply(data->getStringRef(), 0, length, status);
    253    data->getStringRef().writeTerminator(status);
    254 }
    255 
    256 #endif /* #if !UCONFIG_NO_FORMATTING */