summaryrefslogtreecommitdiff
path: root/deps/node/deps/icu-small/source/i18n/number_formatimpl.cpp
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2019-08-13 12:29:07 +0200
committerFlorian Dold <florian.dold@gmail.com>2019-08-13 12:29:22 +0200
commitda736d8259331a8ef13bf4bbb10bbb8a5c0e5299 (patch)
tree4d849133b1c9a9c7067e96ff7dd8faa1d927e0bb /deps/node/deps/icu-small/source/i18n/number_formatimpl.cpp
parentda228cf9d71b747f1824e85127039e5afc7effd8 (diff)
downloadakono-da736d8259331a8ef13bf4bbb10bbb8a5c0e5299.tar.gz
akono-da736d8259331a8ef13bf4bbb10bbb8a5c0e5299.tar.bz2
akono-da736d8259331a8ef13bf4bbb10bbb8a5c0e5299.zip
remove node/v8 from source tree
Diffstat (limited to 'deps/node/deps/icu-small/source/i18n/number_formatimpl.cpp')
-rw-r--r--deps/node/deps/icu-small/source/i18n/number_formatimpl.cpp523
1 files changed, 0 insertions, 523 deletions
diff --git a/deps/node/deps/icu-small/source/i18n/number_formatimpl.cpp b/deps/node/deps/icu-small/source/i18n/number_formatimpl.cpp
deleted file mode 100644
index 60c18ee2..00000000
--- a/deps/node/deps/icu-small/source/i18n/number_formatimpl.cpp
+++ /dev/null
@@ -1,523 +0,0 @@
-// © 2017 and later: Unicode, Inc. and others.
-// License & terms of use: http://www.unicode.org/copyright.html
-
-#include "unicode/utypes.h"
-
-#if !UCONFIG_NO_FORMATTING
-
-#include "cstring.h"
-#include "unicode/ures.h"
-#include "uresimp.h"
-#include "charstr.h"
-#include "number_formatimpl.h"
-#include "unicode/numfmt.h"
-#include "number_patternstring.h"
-#include "number_utils.h"
-#include "unicode/numberformatter.h"
-#include "unicode/dcfmtsym.h"
-#include "number_scientific.h"
-#include "number_compact.h"
-#include "uresimp.h"
-#include "ureslocs.h"
-
-using namespace icu;
-using namespace icu::number;
-using namespace icu::number::impl;
-
-namespace {
-
-struct CurrencyFormatInfoResult {
- bool exists;
- const char16_t* pattern;
- const char16_t* decimalSeparator;
- const char16_t* groupingSeparator;
-};
-
-CurrencyFormatInfoResult
-getCurrencyFormatInfo(const Locale& locale, const char* isoCode, UErrorCode& status) {
- // TODO: Load this data in a centralized location like ICU4J?
- // TODO: Move this into the CurrencySymbols class?
- // TODO: Parts of this same data are loaded in dcfmtsym.cpp; should clean up.
- CurrencyFormatInfoResult result = {false, nullptr, nullptr, nullptr};
- if (U_FAILURE(status)) { return result; }
- CharString key;
- key.append("Currencies/", status);
- key.append(isoCode, status);
- UErrorCode localStatus = status;
- LocalUResourceBundlePointer bundle(ures_open(U_ICUDATA_CURR, locale.getName(), &localStatus));
- ures_getByKeyWithFallback(bundle.getAlias(), key.data(), bundle.getAlias(), &localStatus);
- if (U_SUCCESS(localStatus) &&
- ures_getSize(bundle.getAlias()) > 2) { // the length is 3 if more data is present
- ures_getByIndex(bundle.getAlias(), 2, bundle.getAlias(), &localStatus);
- int32_t dummy;
- result.exists = true;
- result.pattern = ures_getStringByIndex(bundle.getAlias(), 0, &dummy, &localStatus);
- result.decimalSeparator = ures_getStringByIndex(bundle.getAlias(), 1, &dummy, &localStatus);
- result.groupingSeparator = ures_getStringByIndex(bundle.getAlias(), 2, &dummy, &localStatus);
- status = localStatus;
- } else if (localStatus != U_MISSING_RESOURCE_ERROR) {
- status = localStatus;
- }
- return result;
-}
-
-} // namespace
-
-
-MicroPropsGenerator::~MicroPropsGenerator() = default;
-
-
-NumberFormatterImpl::NumberFormatterImpl(const MacroProps& macros, UErrorCode& status)
- : NumberFormatterImpl(macros, true, status) {
-}
-
-int32_t NumberFormatterImpl::formatStatic(const MacroProps& macros, DecimalQuantity& inValue,
- NumberStringBuilder& outString, UErrorCode& status) {
- NumberFormatterImpl impl(macros, false, status);
- MicroProps& micros = impl.preProcessUnsafe(inValue, status);
- if (U_FAILURE(status)) { return 0; }
- int32_t length = writeNumber(micros, inValue, outString, 0, status);
- length += writeAffixes(micros, outString, 0, length, status);
- return length;
-}
-
-int32_t NumberFormatterImpl::getPrefixSuffixStatic(const MacroProps& macros, int8_t signum,
- StandardPlural::Form plural,
- NumberStringBuilder& outString, UErrorCode& status) {
- NumberFormatterImpl impl(macros, false, status);
- return impl.getPrefixSuffixUnsafe(signum, plural, outString, status);
-}
-
-// NOTE: C++ SPECIFIC DIFFERENCE FROM JAVA:
-// The "safe" apply method uses a new MicroProps. In the MicroPropsGenerator, fMicros is copied into the new instance.
-// The "unsafe" method simply re-uses fMicros, eliminating the extra copy operation.
-// See MicroProps::processQuantity() for details.
-
-int32_t NumberFormatterImpl::format(DecimalQuantity& inValue, NumberStringBuilder& outString,
- UErrorCode& status) const {
- MicroProps micros;
- preProcess(inValue, micros, status);
- if (U_FAILURE(status)) { return 0; }
- int32_t length = writeNumber(micros, inValue, outString, 0, status);
- length += writeAffixes(micros, outString, 0, length, status);
- return length;
-}
-
-void NumberFormatterImpl::preProcess(DecimalQuantity& inValue, MicroProps& microsOut,
- UErrorCode& status) const {
- if (U_FAILURE(status)) { return; }
- if (fMicroPropsGenerator == nullptr) {
- status = U_INTERNAL_PROGRAM_ERROR;
- return;
- }
- fMicroPropsGenerator->processQuantity(inValue, microsOut, status);
- microsOut.rounder.apply(inValue, status);
- microsOut.integerWidth.apply(inValue, status);
-}
-
-MicroProps& NumberFormatterImpl::preProcessUnsafe(DecimalQuantity& inValue, UErrorCode& status) {
- if (U_FAILURE(status)) {
- return fMicros; // must always return a value
- }
- if (fMicroPropsGenerator == nullptr) {
- status = U_INTERNAL_PROGRAM_ERROR;
- return fMicros; // must always return a value
- }
- fMicroPropsGenerator->processQuantity(inValue, fMicros, status);
- fMicros.rounder.apply(inValue, status);
- fMicros.integerWidth.apply(inValue, status);
- return fMicros;
-}
-
-int32_t NumberFormatterImpl::getPrefixSuffix(int8_t signum, StandardPlural::Form plural,
- NumberStringBuilder& outString, UErrorCode& status) const {
- if (U_FAILURE(status)) { return 0; }
- // #13453: DecimalFormat wants the affixes from the pattern only (modMiddle, aka pattern modifier).
- // Safe path: use fImmutablePatternModifier.
- const Modifier* modifier = fImmutablePatternModifier->getModifier(signum, plural);
- modifier->apply(outString, 0, 0, status);
- if (U_FAILURE(status)) { return 0; }
- return modifier->getPrefixLength();
-}
-
-int32_t NumberFormatterImpl::getPrefixSuffixUnsafe(int8_t signum, StandardPlural::Form plural,
- NumberStringBuilder& outString, UErrorCode& status) {
- if (U_FAILURE(status)) { return 0; }
- // #13453: DecimalFormat wants the affixes from the pattern only (modMiddle, aka pattern modifier).
- // Unsafe path: use fPatternModifier.
- fPatternModifier->setNumberProperties(signum, plural);
- fPatternModifier->apply(outString, 0, 0, status);
- if (U_FAILURE(status)) { return 0; }
- return fPatternModifier->getPrefixLength();
-}
-
-NumberFormatterImpl::NumberFormatterImpl(const MacroProps& macros, bool safe, UErrorCode& status) {
- fMicroPropsGenerator = macrosToMicroGenerator(macros, safe, status);
-}
-
-//////////
-
-const MicroPropsGenerator*
-NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, UErrorCode& status) {
- if (U_FAILURE(status)) { return nullptr; }
- const MicroPropsGenerator* chain = &fMicros;
-
- // Check that macros is error-free before continuing.
- if (macros.copyErrorTo(status)) {
- return nullptr;
- }
-
- // TODO: Accept currency symbols from DecimalFormatSymbols?
-
- // Pre-compute a few values for efficiency.
- bool isCurrency = utils::unitIsCurrency(macros.unit);
- bool isNoUnit = utils::unitIsNoUnit(macros.unit);
- bool isPercent = isNoUnit && utils::unitIsPercent(macros.unit);
- bool isPermille = isNoUnit && utils::unitIsPermille(macros.unit);
- bool isCldrUnit = !isCurrency && !isNoUnit;
- bool isAccounting =
- macros.sign == UNUM_SIGN_ACCOUNTING || macros.sign == UNUM_SIGN_ACCOUNTING_ALWAYS ||
- macros.sign == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO;
- CurrencyUnit currency(nullptr, status);
- if (isCurrency) {
- currency = CurrencyUnit(macros.unit, status); // Restore CurrencyUnit from MeasureUnit
- }
- const CurrencySymbols* currencySymbols;
- if (macros.currencySymbols != nullptr) {
- // Used by the DecimalFormat code path
- currencySymbols = macros.currencySymbols;
- } else {
- fWarehouse.fCurrencySymbols = {currency, macros.locale, status};
- currencySymbols = &fWarehouse.fCurrencySymbols;
- }
- UNumberUnitWidth unitWidth = UNUM_UNIT_WIDTH_SHORT;
- if (macros.unitWidth != UNUM_UNIT_WIDTH_COUNT) {
- unitWidth = macros.unitWidth;
- }
-
- // Select the numbering system.
- LocalPointer<const NumberingSystem> nsLocal;
- const NumberingSystem* ns;
- if (macros.symbols.isNumberingSystem()) {
- ns = macros.symbols.getNumberingSystem();
- } else {
- // TODO: Is there a way to avoid creating the NumberingSystem object?
- ns = NumberingSystem::createInstance(macros.locale, status);
- // Give ownership to the function scope.
- nsLocal.adoptInstead(ns);
- }
- const char* nsName = U_SUCCESS(status) ? ns->getName() : "latn";
-
- // Resolve the symbols. Do this here because currency may need to customize them.
- if (macros.symbols.isDecimalFormatSymbols()) {
- fMicros.symbols = macros.symbols.getDecimalFormatSymbols();
- } else {
- fMicros.symbols = new DecimalFormatSymbols(macros.locale, *ns, status);
- // Give ownership to the NumberFormatterImpl.
- fSymbols.adoptInstead(fMicros.symbols);
- }
-
- // Load and parse the pattern string. It is used for grouping sizes and affixes only.
- // If we are formatting currency, check for a currency-specific pattern.
- const char16_t* pattern = nullptr;
- if (isCurrency) {
- CurrencyFormatInfoResult info = getCurrencyFormatInfo(
- macros.locale, currency.getSubtype(), status);
- if (info.exists) {
- pattern = info.pattern;
- // It's clunky to clone an object here, but this code is not frequently executed.
- auto* symbols = new DecimalFormatSymbols(*fMicros.symbols);
- fMicros.symbols = symbols;
- fSymbols.adoptInstead(symbols);
- symbols->setSymbol(
- DecimalFormatSymbols::ENumberFormatSymbol::kMonetarySeparatorSymbol,
- UnicodeString(info.decimalSeparator),
- FALSE);
- symbols->setSymbol(
- DecimalFormatSymbols::ENumberFormatSymbol::kMonetaryGroupingSeparatorSymbol,
- UnicodeString(info.groupingSeparator),
- FALSE);
- }
- }
- if (pattern == nullptr) {
- CldrPatternStyle patternStyle;
- if (isPercent || isPermille) {
- patternStyle = CLDR_PATTERN_STYLE_PERCENT;
- } else if (!isCurrency || unitWidth == UNUM_UNIT_WIDTH_FULL_NAME) {
- patternStyle = CLDR_PATTERN_STYLE_DECIMAL;
- } else if (isAccounting) {
- // NOTE: Although ACCOUNTING and ACCOUNTING_ALWAYS are only supported in currencies right now,
- // the API contract allows us to add support to other units in the future.
- patternStyle = CLDR_PATTERN_STYLE_ACCOUNTING;
- } else {
- patternStyle = CLDR_PATTERN_STYLE_CURRENCY;
- }
- pattern = utils::getPatternForStyle(macros.locale, nsName, patternStyle, status);
- }
- auto patternInfo = new ParsedPatternInfo();
- fPatternInfo.adoptInstead(patternInfo);
- PatternParser::parseToPatternInfo(UnicodeString(pattern), *patternInfo, status);
-
- /////////////////////////////////////////////////////////////////////////////////////
- /// START POPULATING THE DEFAULT MICROPROPS AND BUILDING THE MICROPROPS GENERATOR ///
- /////////////////////////////////////////////////////////////////////////////////////
-
- // Multiplier
- if (macros.scale.isValid()) {
- fMicros.helpers.multiplier.setAndChain(macros.scale, chain);
- chain = &fMicros.helpers.multiplier;
- }
-
- // Rounding strategy
- Precision precision;
- if (!macros.precision.isBogus()) {
- precision = macros.precision;
- } else if (macros.notation.fType == Notation::NTN_COMPACT) {
- precision = Precision::integer().withMinDigits(2);
- } else if (isCurrency) {
- precision = Precision::currency(UCURR_USAGE_STANDARD);
- } else {
- precision = Precision::maxFraction(6);
- }
- UNumberFormatRoundingMode roundingMode;
- if (macros.roundingMode != kDefaultMode) {
- roundingMode = macros.roundingMode;
- } else {
- // Temporary until ICU 64
- roundingMode = precision.fRoundingMode;
- }
- fMicros.rounder = {precision, roundingMode, currency, status};
-
- // Grouping strategy
- if (!macros.grouper.isBogus()) {
- fMicros.grouping = macros.grouper;
- } else if (macros.notation.fType == Notation::NTN_COMPACT) {
- // Compact notation uses minGrouping by default since ICU 59
- fMicros.grouping = Grouper::forStrategy(UNUM_GROUPING_MIN2);
- } else {
- fMicros.grouping = Grouper::forStrategy(UNUM_GROUPING_AUTO);
- }
- fMicros.grouping.setLocaleData(*fPatternInfo, macros.locale);
-
- // Padding strategy
- if (!macros.padder.isBogus()) {
- fMicros.padding = macros.padder;
- } else {
- fMicros.padding = Padder::none();
- }
-
- // Integer width
- if (!macros.integerWidth.isBogus()) {
- fMicros.integerWidth = macros.integerWidth;
- } else {
- fMicros.integerWidth = IntegerWidth::standard();
- }
-
- // Sign display
- if (macros.sign != UNUM_SIGN_COUNT) {
- fMicros.sign = macros.sign;
- } else {
- fMicros.sign = UNUM_SIGN_AUTO;
- }
-
- // Decimal mark display
- if (macros.decimal != UNUM_DECIMAL_SEPARATOR_COUNT) {
- fMicros.decimal = macros.decimal;
- } else {
- fMicros.decimal = UNUM_DECIMAL_SEPARATOR_AUTO;
- }
-
- // Use monetary separator symbols
- fMicros.useCurrency = isCurrency;
-
- // Inner modifier (scientific notation)
- if (macros.notation.fType == Notation::NTN_SCIENTIFIC) {
- fScientificHandler.adoptInstead(new ScientificHandler(&macros.notation, fMicros.symbols, chain));
- chain = fScientificHandler.getAlias();
- } else {
- // No inner modifier required
- fMicros.modInner = &fMicros.helpers.emptyStrongModifier;
- }
-
- // Middle modifier (patterns, positive/negative, currency symbols, percent)
- auto patternModifier = new MutablePatternModifier(false);
- fPatternModifier.adoptInstead(patternModifier);
- patternModifier->setPatternInfo(
- macros.affixProvider != nullptr ? macros.affixProvider
- : static_cast<const AffixPatternProvider*>(fPatternInfo.getAlias()));
- patternModifier->setPatternAttributes(fMicros.sign, isPermille);
- if (patternModifier->needsPlurals()) {
- patternModifier->setSymbols(
- fMicros.symbols,
- currencySymbols,
- unitWidth,
- resolvePluralRules(macros.rules, macros.locale, status));
- } else {
- patternModifier->setSymbols(fMicros.symbols, currencySymbols, unitWidth, nullptr);
- }
- if (safe) {
- fImmutablePatternModifier.adoptInstead(patternModifier->createImmutableAndChain(chain, status));
- chain = fImmutablePatternModifier.getAlias();
- } else {
- patternModifier->addToChain(chain);
- chain = patternModifier;
- }
-
- // Outer modifier (CLDR units and currency long names)
- if (isCldrUnit) {
- fLongNameHandler.adoptInstead(
- LongNameHandler::forMeasureUnit(
- macros.locale,
- macros.unit,
- macros.perUnit,
- unitWidth,
- resolvePluralRules(macros.rules, macros.locale, status),
- chain,
- status));
- chain = fLongNameHandler.getAlias();
- } else if (isCurrency && unitWidth == UNUM_UNIT_WIDTH_FULL_NAME) {
- fLongNameHandler.adoptInstead(
- LongNameHandler::forCurrencyLongNames(
- macros.locale,
- currency,
- resolvePluralRules(macros.rules, macros.locale, status),
- chain,
- status));
- chain = fLongNameHandler.getAlias();
- } else {
- // No outer modifier required
- fMicros.modOuter = &fMicros.helpers.emptyWeakModifier;
- }
-
- // Compact notation
- // NOTE: Compact notation can (but might not) override the middle modifier and rounding.
- // It therefore needs to go at the end of the chain.
- if (macros.notation.fType == Notation::NTN_COMPACT) {
- CompactType compactType = (isCurrency && unitWidth != UNUM_UNIT_WIDTH_FULL_NAME)
- ? CompactType::TYPE_CURRENCY : CompactType::TYPE_DECIMAL;
- fCompactHandler.adoptInstead(
- new CompactHandler(
- macros.notation.fUnion.compactStyle,
- macros.locale,
- nsName,
- compactType,
- resolvePluralRules(macros.rules, macros.locale, status),
- safe ? patternModifier : nullptr,
- chain,
- status));
- chain = fCompactHandler.getAlias();
- }
-
- return chain;
-}
-
-const PluralRules*
-NumberFormatterImpl::resolvePluralRules(const PluralRules* rulesPtr, const Locale& locale,
- UErrorCode& status) {
- if (rulesPtr != nullptr) {
- return rulesPtr;
- }
- // Lazily create PluralRules
- if (fRules.isNull()) {
- fRules.adoptInstead(PluralRules::forLocale(locale, status));
- }
- return fRules.getAlias();
-}
-
-int32_t NumberFormatterImpl::writeAffixes(const MicroProps& micros, NumberStringBuilder& string,
- int32_t start, int32_t end, UErrorCode& status) {
- // Always apply the inner modifier (which is "strong").
- int32_t length = micros.modInner->apply(string, start, end, status);
- if (micros.padding.isValid()) {
- length += micros.padding
- .padAndApply(*micros.modMiddle, *micros.modOuter, string, start, length + end, status);
- } else {
- length += micros.modMiddle->apply(string, start, length + end, status);
- length += micros.modOuter->apply(string, start, length + end, status);
- }
- return length;
-}
-
-int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuantity& quantity,
- NumberStringBuilder& string, int32_t index,
- UErrorCode& status) {
- int32_t length = 0;
- if (quantity.isInfinite()) {
- length += string.insert(
- length + index,
- micros.symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kInfinitySymbol),
- UNUM_INTEGER_FIELD,
- status);
-
- } else if (quantity.isNaN()) {
- length += string.insert(
- length + index,
- micros.symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kNaNSymbol),
- UNUM_INTEGER_FIELD,
- status);
-
- } else {
- // Add the integer digits
- length += writeIntegerDigits(micros, quantity, string, length + index, status);
-
- // Add the decimal point
- if (quantity.getLowerDisplayMagnitude() < 0 || micros.decimal == UNUM_DECIMAL_SEPARATOR_ALWAYS) {
- length += string.insert(
- length + index,
- micros.useCurrency ? micros.symbols->getSymbol(
- DecimalFormatSymbols::ENumberFormatSymbol::kMonetarySeparatorSymbol) : micros
- .symbols
- ->getSymbol(
- DecimalFormatSymbols::ENumberFormatSymbol::kDecimalSeparatorSymbol),
- UNUM_DECIMAL_SEPARATOR_FIELD,
- status);
- }
-
- // Add the fraction digits
- length += writeFractionDigits(micros, quantity, string, length + index, status);
- }
-
- return length;
-}
-
-int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps& micros, DecimalQuantity& quantity,
- NumberStringBuilder& string, int32_t index,
- UErrorCode& status) {
- int length = 0;
- int integerCount = quantity.getUpperDisplayMagnitude() + 1;
- for (int i = 0; i < integerCount; i++) {
- // Add grouping separator
- if (micros.grouping.groupAtPosition(i, quantity)) {
- length += string.insert(
- index,
- micros.useCurrency ? micros.symbols->getSymbol(
- DecimalFormatSymbols::ENumberFormatSymbol::kMonetaryGroupingSeparatorSymbol)
- : micros.symbols->getSymbol(
- DecimalFormatSymbols::ENumberFormatSymbol::kGroupingSeparatorSymbol),
- UNUM_GROUPING_SEPARATOR_FIELD,
- status);
- }
-
- // Get and append the next digit value
- int8_t nextDigit = quantity.getDigit(i);
- length += utils::insertDigitFromSymbols(
- string, index, nextDigit, *micros.symbols, UNUM_INTEGER_FIELD, status);
- }
- return length;
-}
-
-int32_t NumberFormatterImpl::writeFractionDigits(const MicroProps& micros, DecimalQuantity& quantity,
- NumberStringBuilder& string, int32_t index,
- UErrorCode& status) {
- int length = 0;
- int fractionCount = -quantity.getLowerDisplayMagnitude();
- for (int i = 0; i < fractionCount; i++) {
- // Get and append the next digit value
- int8_t nextDigit = quantity.getDigit(-i - 1);
- length += utils::insertDigitFromSymbols(
- string, length + index, nextDigit, *micros.symbols, UNUM_FRACTION_FIELD, status);
- }
- return length;
-}
-
-#endif /* #if !UCONFIG_NO_FORMATTING */