summaryrefslogtreecommitdiffstats
path: root/intl/icu/source/i18n/number_capi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'intl/icu/source/i18n/number_capi.cpp')
-rw-r--r--intl/icu/source/i18n/number_capi.cpp430
1 files changed, 430 insertions, 0 deletions
diff --git a/intl/icu/source/i18n/number_capi.cpp b/intl/icu/source/i18n/number_capi.cpp
new file mode 100644
index 0000000000..abada9ad86
--- /dev/null
+++ b/intl/icu/source/i18n/number_capi.cpp
@@ -0,0 +1,430 @@
+// © 2018 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+// Allow implicit conversion from char16_t* to UnicodeString for this file:
+// Helpful in toString methods and elsewhere.
+#define UNISTR_FROM_STRING_EXPLICIT
+
+#include "fphdlimp.h"
+#include "number_utypes.h"
+#include "numparse_types.h"
+#include "formattedval_impl.h"
+#include "number_decnum.h"
+#include "unicode/numberformatter.h"
+#include "unicode/unumberformatter.h"
+#include "unicode/simplenumberformatter.h"
+#include "unicode/usimplenumberformatter.h"
+
+using namespace icu;
+using namespace icu::number;
+using namespace icu::number::impl;
+
+
+U_NAMESPACE_BEGIN
+namespace number {
+namespace impl {
+
+/**
+ * Implementation class for UNumberFormatter. Wraps a LocalizedNumberFormatter.
+ */
+struct UNumberFormatterData : public UMemory,
+ // Magic number as ASCII == "NFR" (NumberFormatteR)
+ public IcuCApiHelper<UNumberFormatter, UNumberFormatterData, 0x4E465200> {
+ LocalizedNumberFormatter fFormatter;
+};
+
+/**
+ * Implementation class for USimpleNumber. Wraps a SimpleNumberFormatter.
+ */
+struct USimpleNumberData : public UMemory,
+ // Magic number as ASCII == "SNM" (SimpleNuMber)
+ public IcuCApiHelper<USimpleNumber, USimpleNumberData, 0x534E4D00> {
+ SimpleNumber fNumber;
+};
+
+/**
+ * Implementation class for USimpleNumberFormatter. Wraps a SimpleNumberFormatter.
+ */
+struct USimpleNumberFormatterData : public UMemory,
+ // Magic number as ASCII == "SNF" (SimpleNumberFormatter)
+ public IcuCApiHelper<USimpleNumberFormatter, USimpleNumberFormatterData, 0x534E4600> {
+ SimpleNumberFormatter fFormatter;
+};
+
+struct UFormattedNumberImpl;
+
+// Magic number as ASCII == "FDN" (FormatteDNumber)
+typedef IcuCApiHelper<UFormattedNumber, UFormattedNumberImpl, 0x46444E00> UFormattedNumberApiHelper;
+
+struct UFormattedNumberImpl : public UFormattedValueImpl, public UFormattedNumberApiHelper {
+ UFormattedNumberImpl();
+ ~UFormattedNumberImpl();
+
+ FormattedNumber fImpl;
+ UFormattedNumberData fData;
+
+ void setTo(FormattedNumber value);
+};
+
+UFormattedNumberImpl::UFormattedNumberImpl()
+ : fImpl(&fData) {
+ fFormattedValue = &fImpl;
+}
+
+UFormattedNumberImpl::~UFormattedNumberImpl() {
+ // Disown the data from fImpl so it doesn't get deleted twice
+ fImpl.fData = nullptr;
+}
+
+void UFormattedNumberImpl::setTo(FormattedNumber value) {
+ fData = std::move(*value.fData);
+}
+
+}
+}
+U_NAMESPACE_END
+
+
+UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(
+ UFormattedNumber,
+ UFormattedNumberImpl,
+ UFormattedNumberApiHelper,
+ unumf)
+
+
+const DecimalQuantity* icu::number::impl::validateUFormattedNumberToDecimalQuantity(
+ const UFormattedNumber* uresult, UErrorCode& status) {
+ auto* result = UFormattedNumberApiHelper::validate(uresult, status);
+ if (U_FAILURE(status)) {
+ return nullptr;
+ }
+ return &result->fData.quantity;
+}
+
+
+
+U_CAPI UNumberFormatter* U_EXPORT2
+unumf_openForSkeletonAndLocale(const char16_t* skeleton, int32_t skeletonLen, const char* locale,
+ UErrorCode* ec) {
+ auto* impl = new UNumberFormatterData();
+ if (impl == nullptr) {
+ *ec = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
+ }
+ // Readonly-alias constructor (first argument is whether we are NUL-terminated)
+ UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen);
+ impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, *ec).locale(locale);
+ return impl->exportForC();
+}
+
+U_CAPI UNumberFormatter* U_EXPORT2
+unumf_openForSkeletonAndLocaleWithError(const char16_t* skeleton, int32_t skeletonLen, const char* locale,
+ UParseError* perror, UErrorCode* ec) {
+ auto* impl = new UNumberFormatterData();
+ if (impl == nullptr) {
+ *ec = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
+ }
+ // Readonly-alias constructor (first argument is whether we are NUL-terminated)
+ UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen);
+ UParseError tempParseError;
+ impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, (perror == nullptr) ? tempParseError : *perror, *ec).locale(locale);
+ return impl->exportForC();
+}
+
+U_CAPI void U_EXPORT2
+unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNumber* uresult,
+ UErrorCode* ec) {
+ const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
+ auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
+ if (U_FAILURE(*ec)) { return; }
+
+ result->fData.resetString();
+ result->fData.quantity.clear();
+ result->fData.quantity.setToLong(value);
+ formatter->fFormatter.formatImpl(&result->fData, *ec);
+}
+
+U_CAPI void U_EXPORT2
+unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedNumber* uresult,
+ UErrorCode* ec) {
+ const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
+ auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
+ if (U_FAILURE(*ec)) { return; }
+
+ result->fData.resetString();
+ result->fData.quantity.clear();
+ result->fData.quantity.setToDouble(value);
+ formatter->fFormatter.formatImpl(&result->fData, *ec);
+}
+
+U_CAPI void U_EXPORT2
+unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen,
+ UFormattedNumber* uresult, UErrorCode* ec) {
+ const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
+ auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
+ if (U_FAILURE(*ec)) { return; }
+
+ result->fData.resetString();
+ result->fData.quantity.clear();
+ result->fData.quantity.setToDecNumber({value, valueLen}, *ec);
+ if (U_FAILURE(*ec)) { return; }
+ formatter->fFormatter.formatImpl(&result->fData, *ec);
+}
+
+U_CAPI int32_t U_EXPORT2
+unumf_resultToString(const UFormattedNumber* uresult, char16_t* buffer, int32_t bufferCapacity,
+ UErrorCode* ec) {
+ const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
+ if (U_FAILURE(*ec)) { return 0; }
+
+ if (buffer == nullptr ? bufferCapacity != 0 : bufferCapacity < 0) {
+ *ec = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+
+ return result->fData.toTempString(*ec).extract(buffer, bufferCapacity, *ec);
+}
+
+U_CAPI UBool U_EXPORT2
+unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* ufpos, UErrorCode* ec) {
+ const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
+ if (U_FAILURE(*ec)) { return false; }
+
+ if (ufpos == nullptr) {
+ *ec = U_ILLEGAL_ARGUMENT_ERROR;
+ return false;
+ }
+
+ FieldPosition fp;
+ fp.setField(ufpos->field);
+ fp.setBeginIndex(ufpos->beginIndex);
+ fp.setEndIndex(ufpos->endIndex);
+ bool retval = result->fData.nextFieldPosition(fp, *ec);
+ ufpos->beginIndex = fp.getBeginIndex();
+ ufpos->endIndex = fp.getEndIndex();
+ // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
+ return retval ? true : false;
+}
+
+U_CAPI void U_EXPORT2
+unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer,
+ UErrorCode* ec) {
+ const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
+ if (U_FAILURE(*ec)) { return; }
+
+ if (ufpositer == nullptr) {
+ *ec = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+
+ auto* fpi = reinterpret_cast<FieldPositionIterator*>(ufpositer);
+ FieldPositionIteratorHandler fpih(fpi, *ec);
+ result->fData.getAllFieldPositions(fpih, *ec);
+}
+
+U_CAPI int32_t U_EXPORT2
+unumf_resultToDecimalNumber(
+ const UFormattedNumber* uresult,
+ char* dest,
+ int32_t destCapacity,
+ UErrorCode* ec) {
+ const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
+ if (U_FAILURE(*ec)) {
+ return 0;
+ }
+ DecNum decnum;
+ return result->fData.quantity
+ .toDecNum(decnum, *ec)
+ .toCharString(*ec)
+ .extract(dest, destCapacity, *ec);
+}
+
+U_CAPI void U_EXPORT2
+unumf_close(UNumberFormatter* f) {
+ UErrorCode localStatus = U_ZERO_ERROR;
+ const UNumberFormatterData* impl = UNumberFormatterData::validate(f, localStatus);
+ delete impl;
+}
+
+
+///// SIMPLE NUMBER FORMATTER /////
+
+U_CAPI USimpleNumber* U_EXPORT2
+usnum_openForInt64(int64_t value, UErrorCode* ec) {
+ auto* number = new USimpleNumberData();
+ if (number == nullptr) {
+ *ec = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
+ }
+ number->fNumber = SimpleNumber::forInt64(value, *ec);
+ return number->exportForC();
+}
+
+U_CAPI void U_EXPORT2
+usnum_setToInt64(USimpleNumber* unumber, int64_t value, UErrorCode* ec) {
+ auto* number = USimpleNumberData::validate(unumber, *ec);
+ if (U_FAILURE(*ec)) {
+ return;
+ }
+ number->fNumber = SimpleNumber::forInt64(value, *ec);
+}
+
+U_CAPI void U_EXPORT2
+usnum_multiplyByPowerOfTen(USimpleNumber* unumber, int32_t power, UErrorCode* ec) {
+ auto* number = USimpleNumberData::validate(unumber, *ec);
+ if (U_FAILURE(*ec)) {
+ return;
+ }
+ number->fNumber.multiplyByPowerOfTen(power, *ec);
+}
+
+U_CAPI void U_EXPORT2
+usnum_roundTo(USimpleNumber* unumber, int32_t position, UNumberFormatRoundingMode roundingMode, UErrorCode* ec) {
+ auto* number = USimpleNumberData::validate(unumber, *ec);
+ if (U_FAILURE(*ec)) {
+ return;
+ }
+ number->fNumber.roundTo(position, roundingMode, *ec);
+}
+
+U_CAPI void U_EXPORT2
+usnum_setMinimumIntegerDigits(USimpleNumber* unumber, int32_t minimumIntegerDigits, UErrorCode* ec) {
+ auto* number = USimpleNumberData::validate(unumber, *ec);
+ if (U_FAILURE(*ec)) {
+ return;
+ }
+ number->fNumber.setMinimumIntegerDigits(minimumIntegerDigits, *ec);
+}
+
+U_CAPI void U_EXPORT2
+usnum_setMinimumFractionDigits(USimpleNumber* unumber, int32_t minimumFractionDigits, UErrorCode* ec) {
+ auto* number = USimpleNumberData::validate(unumber, *ec);
+ if (U_FAILURE(*ec)) {
+ return;
+ }
+ number->fNumber.setMinimumFractionDigits(minimumFractionDigits, *ec);
+}
+
+U_CAPI void U_EXPORT2
+usnum_truncateStart(USimpleNumber* unumber, int32_t maximumIntegerDigits, UErrorCode* ec) {
+ auto* number = USimpleNumberData::validate(unumber, *ec);
+ if (U_FAILURE(*ec)) {
+ return;
+ }
+ number->fNumber.truncateStart(maximumIntegerDigits, *ec);
+}
+
+U_CAPI void U_EXPORT2
+usnum_setSign(USimpleNumber* unumber, USimpleNumberSign sign, UErrorCode* ec) {
+ auto* number = USimpleNumberData::validate(unumber, *ec);
+ if (U_FAILURE(*ec)) {
+ return;
+ }
+ number->fNumber.setSign(sign, *ec);
+}
+
+U_CAPI USimpleNumberFormatter* U_EXPORT2
+usnumf_openForLocale(const char* locale, UErrorCode* ec) {
+ auto* impl = new USimpleNumberFormatterData();
+ if (impl == nullptr) {
+ *ec = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
+ }
+ impl->fFormatter = SimpleNumberFormatter::forLocale(locale, *ec);
+ return impl->exportForC();
+}
+
+U_CAPI USimpleNumberFormatter* U_EXPORT2
+usnumf_openForLocaleAndGroupingStrategy(
+ const char* locale, UNumberGroupingStrategy groupingStrategy, UErrorCode* ec) {
+ auto* impl = new USimpleNumberFormatterData();
+ if (impl == nullptr) {
+ *ec = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
+ }
+ impl->fFormatter = SimpleNumberFormatter::forLocaleAndGroupingStrategy(locale, groupingStrategy, *ec);
+ return impl->exportForC();
+}
+
+U_CAPI void U_EXPORT2
+usnumf_format(
+ const USimpleNumberFormatter* uformatter,
+ USimpleNumber* unumber,
+ UFormattedNumber* uresult,
+ UErrorCode* ec) {
+ auto* formatter = USimpleNumberFormatterData::validate(uformatter, *ec);
+ auto* number = USimpleNumberData::validate(unumber, *ec);
+ auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
+ if (U_FAILURE(*ec)) {
+ return;
+ }
+ auto localResult = formatter->fFormatter.format(std::move(number->fNumber), *ec);
+ if (U_FAILURE(*ec)) {
+ return;
+ }
+ result->setTo(std::move(localResult));
+}
+
+U_CAPI void U_EXPORT2
+usnumf_formatInt64(
+ const USimpleNumberFormatter* uformatter,
+ int64_t value,
+ UFormattedNumber* uresult,
+ UErrorCode* ec) {
+ auto* formatter = USimpleNumberFormatterData::validate(uformatter, *ec);
+ auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
+ if (U_FAILURE(*ec)) {
+ return;
+ }
+ auto localResult = formatter->fFormatter.formatInt64(value, *ec);
+ result->setTo(std::move(localResult));
+}
+
+U_CAPI void U_EXPORT2
+usnum_close(USimpleNumber* unumber) {
+ UErrorCode localStatus = U_ZERO_ERROR;
+ const USimpleNumberData* impl = USimpleNumberData::validate(unumber, localStatus);
+ delete impl;
+}
+
+U_CAPI void U_EXPORT2
+usnumf_close(USimpleNumberFormatter* uformatter) {
+ UErrorCode localStatus = U_ZERO_ERROR;
+ const USimpleNumberFormatterData* impl = USimpleNumberFormatterData::validate(uformatter, localStatus);
+ delete impl;
+}
+
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+