tor-browser

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

number_grouping.cpp (3615B)


      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 "number_patternstring.h"
     10 #include "uresimp.h"
     11 
     12 using namespace icu;
     13 using namespace icu::number;
     14 using namespace icu::number::impl;
     15 
     16 namespace {
     17 
     18 int16_t getMinGroupingForLocale(const Locale& locale) {
     19    // TODO: Cache this?
     20    UErrorCode localStatus = U_ZERO_ERROR;
     21    LocalUResourceBundlePointer bundle(ures_open(nullptr, locale.getName(), &localStatus));
     22    int32_t resultLen = 0;
     23    const char16_t* result = ures_getStringByKeyWithFallback(
     24        bundle.getAlias(),
     25        "NumberElements/minimumGroupingDigits",
     26        &resultLen,
     27        &localStatus);
     28    // TODO: Is it safe to assume resultLen == 1? Would locales set minGrouping >= 10?
     29    if (U_FAILURE(localStatus) || resultLen != 1) {
     30        return 1;
     31    }
     32    return result[0] - u'0';
     33 }
     34 
     35 }
     36 
     37 Grouper Grouper::forStrategy(UNumberGroupingStrategy grouping) {
     38    switch (grouping) {
     39    case UNUM_GROUPING_OFF:
     40        return {-1, -1, -2, grouping};
     41    case UNUM_GROUPING_AUTO:
     42        return {-2, -2, -2, grouping};
     43    case UNUM_GROUPING_MIN2:
     44        return {-2, -2, -3, grouping};
     45    case UNUM_GROUPING_ON_ALIGNED:
     46        return {-4, -4, 1, grouping};
     47    case UNUM_GROUPING_THOUSANDS:
     48        return {3, 3, 1, grouping};
     49    default:
     50        UPRV_UNREACHABLE_EXIT;
     51    }
     52 }
     53 
     54 Grouper Grouper::forProperties(const DecimalFormatProperties& properties) {
     55    if (!properties.groupingUsed) {
     56        return forStrategy(UNUM_GROUPING_OFF);
     57    }
     58    auto grouping1 = static_cast<int16_t>(properties.groupingSize);
     59    auto grouping2 = static_cast<int16_t>(properties.secondaryGroupingSize);
     60    auto minGrouping = static_cast<int16_t>(properties.minimumGroupingDigits);
     61    grouping1 = grouping1 > 0 ? grouping1 : grouping2 > 0 ? grouping2 : grouping1;
     62    grouping2 = grouping2 > 0 ? grouping2 : grouping1;
     63    return {grouping1, grouping2, minGrouping, UNUM_GROUPING_COUNT};
     64 }
     65 
     66 void Grouper::setLocaleData(const impl::ParsedPatternInfo &patternInfo, const Locale& locale) {
     67    if (fMinGrouping == -2) {
     68        fMinGrouping = getMinGroupingForLocale(locale);
     69    } else if (fMinGrouping == -3) {
     70        fMinGrouping = static_cast<int16_t>(uprv_max(2, getMinGroupingForLocale(locale)));
     71    } else {
     72        // leave fMinGrouping alone
     73    }
     74    if (fGrouping1 != -2 && fGrouping2 != -4) {
     75        return;
     76    }
     77    auto grouping1 = static_cast<int16_t> (patternInfo.positive.groupingSizes & 0xffff);
     78    auto grouping2 = static_cast<int16_t> ((patternInfo.positive.groupingSizes >> 16) & 0xffff);
     79    auto grouping3 = static_cast<int16_t> ((patternInfo.positive.groupingSizes >> 32) & 0xffff);
     80    if (grouping2 == -1) {
     81        grouping1 = fGrouping1 == -4 ? static_cast<short>(3) : static_cast<short>(-1);
     82    }
     83    if (grouping3 == -1) {
     84        grouping2 = grouping1;
     85    }
     86    fGrouping1 = grouping1;
     87    fGrouping2 = grouping2;
     88 }
     89 
     90 bool Grouper::groupAtPosition(int32_t position, const impl::DecimalQuantity &value) const {
     91    U_ASSERT(fGrouping1 > -2);
     92    if (fGrouping1 == -1 || fGrouping1 == 0) {
     93        // Either -1 or 0 means "no grouping"
     94        return false;
     95    }
     96    position -= fGrouping1;
     97    return position >= 0 && (position % fGrouping2) == 0
     98           && value.getUpperDisplayMagnitude() - fGrouping1 + 1 >= fMinGrouping;
     99 }
    100 
    101 int16_t Grouper::getPrimary() const {
    102    return fGrouping1;
    103 }
    104 
    105 int16_t Grouper::getSecondary() const {
    106    return fGrouping2;
    107 }
    108 
    109 #endif /* #if !UCONFIG_NO_FORMATTING */