X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/f3c0d7a59d99c2a94c6b8822291f0e42be3773c9..refs/heads/master:/icuSources/i18n/msgfmt.cpp diff --git a/icuSources/i18n/msgfmt.cpp b/icuSources/i18n/msgfmt.cpp index 94a02861..3ca368ef 100644 --- a/icuSources/i18n/msgfmt.cpp +++ b/icuSources/i18n/msgfmt.cpp @@ -31,6 +31,7 @@ #include "unicode/decimfmt.h" #include "unicode/localpointer.h" #include "unicode/msgfmt.h" +#include "unicode/numberformatter.h" #include "unicode/plurfmt.h" #include "unicode/rbnf.h" #include "unicode/selfmt.h" @@ -48,7 +49,7 @@ #include "ustrfmt.h" #include "util.h" #include "uvector.h" -#include "visibledigits.h" +#include "number_decimalquantity.h" // ***************************************************************************** // class MessageFormat @@ -435,7 +436,7 @@ MessageFormat::operator==(const Format& rhs) const // ------------------------------------- // Creates a copy of this MessageFormat, the caller owns the copy. -Format* +MessageFormat* MessageFormat::clone() const { return new MessageFormat(*this); @@ -809,26 +810,31 @@ MessageFormat::getFormats(int32_t& cnt) const // method on this object. We construct and resize an array // on demand that contains aliases to the subformats[i].format // pointers. + + // Get total required capacity first (it's refreshed on each call). + int32_t totalCapacity = 0; + for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0; ++totalCapacity) {} + MessageFormat* t = const_cast (this); cnt = 0; - if (formatAliases == NULL) { - t->formatAliasesCapacity = (argTypeCount<10) ? 10 : argTypeCount; + if (formatAliases == nullptr) { + t->formatAliasesCapacity = totalCapacity; Format** a = (Format**) uprv_malloc(sizeof(Format*) * formatAliasesCapacity); - if (a == NULL) { + if (a == nullptr) { t->formatAliasesCapacity = 0; - return NULL; + return nullptr; } t->formatAliases = a; - } else if (argTypeCount > formatAliasesCapacity) { + } else if (totalCapacity > formatAliasesCapacity) { Format** a = (Format**) - uprv_realloc(formatAliases, sizeof(Format*) * argTypeCount); - if (a == NULL) { + uprv_realloc(formatAliases, sizeof(Format*) * totalCapacity); + if (a == nullptr) { t->formatAliasesCapacity = 0; - return NULL; + return nullptr; } t->formatAliases = a; - t->formatAliasesCapacity = argTypeCount; + t->formatAliasesCapacity = totalCapacity; } for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { @@ -1077,7 +1083,7 @@ void MessageFormat::format(int32_t msgStart, const void *plNumber, // that formats the number without subtracting the offset. appendTo.formatAndAppend(pluralNumber.formatter, *arg, success); } - } else if ((formatter = getCachedFormatter(i -2))) { + } else if ((formatter = getCachedFormatter(i -2)) != 0) { // Handles all ArgType.SIMPLE, and formatters from setFormat() and its siblings. if (dynamic_cast(formatter) || dynamic_cast(formatter) || @@ -1672,7 +1678,6 @@ void MessageFormat::cacheExplicitFormats(UErrorCode& status) { } } - Format* MessageFormat::createAppropriateFormat(UnicodeString& type, UnicodeString& style, Formattable::Type& formattableType, UParseError& parseError, UErrorCode& ec) { @@ -1682,6 +1687,7 @@ Format* MessageFormat::createAppropriateFormat(UnicodeString& type, UnicodeStrin Format* fmt = NULL; int32_t typeID, styleID; DateFormat::EStyle date_style; + int32_t firstNonSpace; switch (typeID = findKeyword(type, TYPE_IDS)) { case 0: // number @@ -1700,12 +1706,20 @@ Format* MessageFormat::createAppropriateFormat(UnicodeString& type, UnicodeStrin formattableType = Formattable::kLong; fmt = createIntegerFormat(fLocale, ec); break; - default: // pattern - fmt = NumberFormat::createInstance(fLocale, ec); - if (fmt) { - DecimalFormat* decfmt = dynamic_cast(fmt); - if (decfmt != NULL) { - decfmt->applyPattern(style,parseError,ec); + default: // pattern or skeleton + firstNonSpace = PatternProps::skipWhiteSpace(style, 0); + if (style.compare(firstNonSpace, 2, u"::", 0, 2) == 0) { + // Skeleton + UnicodeString skeleton = style.tempSubString(firstNonSpace + 2); + fmt = number::NumberFormatter::forSkeleton(skeleton, ec).locale(fLocale).toFormat(ec); + } else { + // Pattern + fmt = NumberFormat::createInstance(fLocale, ec); + if (fmt) { + auto* decfmt = dynamic_cast(fmt); + if (decfmt != nullptr) { + decfmt->applyPattern(style, parseError, ec); + } } } break; @@ -1715,19 +1729,27 @@ Format* MessageFormat::createAppropriateFormat(UnicodeString& type, UnicodeStrin case 1: // date case 2: // time formattableType = Formattable::kDate; - styleID = findKeyword(style, DATE_STYLE_IDS); - date_style = (styleID >= 0) ? DATE_STYLES[styleID] : DateFormat::kDefault; - - if (typeID == 1) { - fmt = DateFormat::createDateInstance(date_style, fLocale); + firstNonSpace = PatternProps::skipWhiteSpace(style, 0); + if (style.compare(firstNonSpace, 2, u"::", 0, 2) == 0) { + // Skeleton + UnicodeString skeleton = style.tempSubString(firstNonSpace + 2); + fmt = DateFormat::createInstanceForSkeleton(skeleton, fLocale, ec); } else { - fmt = DateFormat::createTimeInstance(date_style, fLocale); - } + // Pattern + styleID = findKeyword(style, DATE_STYLE_IDS); + date_style = (styleID >= 0) ? DATE_STYLES[styleID] : DateFormat::kDefault; - if (styleID < 0 && fmt != NULL) { - SimpleDateFormat* sdtfmt = dynamic_cast(fmt); - if (sdtfmt != NULL) { - sdtfmt->applyPattern(style); + if (typeID == 1) { + fmt = DateFormat::createDateInstance(date_style, fLocale); + } else { + fmt = DateFormat::createTimeInstance(date_style, fLocale); + } + + if (styleID < 0 && fmt != NULL) { + SimpleDateFormat* sdtfmt = dynamic_cast(fmt); + if (sdtfmt != NULL) { + sdtfmt->applyPattern(style); + } } } break; @@ -1851,7 +1873,7 @@ UBool MessageFormat::DummyFormat::operator==(const Format&) const { return TRUE; } -Format* MessageFormat::DummyFormat::clone() const { +MessageFormat::DummyFormat* MessageFormat::DummyFormat::clone() const { return new DummyFormat(); } @@ -1954,16 +1976,19 @@ UnicodeString MessageFormat::PluralSelectorProvider::select(void *ctx, double nu context.formatter = msgFormat.getDefaultNumberFormat(ec); context.forReplaceNumber = TRUE; } - U_ASSERT(context.number.getDouble(ec) == number); // argument number minus the offset + if (context.number.getDouble(ec) != number) { + ec = U_INTERNAL_PROGRAM_ERROR; + return UnicodeString(FALSE, OTHER_STRING, 5); + } context.formatter->format(context.number, context.numberString, ec); - const DecimalFormat *decFmt = dynamic_cast(context.formatter); + auto* decFmt = dynamic_cast(context.formatter); if(decFmt != NULL) { - VisibleDigitsWithExponent digits; - decFmt->initVisibleDigitsWithExponent(context.number, digits, ec); + number::impl::DecimalQuantity dq; + decFmt->formatToDecimalQuantity(context.number, dq, ec); if (U_FAILURE(ec)) { return UnicodeString(FALSE, OTHER_STRING, 5); } - return rules->select(digits); + return rules->select(dq); } else { return rules->select(number); }