summaryrefslogtreecommitdiffstats
path: root/intl/icu/source/i18n/number_simple.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'intl/icu/source/i18n/number_simple.cpp')
-rw-r--r--intl/icu/source/i18n/number_simple.cpp255
1 files changed, 255 insertions, 0 deletions
diff --git a/intl/icu/source/i18n/number_simple.cpp b/intl/icu/source/i18n/number_simple.cpp
new file mode 100644
index 0000000000..a2af6be42d
--- /dev/null
+++ b/intl/icu/source/i18n/number_simple.cpp
@@ -0,0 +1,255 @@
+// © 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 "unicode/numberformatter.h"
+#include "unicode/simplenumberformatter.h"
+#include "number_formatimpl.h"
+#include "number_utils.h"
+#include "number_patternmodifier.h"
+#include "number_utypes.h"
+
+using namespace icu;
+using namespace icu::number;
+using namespace icu::number::impl;
+
+
+SimpleNumber
+SimpleNumber::forInt64(int64_t value, UErrorCode& status) {
+ if (U_FAILURE(status)) {
+ return SimpleNumber();
+ }
+ auto results = new UFormattedNumberData();
+ if (results == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return SimpleNumber();
+ }
+ results->quantity.setToLong(value);
+ return SimpleNumber(results, status);
+}
+
+SimpleNumber::SimpleNumber(UFormattedNumberData* data, UErrorCode& status) : fData(data) {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (fData == nullptr) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ if (fData->quantity.isNegative()) {
+ fSign = UNUM_SIMPLE_NUMBER_MINUS_SIGN;
+ } else {
+ fSign = UNUM_SIMPLE_NUMBER_NO_SIGN;
+ }
+}
+
+void SimpleNumber::cleanup() {
+ delete fData;
+ fData = nullptr;
+}
+
+void SimpleNumber::multiplyByPowerOfTen(int32_t power, UErrorCode& status) {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (fData == nullptr) {
+ status = U_INVALID_STATE_ERROR;
+ return;
+ }
+ fData->quantity.adjustMagnitude(power);
+}
+
+void SimpleNumber::roundTo(int32_t position, UNumberFormatRoundingMode roundingMode, UErrorCode& status) {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (fData == nullptr) {
+ status = U_INVALID_STATE_ERROR;
+ return;
+ }
+ fData->quantity.roundToMagnitude(position, roundingMode, status);
+}
+
+void SimpleNumber::setMinimumIntegerDigits(uint32_t position, UErrorCode& status) {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (fData == nullptr) {
+ status = U_INVALID_STATE_ERROR;
+ return;
+ }
+ fData->quantity.setMinInteger(position);
+}
+
+void SimpleNumber::setMinimumFractionDigits(uint32_t position, UErrorCode& status) {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (fData == nullptr) {
+ status = U_INVALID_STATE_ERROR;
+ return;
+ }
+ fData->quantity.setMinFraction(position);
+}
+
+void SimpleNumber::truncateStart(uint32_t position, UErrorCode& status) {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (fData == nullptr) {
+ status = U_INVALID_STATE_ERROR;
+ return;
+ }
+ fData->quantity.applyMaxInteger(position);
+}
+
+void SimpleNumber::setSign(USimpleNumberSign sign, UErrorCode& status) {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (fData == nullptr) {
+ status = U_INVALID_STATE_ERROR;
+ return;
+ }
+ fSign = sign;
+}
+
+
+void SimpleNumberFormatter::cleanup() {
+ delete fOwnedSymbols;
+ delete fMicros;
+ delete fPatternModifier;
+ fOwnedSymbols = nullptr;
+ fMicros = nullptr;
+ fPatternModifier = nullptr;
+}
+
+SimpleNumberFormatter SimpleNumberFormatter::forLocale(const icu::Locale &locale, UErrorCode &status) {
+ return SimpleNumberFormatter::forLocaleAndGroupingStrategy(locale, UNUM_GROUPING_AUTO, status);
+}
+
+SimpleNumberFormatter SimpleNumberFormatter::forLocaleAndGroupingStrategy(
+ const icu::Locale &locale,
+ UNumberGroupingStrategy groupingStrategy,
+ UErrorCode &status) {
+ SimpleNumberFormatter retval;
+ retval.fOwnedSymbols = new DecimalFormatSymbols(locale, status);
+ if (U_FAILURE(status)) {
+ return retval;
+ }
+ if (retval.fOwnedSymbols == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return retval;
+ }
+ retval.initialize(locale, *retval.fOwnedSymbols, groupingStrategy, status);
+ return retval;
+}
+
+
+SimpleNumberFormatter SimpleNumberFormatter::forLocaleAndSymbolsAndGroupingStrategy(
+ const icu::Locale &locale,
+ const DecimalFormatSymbols &symbols,
+ UNumberGroupingStrategy groupingStrategy,
+ UErrorCode &status) {
+ SimpleNumberFormatter retval;
+ retval.initialize(locale, symbols, groupingStrategy, status);
+ return retval;
+}
+
+
+void SimpleNumberFormatter::initialize(
+ const icu::Locale &locale,
+ const DecimalFormatSymbols &symbols,
+ UNumberGroupingStrategy groupingStrategy,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return;
+ }
+
+ fMicros = new SimpleMicroProps();
+ if (fMicros == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ fMicros->symbols = &symbols;
+
+ auto pattern = utils::getPatternForStyle(
+ locale,
+ symbols.getNumberingSystemName(),
+ CLDR_PATTERN_STYLE_DECIMAL,
+ status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+
+ ParsedPatternInfo patternInfo;
+ PatternParser::parseToPatternInfo(UnicodeString(pattern), patternInfo, status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+
+ auto grouper = Grouper::forStrategy(groupingStrategy);
+ grouper.setLocaleData(patternInfo, locale);
+ fMicros->grouping = grouper;
+
+ MutablePatternModifier patternModifier(false);
+ patternModifier.setPatternInfo(&patternInfo, kUndefinedField);
+ patternModifier.setPatternAttributes(UNUM_SIGN_EXCEPT_ZERO, false, false);
+ patternModifier.setSymbols(fMicros->symbols, {}, UNUM_UNIT_WIDTH_SHORT, nullptr, status);
+
+ fPatternModifier = new AdoptingSignumModifierStore(patternModifier.createImmutableForPlural(StandardPlural::COUNT, status));
+
+ fGroupingStrategy = groupingStrategy;
+ return;
+}
+
+FormattedNumber SimpleNumberFormatter::format(SimpleNumber value, UErrorCode &status) const {
+ formatImpl(value.fData, value.fSign, status);
+
+ // Do not save the results object if we encountered a failure.
+ if (U_SUCCESS(status)) {
+ auto temp = value.fData;
+ value.fData = nullptr;
+ return FormattedNumber(temp);
+ } else {
+ return FormattedNumber(status);
+ }
+}
+
+void SimpleNumberFormatter::formatImpl(UFormattedNumberData* data, USimpleNumberSign sign, UErrorCode &status) const {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (data == nullptr) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ if (fPatternModifier == nullptr || fMicros == nullptr) {
+ status = U_INVALID_STATE_ERROR;
+ return;
+ }
+
+ Signum signum;
+ if (sign == UNUM_SIMPLE_NUMBER_MINUS_SIGN) {
+ signum = SIGNUM_NEG;
+ } else if (sign == UNUM_SIMPLE_NUMBER_PLUS_SIGN) {
+ signum = SIGNUM_POS;
+ } else {
+ signum = SIGNUM_POS_ZERO;
+ }
+
+ const Modifier* modifier = (*fPatternModifier)[signum];
+ auto length = NumberFormatterImpl::writeNumber(
+ *fMicros,
+ data->quantity,
+ data->getStringRef(),
+ 0,
+ status);
+ length += modifier->apply(data->getStringRef(), 0, length, status);
+ data->getStringRef().writeTerminator(status);
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING */