12e5b6d6dSopenharmony_ci// © 2018 and later: Unicode, Inc. and others. 22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 32e5b6d6dSopenharmony_ci 42e5b6d6dSopenharmony_ci#include "unicode/utypes.h" 52e5b6d6dSopenharmony_ci 62e5b6d6dSopenharmony_ci#if !UCONFIG_NO_FORMATTING 72e5b6d6dSopenharmony_ci 82e5b6d6dSopenharmony_ci// Allow implicit conversion from char16_t* to UnicodeString for this file: 92e5b6d6dSopenharmony_ci// Helpful in toString methods and elsewhere. 102e5b6d6dSopenharmony_ci#define UNISTR_FROM_STRING_EXPLICIT 112e5b6d6dSopenharmony_ci 122e5b6d6dSopenharmony_ci#include "unicode/numberrangeformatter.h" 132e5b6d6dSopenharmony_ci#include "pluralranges.h" 142e5b6d6dSopenharmony_ci#include "uresimp.h" 152e5b6d6dSopenharmony_ci#include "charstr.h" 162e5b6d6dSopenharmony_ci#include "uassert.h" 172e5b6d6dSopenharmony_ci#include "util.h" 182e5b6d6dSopenharmony_ci#include "numrange_impl.h" 192e5b6d6dSopenharmony_ci 202e5b6d6dSopenharmony_ciU_NAMESPACE_BEGIN 212e5b6d6dSopenharmony_ci 222e5b6d6dSopenharmony_ci 232e5b6d6dSopenharmony_cinamespace { 242e5b6d6dSopenharmony_ci 252e5b6d6dSopenharmony_ciclass PluralRangesDataSink : public ResourceSink { 262e5b6d6dSopenharmony_ci public: 272e5b6d6dSopenharmony_ci PluralRangesDataSink(StandardPluralRanges& output) : fOutput(output) {} 282e5b6d6dSopenharmony_ci 292e5b6d6dSopenharmony_ci void put(const char* /*key*/, ResourceValue& value, UBool /*noFallback*/, UErrorCode& status) U_OVERRIDE { 302e5b6d6dSopenharmony_ci ResourceArray entriesArray = value.getArray(status); 312e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { return; } 322e5b6d6dSopenharmony_ci fOutput.setCapacity(entriesArray.getSize(), status); 332e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { return; } 342e5b6d6dSopenharmony_ci for (int i = 0; entriesArray.getValue(i, value); i++) { 352e5b6d6dSopenharmony_ci ResourceArray pluralFormsArray = value.getArray(status); 362e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { return; } 372e5b6d6dSopenharmony_ci if (pluralFormsArray.getSize() != 3) { 382e5b6d6dSopenharmony_ci status = U_RESOURCE_TYPE_MISMATCH; 392e5b6d6dSopenharmony_ci return; 402e5b6d6dSopenharmony_ci } 412e5b6d6dSopenharmony_ci pluralFormsArray.getValue(0, value); 422e5b6d6dSopenharmony_ci StandardPlural::Form first = StandardPlural::fromString(value.getUnicodeString(status), status); 432e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { return; } 442e5b6d6dSopenharmony_ci pluralFormsArray.getValue(1, value); 452e5b6d6dSopenharmony_ci StandardPlural::Form second = StandardPlural::fromString(value.getUnicodeString(status), status); 462e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { return; } 472e5b6d6dSopenharmony_ci pluralFormsArray.getValue(2, value); 482e5b6d6dSopenharmony_ci StandardPlural::Form result = StandardPlural::fromString(value.getUnicodeString(status), status); 492e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { return; } 502e5b6d6dSopenharmony_ci fOutput.addPluralRange(first, second, result); 512e5b6d6dSopenharmony_ci } 522e5b6d6dSopenharmony_ci } 532e5b6d6dSopenharmony_ci 542e5b6d6dSopenharmony_ci private: 552e5b6d6dSopenharmony_ci StandardPluralRanges& fOutput; 562e5b6d6dSopenharmony_ci}; 572e5b6d6dSopenharmony_ci 582e5b6d6dSopenharmony_civoid getPluralRangesData(const Locale& locale, StandardPluralRanges& output, UErrorCode& status) { 592e5b6d6dSopenharmony_ci LocalUResourceBundlePointer rb(ures_openDirect(nullptr, "pluralRanges", &status)); 602e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { return; } 612e5b6d6dSopenharmony_ci 622e5b6d6dSopenharmony_ci CharString dataPath; 632e5b6d6dSopenharmony_ci dataPath.append("locales/", -1, status); 642e5b6d6dSopenharmony_ci dataPath.append(locale.getLanguage(), -1, status); 652e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { return; } 662e5b6d6dSopenharmony_ci int32_t setLen; 672e5b6d6dSopenharmony_ci // Not all languages are covered: fail gracefully 682e5b6d6dSopenharmony_ci UErrorCode internalStatus = U_ZERO_ERROR; 692e5b6d6dSopenharmony_ci const UChar* set = ures_getStringByKeyWithFallback(rb.getAlias(), dataPath.data(), &setLen, &internalStatus); 702e5b6d6dSopenharmony_ci if (U_FAILURE(internalStatus)) { return; } 712e5b6d6dSopenharmony_ci 722e5b6d6dSopenharmony_ci dataPath.clear(); 732e5b6d6dSopenharmony_ci dataPath.append("rules/", -1, status); 742e5b6d6dSopenharmony_ci dataPath.appendInvariantChars(set, setLen, status); 752e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { return; } 762e5b6d6dSopenharmony_ci PluralRangesDataSink sink(output); 772e5b6d6dSopenharmony_ci ures_getAllItemsWithFallback(rb.getAlias(), dataPath.data(), sink, status); 782e5b6d6dSopenharmony_ci} 792e5b6d6dSopenharmony_ci 802e5b6d6dSopenharmony_ci} // namespace 812e5b6d6dSopenharmony_ci 822e5b6d6dSopenharmony_ci 832e5b6d6dSopenharmony_ciStandardPluralRanges 842e5b6d6dSopenharmony_ciStandardPluralRanges::forLocale(const Locale& locale, UErrorCode& status) { 852e5b6d6dSopenharmony_ci StandardPluralRanges result; 862e5b6d6dSopenharmony_ci getPluralRangesData(locale, result, status); 872e5b6d6dSopenharmony_ci return result; 882e5b6d6dSopenharmony_ci} 892e5b6d6dSopenharmony_ci 902e5b6d6dSopenharmony_ciStandardPluralRanges 912e5b6d6dSopenharmony_ciStandardPluralRanges::copy(UErrorCode& status) const { 922e5b6d6dSopenharmony_ci StandardPluralRanges result; 932e5b6d6dSopenharmony_ci if (fTriplesLen > result.fTriples.getCapacity()) { 942e5b6d6dSopenharmony_ci if (result.fTriples.resize(fTriplesLen) == nullptr) { 952e5b6d6dSopenharmony_ci status = U_MEMORY_ALLOCATION_ERROR; 962e5b6d6dSopenharmony_ci return result; 972e5b6d6dSopenharmony_ci } 982e5b6d6dSopenharmony_ci } 992e5b6d6dSopenharmony_ci uprv_memcpy(result.fTriples.getAlias(), 1002e5b6d6dSopenharmony_ci fTriples.getAlias(), 1012e5b6d6dSopenharmony_ci fTriplesLen * sizeof(fTriples[0])); 1022e5b6d6dSopenharmony_ci result.fTriplesLen = fTriplesLen; 1032e5b6d6dSopenharmony_ci return result; 1042e5b6d6dSopenharmony_ci} 1052e5b6d6dSopenharmony_ci 1062e5b6d6dSopenharmony_ciLocalPointer<StandardPluralRanges> 1072e5b6d6dSopenharmony_ciStandardPluralRanges::toPointer(UErrorCode& status) && noexcept { 1082e5b6d6dSopenharmony_ci return LocalPointer<StandardPluralRanges>(new StandardPluralRanges(std::move(*this)), status); 1092e5b6d6dSopenharmony_ci} 1102e5b6d6dSopenharmony_ci 1112e5b6d6dSopenharmony_civoid StandardPluralRanges::addPluralRange( 1122e5b6d6dSopenharmony_ci StandardPlural::Form first, 1132e5b6d6dSopenharmony_ci StandardPlural::Form second, 1142e5b6d6dSopenharmony_ci StandardPlural::Form result) { 1152e5b6d6dSopenharmony_ci U_ASSERT(fTriplesLen < fTriples.getCapacity()); 1162e5b6d6dSopenharmony_ci fTriples[fTriplesLen] = {first, second, result}; 1172e5b6d6dSopenharmony_ci fTriplesLen++; 1182e5b6d6dSopenharmony_ci} 1192e5b6d6dSopenharmony_ci 1202e5b6d6dSopenharmony_civoid StandardPluralRanges::setCapacity(int32_t length, UErrorCode& status) { 1212e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { return; } 1222e5b6d6dSopenharmony_ci if (length > fTriples.getCapacity()) { 1232e5b6d6dSopenharmony_ci if (fTriples.resize(length, 0) == nullptr) { 1242e5b6d6dSopenharmony_ci status = U_MEMORY_ALLOCATION_ERROR; 1252e5b6d6dSopenharmony_ci } 1262e5b6d6dSopenharmony_ci } 1272e5b6d6dSopenharmony_ci} 1282e5b6d6dSopenharmony_ci 1292e5b6d6dSopenharmony_ciStandardPlural::Form 1302e5b6d6dSopenharmony_ciStandardPluralRanges::resolve(StandardPlural::Form first, StandardPlural::Form second) const { 1312e5b6d6dSopenharmony_ci for (int32_t i=0; i<fTriplesLen; i++) { 1322e5b6d6dSopenharmony_ci const auto& triple = fTriples[i]; 1332e5b6d6dSopenharmony_ci if (triple.first == first && triple.second == second) { 1342e5b6d6dSopenharmony_ci return triple.result; 1352e5b6d6dSopenharmony_ci } 1362e5b6d6dSopenharmony_ci } 1372e5b6d6dSopenharmony_ci // Default fallback 1382e5b6d6dSopenharmony_ci return StandardPlural::OTHER; 1392e5b6d6dSopenharmony_ci} 1402e5b6d6dSopenharmony_ci 1412e5b6d6dSopenharmony_ci 1422e5b6d6dSopenharmony_ciU_NAMESPACE_END 1432e5b6d6dSopenharmony_ci 1442e5b6d6dSopenharmony_ci#endif /* #if !UCONFIG_NO_FORMATTING */ 145