tor-browser

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

pluralranges.cpp (4926B)


      1 // © 2018 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 // Allow implicit conversion from char16_t* to UnicodeString for this file:
      9 // Helpful in toString methods and elsewhere.
     10 #define UNISTR_FROM_STRING_EXPLICIT
     11 
     12 #include "unicode/numberrangeformatter.h"
     13 #include "pluralranges.h"
     14 #include "uresimp.h"
     15 #include "charstr.h"
     16 #include "uassert.h"
     17 #include "util.h"
     18 #include "numrange_impl.h"
     19 
     20 U_NAMESPACE_BEGIN
     21 
     22 
     23 namespace {
     24 
     25 class PluralRangesDataSink : public ResourceSink {
     26  public:
     27    PluralRangesDataSink(StandardPluralRanges& output) : fOutput(output) {}
     28 
     29    void put(const char* /*key*/, ResourceValue& value, UBool /*noFallback*/, UErrorCode& status) override {
     30        ResourceArray entriesArray = value.getArray(status);
     31        if (U_FAILURE(status)) { return; }
     32        fOutput.setCapacity(entriesArray.getSize(), status);
     33        if (U_FAILURE(status)) { return; }
     34        for (int i = 0; entriesArray.getValue(i, value); i++) {
     35            ResourceArray pluralFormsArray = value.getArray(status);
     36            if (U_FAILURE(status)) { return; }
     37            if (pluralFormsArray.getSize() != 3) {
     38                status = U_RESOURCE_TYPE_MISMATCH;
     39                return;
     40            }
     41            pluralFormsArray.getValue(0, value);
     42            StandardPlural::Form first = StandardPlural::fromString(value.getUnicodeString(status), status);
     43            if (U_FAILURE(status)) { return; }
     44            pluralFormsArray.getValue(1, value);
     45            StandardPlural::Form second = StandardPlural::fromString(value.getUnicodeString(status), status);
     46            if (U_FAILURE(status)) { return; }
     47            pluralFormsArray.getValue(2, value);
     48            StandardPlural::Form result = StandardPlural::fromString(value.getUnicodeString(status), status);
     49            if (U_FAILURE(status)) { return; }
     50            fOutput.addPluralRange(first, second, result);
     51        }
     52    }
     53 
     54  private:
     55    StandardPluralRanges& fOutput;
     56 };
     57 
     58 void getPluralRangesData(const Locale& locale, StandardPluralRanges& output, UErrorCode& status) {
     59    LocalUResourceBundlePointer rb(ures_openDirect(nullptr, "pluralRanges", &status));
     60    if (U_FAILURE(status)) { return; }
     61 
     62    CharString dataPath;
     63    dataPath.append("locales/", -1, status);
     64    dataPath.append(locale.getLanguage(), -1, status);
     65    if (U_FAILURE(status)) { return; }
     66    int32_t setLen;
     67    // Not all languages are covered: fail gracefully
     68    UErrorCode internalStatus = U_ZERO_ERROR;
     69    const char16_t* set = ures_getStringByKeyWithFallback(rb.getAlias(), dataPath.data(), &setLen, &internalStatus);
     70    if (U_FAILURE(internalStatus)) { return; }
     71 
     72    dataPath.clear();
     73    dataPath.append("rules/", -1, status);
     74    dataPath.appendInvariantChars(set, setLen, status);
     75    if (U_FAILURE(status)) { return; }
     76    PluralRangesDataSink sink(output);
     77    ures_getAllItemsWithFallback(rb.getAlias(), dataPath.data(), sink, status);
     78 }
     79 
     80 } // namespace
     81 
     82 
     83 StandardPluralRanges
     84 StandardPluralRanges::forLocale(const Locale& locale, UErrorCode& status) {
     85    StandardPluralRanges result;
     86    getPluralRangesData(locale, result, status);
     87    return result;
     88 }
     89 
     90 StandardPluralRanges
     91 StandardPluralRanges::copy(UErrorCode& status) const {
     92    StandardPluralRanges result;
     93    if (fTriplesLen > result.fTriples.getCapacity()) {
     94        if (result.fTriples.resize(fTriplesLen) == nullptr) {
     95            status = U_MEMORY_ALLOCATION_ERROR;
     96            return result;
     97        }
     98    }
     99    uprv_memcpy(result.fTriples.getAlias(),
    100        fTriples.getAlias(),
    101        fTriplesLen * sizeof(fTriples[0]));
    102    result.fTriplesLen = fTriplesLen;
    103    return result;
    104 }
    105 
    106 LocalPointer<StandardPluralRanges>
    107 StandardPluralRanges::toPointer(UErrorCode& status) && noexcept {
    108    return LocalPointer<StandardPluralRanges>(new StandardPluralRanges(std::move(*this)), status);
    109 }
    110 
    111 void StandardPluralRanges::addPluralRange(
    112        StandardPlural::Form first,
    113        StandardPlural::Form second,
    114        StandardPlural::Form result) {
    115    U_ASSERT(fTriplesLen < fTriples.getCapacity());
    116    fTriples[fTriplesLen] = {first, second, result};
    117    fTriplesLen++;
    118 }
    119 
    120 void StandardPluralRanges::setCapacity(int32_t length, UErrorCode& status) {
    121    if (U_FAILURE(status)) { return; }
    122    if (length > fTriples.getCapacity()) {
    123        if (fTriples.resize(length, 0) == nullptr) {
    124            status = U_MEMORY_ALLOCATION_ERROR;
    125        }
    126    }
    127 }
    128 
    129 StandardPlural::Form
    130 StandardPluralRanges::resolve(StandardPlural::Form first, StandardPlural::Form second) const {
    131    for (int32_t i=0; i<fTriplesLen; i++) {
    132        const auto& triple = fTriples[i];
    133        if (triple.first == first && triple.second == second) {
    134            return triple.result;
    135        }
    136    }
    137    // Default fallback
    138    return StandardPlural::OTHER;
    139 }
    140 
    141 
    142 U_NAMESPACE_END
    143 
    144 #endif /* #if !UCONFIG_NO_FORMATTING */