11cb0ef41Sopenharmony_ci// © 2018 and later: Unicode, Inc. and others. 21cb0ef41Sopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ci#include "unicode/utypes.h" 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ci#if !UCONFIG_NO_FORMATTING 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci// Allow implicit conversion from char16_t* to UnicodeString for this file: 91cb0ef41Sopenharmony_ci// Helpful in toString methods and elsewhere. 101cb0ef41Sopenharmony_ci#define UNISTR_FROM_STRING_EXPLICIT 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci#include "unicode/numberrangeformatter.h" 131cb0ef41Sopenharmony_ci#include "pluralranges.h" 141cb0ef41Sopenharmony_ci#include "uresimp.h" 151cb0ef41Sopenharmony_ci#include "charstr.h" 161cb0ef41Sopenharmony_ci#include "uassert.h" 171cb0ef41Sopenharmony_ci#include "util.h" 181cb0ef41Sopenharmony_ci#include "numrange_impl.h" 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_ciU_NAMESPACE_BEGIN 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_cinamespace { 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ciclass PluralRangesDataSink : public ResourceSink { 261cb0ef41Sopenharmony_ci public: 271cb0ef41Sopenharmony_ci PluralRangesDataSink(StandardPluralRanges& output) : fOutput(output) {} 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci void put(const char* /*key*/, ResourceValue& value, UBool /*noFallback*/, UErrorCode& status) override { 301cb0ef41Sopenharmony_ci ResourceArray entriesArray = value.getArray(status); 311cb0ef41Sopenharmony_ci if (U_FAILURE(status)) { return; } 321cb0ef41Sopenharmony_ci fOutput.setCapacity(entriesArray.getSize(), status); 331cb0ef41Sopenharmony_ci if (U_FAILURE(status)) { return; } 341cb0ef41Sopenharmony_ci for (int i = 0; entriesArray.getValue(i, value); i++) { 351cb0ef41Sopenharmony_ci ResourceArray pluralFormsArray = value.getArray(status); 361cb0ef41Sopenharmony_ci if (U_FAILURE(status)) { return; } 371cb0ef41Sopenharmony_ci if (pluralFormsArray.getSize() != 3) { 381cb0ef41Sopenharmony_ci status = U_RESOURCE_TYPE_MISMATCH; 391cb0ef41Sopenharmony_ci return; 401cb0ef41Sopenharmony_ci } 411cb0ef41Sopenharmony_ci pluralFormsArray.getValue(0, value); 421cb0ef41Sopenharmony_ci StandardPlural::Form first = StandardPlural::fromString(value.getUnicodeString(status), status); 431cb0ef41Sopenharmony_ci if (U_FAILURE(status)) { return; } 441cb0ef41Sopenharmony_ci pluralFormsArray.getValue(1, value); 451cb0ef41Sopenharmony_ci StandardPlural::Form second = StandardPlural::fromString(value.getUnicodeString(status), status); 461cb0ef41Sopenharmony_ci if (U_FAILURE(status)) { return; } 471cb0ef41Sopenharmony_ci pluralFormsArray.getValue(2, value); 481cb0ef41Sopenharmony_ci StandardPlural::Form result = StandardPlural::fromString(value.getUnicodeString(status), status); 491cb0ef41Sopenharmony_ci if (U_FAILURE(status)) { return; } 501cb0ef41Sopenharmony_ci fOutput.addPluralRange(first, second, result); 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci private: 551cb0ef41Sopenharmony_ci StandardPluralRanges& fOutput; 561cb0ef41Sopenharmony_ci}; 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_civoid getPluralRangesData(const Locale& locale, StandardPluralRanges& output, UErrorCode& status) { 591cb0ef41Sopenharmony_ci LocalUResourceBundlePointer rb(ures_openDirect(nullptr, "pluralRanges", &status)); 601cb0ef41Sopenharmony_ci if (U_FAILURE(status)) { return; } 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci CharString dataPath; 631cb0ef41Sopenharmony_ci dataPath.append("locales/", -1, status); 641cb0ef41Sopenharmony_ci dataPath.append(locale.getLanguage(), -1, status); 651cb0ef41Sopenharmony_ci if (U_FAILURE(status)) { return; } 661cb0ef41Sopenharmony_ci int32_t setLen; 671cb0ef41Sopenharmony_ci // Not all languages are covered: fail gracefully 681cb0ef41Sopenharmony_ci UErrorCode internalStatus = U_ZERO_ERROR; 691cb0ef41Sopenharmony_ci const char16_t* set = ures_getStringByKeyWithFallback(rb.getAlias(), dataPath.data(), &setLen, &internalStatus); 701cb0ef41Sopenharmony_ci if (U_FAILURE(internalStatus)) { return; } 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci dataPath.clear(); 731cb0ef41Sopenharmony_ci dataPath.append("rules/", -1, status); 741cb0ef41Sopenharmony_ci dataPath.appendInvariantChars(set, setLen, status); 751cb0ef41Sopenharmony_ci if (U_FAILURE(status)) { return; } 761cb0ef41Sopenharmony_ci PluralRangesDataSink sink(output); 771cb0ef41Sopenharmony_ci ures_getAllItemsWithFallback(rb.getAlias(), dataPath.data(), sink, status); 781cb0ef41Sopenharmony_ci} 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci} // namespace 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ciStandardPluralRanges 841cb0ef41Sopenharmony_ciStandardPluralRanges::forLocale(const Locale& locale, UErrorCode& status) { 851cb0ef41Sopenharmony_ci StandardPluralRanges result; 861cb0ef41Sopenharmony_ci getPluralRangesData(locale, result, status); 871cb0ef41Sopenharmony_ci return result; 881cb0ef41Sopenharmony_ci} 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ciStandardPluralRanges 911cb0ef41Sopenharmony_ciStandardPluralRanges::copy(UErrorCode& status) const { 921cb0ef41Sopenharmony_ci StandardPluralRanges result; 931cb0ef41Sopenharmony_ci if (fTriplesLen > result.fTriples.getCapacity()) { 941cb0ef41Sopenharmony_ci if (result.fTriples.resize(fTriplesLen) == nullptr) { 951cb0ef41Sopenharmony_ci status = U_MEMORY_ALLOCATION_ERROR; 961cb0ef41Sopenharmony_ci return result; 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci uprv_memcpy(result.fTriples.getAlias(), 1001cb0ef41Sopenharmony_ci fTriples.getAlias(), 1011cb0ef41Sopenharmony_ci fTriplesLen * sizeof(fTriples[0])); 1021cb0ef41Sopenharmony_ci result.fTriplesLen = fTriplesLen; 1031cb0ef41Sopenharmony_ci return result; 1041cb0ef41Sopenharmony_ci} 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ciLocalPointer<StandardPluralRanges> 1071cb0ef41Sopenharmony_ciStandardPluralRanges::toPointer(UErrorCode& status) && noexcept { 1081cb0ef41Sopenharmony_ci return LocalPointer<StandardPluralRanges>(new StandardPluralRanges(std::move(*this)), status); 1091cb0ef41Sopenharmony_ci} 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_civoid StandardPluralRanges::addPluralRange( 1121cb0ef41Sopenharmony_ci StandardPlural::Form first, 1131cb0ef41Sopenharmony_ci StandardPlural::Form second, 1141cb0ef41Sopenharmony_ci StandardPlural::Form result) { 1151cb0ef41Sopenharmony_ci U_ASSERT(fTriplesLen < fTriples.getCapacity()); 1161cb0ef41Sopenharmony_ci fTriples[fTriplesLen] = {first, second, result}; 1171cb0ef41Sopenharmony_ci fTriplesLen++; 1181cb0ef41Sopenharmony_ci} 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_civoid StandardPluralRanges::setCapacity(int32_t length, UErrorCode& status) { 1211cb0ef41Sopenharmony_ci if (U_FAILURE(status)) { return; } 1221cb0ef41Sopenharmony_ci if (length > fTriples.getCapacity()) { 1231cb0ef41Sopenharmony_ci if (fTriples.resize(length, 0) == nullptr) { 1241cb0ef41Sopenharmony_ci status = U_MEMORY_ALLOCATION_ERROR; 1251cb0ef41Sopenharmony_ci } 1261cb0ef41Sopenharmony_ci } 1271cb0ef41Sopenharmony_ci} 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ciStandardPlural::Form 1301cb0ef41Sopenharmony_ciStandardPluralRanges::resolve(StandardPlural::Form first, StandardPlural::Form second) const { 1311cb0ef41Sopenharmony_ci for (int32_t i=0; i<fTriplesLen; i++) { 1321cb0ef41Sopenharmony_ci const auto& triple = fTriples[i]; 1331cb0ef41Sopenharmony_ci if (triple.first == first && triple.second == second) { 1341cb0ef41Sopenharmony_ci return triple.result; 1351cb0ef41Sopenharmony_ci } 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci // Default fallback 1381cb0ef41Sopenharmony_ci return StandardPlural::OTHER; 1391cb0ef41Sopenharmony_ci} 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ciU_NAMESPACE_END 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ci#endif /* #if !UCONFIG_NO_FORMATTING */ 145