diff options
author | mcheshkov <mcheshkov@yandex-team.ru> | 2022-02-10 16:46:16 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:16 +0300 |
commit | 1312621288956f199a5bd5342b0133d4395fa725 (patch) | |
tree | 1a2c5ffcf89eb53ecd79dbc9bc0a195c27404d0c /contrib/libs/icu/i18n/number_utils.cpp | |
parent | e9d19cec64684c9c1e6b0c98297e5b895cf904fe (diff) | |
download | ydb-1312621288956f199a5bd5342b0133d4395fa725.tar.gz |
Restoring authorship annotation for <mcheshkov@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/icu/i18n/number_utils.cpp')
-rw-r--r-- | contrib/libs/icu/i18n/number_utils.cpp | 532 |
1 files changed, 266 insertions, 266 deletions
diff --git a/contrib/libs/icu/i18n/number_utils.cpp b/contrib/libs/icu/i18n/number_utils.cpp index 326e646232..91d7f335cd 100644 --- a/contrib/libs/icu/i18n/number_utils.cpp +++ b/contrib/libs/icu/i18n/number_utils.cpp @@ -1,266 +1,266 @@ -// © 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 <stdlib.h> -#include <cmath> -#include "number_decnum.h" -#include "number_types.h" -#include "number_utils.h" -#include "charstr.h" -#include "decContext.h" -#include "decNumber.h" -#include "double-conversion.h" -#include "fphdlimp.h" -#include "uresimp.h" -#include "ureslocs.h" - -using namespace icu; -using namespace icu::number; -using namespace icu::number::impl; - -using icu::double_conversion::DoubleToStringConverter; - - -namespace { - -const char16_t* -doGetPattern(UResourceBundle* res, const char* nsName, const char* patternKey, UErrorCode& publicStatus, - UErrorCode& localStatus) { - // Construct the path into the resource bundle - CharString key; - key.append("NumberElements/", publicStatus); - key.append(nsName, publicStatus); - key.append("/patterns/", publicStatus); - key.append(patternKey, publicStatus); - if (U_FAILURE(publicStatus)) { - return u""; - } - return ures_getStringByKeyWithFallback(res, key.data(), nullptr, &localStatus); -} - -} - - -const char16_t* utils::getPatternForStyle(const Locale& locale, const char* nsName, CldrPatternStyle style, - UErrorCode& status) { - const char* patternKey; - switch (style) { - case CLDR_PATTERN_STYLE_DECIMAL: - patternKey = "decimalFormat"; - break; - case CLDR_PATTERN_STYLE_CURRENCY: - patternKey = "currencyFormat"; - break; - case CLDR_PATTERN_STYLE_ACCOUNTING: - patternKey = "accountingFormat"; - break; - case CLDR_PATTERN_STYLE_PERCENT: - patternKey = "percentFormat"; - break; - case CLDR_PATTERN_STYLE_SCIENTIFIC: - patternKey = "scientificFormat"; - break; - default: - patternKey = "decimalFormat"; // silence compiler error - UPRV_UNREACHABLE; - } - LocalUResourceBundlePointer res(ures_open(nullptr, locale.getName(), &status)); - if (U_FAILURE(status)) { return u""; } - - // Attempt to get the pattern with the native numbering system. - UErrorCode localStatus = U_ZERO_ERROR; - const char16_t* pattern; - pattern = doGetPattern(res.getAlias(), nsName, patternKey, status, localStatus); - if (U_FAILURE(status)) { return u""; } - - // Fall back to latn if native numbering system does not have the right pattern - if (U_FAILURE(localStatus) && uprv_strcmp("latn", nsName) != 0) { - localStatus = U_ZERO_ERROR; - pattern = doGetPattern(res.getAlias(), "latn", patternKey, status, localStatus); - if (U_FAILURE(status)) { return u""; } - } - - return pattern; -} - - -DecNum::DecNum() { - uprv_decContextDefault(&fContext, DEC_INIT_BASE); - uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN); - fContext.traps = 0; // no traps, thank you (what does this even mean?) -} - -DecNum::DecNum(const DecNum& other, UErrorCode& status) - : fContext(other.fContext) { - // Allocate memory for the new DecNum. - U_ASSERT(fContext.digits == other.fData.getCapacity()); - if (fContext.digits > kDefaultDigits) { - void* p = fData.resize(fContext.digits, 0); - if (p == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - } - - // Copy the data from the old DecNum to the new one. - uprv_memcpy(fData.getAlias(), other.fData.getAlias(), sizeof(decNumber)); - uprv_memcpy(fData.getArrayStart(), - other.fData.getArrayStart(), - other.fData.getArrayLimit() - other.fData.getArrayStart()); -} - -void DecNum::setTo(StringPiece str, UErrorCode& status) { - // We need NUL-terminated for decNumber; CharString guarantees this, but not StringPiece. - CharString cstr(str, status); - if (U_FAILURE(status)) { return; } - _setTo(cstr.data(), str.length(), status); -} - -void DecNum::setTo(const char* str, UErrorCode& status) { - _setTo(str, static_cast<int32_t>(uprv_strlen(str)), status); -} - -void DecNum::setTo(double d, UErrorCode& status) { - // Need to check for NaN and Infinity before going into DoubleToStringConverter - if (std::isnan(d) != 0 || std::isfinite(d) == 0) { - status = U_UNSUPPORTED_ERROR; - return; - } - - // First convert from double to string, then string to DecNum. - // Allocate enough room for: all digits, "E-324", and NUL-terminator. - char buffer[DoubleToStringConverter::kBase10MaximalLength + 6]; - bool sign; // unused; always positive - int32_t length; - int32_t point; - DoubleToStringConverter::DoubleToAscii( - d, - DoubleToStringConverter::DtoaMode::SHORTEST, - 0, - buffer, - sizeof(buffer), - &sign, - &length, - &point - ); - - // Read initial result as a string. - _setTo(buffer, length, status); - - // Set exponent and bitmask. Note that DoubleToStringConverter does not do negatives. - fData.getAlias()->exponent += point - length; - fData.getAlias()->bits |= static_cast<uint8_t>(std::signbit(d) ? DECNEG : 0); -} - -void DecNum::_setTo(const char* str, int32_t maxDigits, UErrorCode& status) { - if (maxDigits > kDefaultDigits) { - fData.resize(maxDigits, 0); - fContext.digits = maxDigits; - } else { - fContext.digits = kDefaultDigits; - } - - static_assert(DECDPUN == 1, "Assumes that DECDPUN is set to 1"); - uprv_decNumberFromString(fData.getAlias(), str, &fContext); - - // Check for invalid syntax and set the corresponding error code. - if ((fContext.status & DEC_Conversion_syntax) != 0) { - status = U_DECIMAL_NUMBER_SYNTAX_ERROR; - return; - } else if (fContext.status != 0) { - // Not a syntax error, but some other error, like an exponent that is too large. - status = U_UNSUPPORTED_ERROR; - return; - } - - // For consistency with Java BigDecimal, no support for DecNum that is NaN or Infinity! - if (decNumberIsSpecial(fData.getAlias())) { - status = U_UNSUPPORTED_ERROR; - return; - } -} - -void -DecNum::setTo(const uint8_t* bcd, int32_t length, int32_t scale, bool isNegative, UErrorCode& status) { - if (length > kDefaultDigits) { - fData.resize(length, 0); - fContext.digits = length; - } else { - fContext.digits = kDefaultDigits; - } - - // "digits is of type int32_t, and must have a value in the range 1 through 999,999,999." - if (length < 1 || length > 999999999) { - // Too large for decNumber - status = U_UNSUPPORTED_ERROR; - return; - } - // "The exponent field holds the exponent of the number. Its range is limited by the requirement that - // "the range of the adjusted exponent of the number be balanced and fit within a whole number of - // "decimal digits (in this implementation, be –999,999,999 through +999,999,999). The adjusted - // "exponent is the exponent that would result if the number were expressed with a single digit before - // "the decimal point, and is therefore given by exponent+digits-1." - if (scale > 999999999 - length + 1 || scale < -999999999 - length + 1) { - // Too large for decNumber - status = U_UNSUPPORTED_ERROR; - return; - } - - fData.getAlias()->digits = length; - fData.getAlias()->exponent = scale; - fData.getAlias()->bits = static_cast<uint8_t>(isNegative ? DECNEG : 0); - uprv_decNumberSetBCD(fData, bcd, static_cast<uint32_t>(length)); - if (fContext.status != 0) { - // Some error occurred while constructing the decNumber. - status = U_INTERNAL_PROGRAM_ERROR; - } -} - -void DecNum::normalize() { - uprv_decNumberReduce(fData, fData, &fContext); -} - -void DecNum::multiplyBy(const DecNum& rhs, UErrorCode& status) { - uprv_decNumberMultiply(fData, fData, rhs.fData, &fContext); - if (fContext.status != 0) { - status = U_INTERNAL_PROGRAM_ERROR; - } -} - -void DecNum::divideBy(const DecNum& rhs, UErrorCode& status) { - uprv_decNumberDivide(fData, fData, rhs.fData, &fContext); - if ((fContext.status & DEC_Inexact) != 0) { - // Ignore. - } else if (fContext.status != 0) { - status = U_INTERNAL_PROGRAM_ERROR; - } -} - -bool DecNum::isNegative() const { - return decNumberIsNegative(fData.getAlias()); -} - -bool DecNum::isZero() const { - return decNumberIsZero(fData.getAlias()); -} - -void DecNum::toString(ByteSink& output, UErrorCode& status) const { - if (U_FAILURE(status)) { - return; - } - // "string must be at least dn->digits+14 characters long" - int32_t minCapacity = fData.getAlias()->digits + 14; - MaybeStackArray<char, 30> buffer(minCapacity); - uprv_decNumberToString(fData, buffer.getAlias()); - output.Append(buffer.getAlias(), static_cast<int32_t>(uprv_strlen(buffer.getAlias()))); -} - -#endif /* #if !UCONFIG_NO_FORMATTING */ +// © 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 <stdlib.h> +#include <cmath> +#include "number_decnum.h" +#include "number_types.h" +#include "number_utils.h" +#include "charstr.h" +#include "decContext.h" +#include "decNumber.h" +#include "double-conversion.h" +#include "fphdlimp.h" +#include "uresimp.h" +#include "ureslocs.h" + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; + +using icu::double_conversion::DoubleToStringConverter; + + +namespace { + +const char16_t* +doGetPattern(UResourceBundle* res, const char* nsName, const char* patternKey, UErrorCode& publicStatus, + UErrorCode& localStatus) { + // Construct the path into the resource bundle + CharString key; + key.append("NumberElements/", publicStatus); + key.append(nsName, publicStatus); + key.append("/patterns/", publicStatus); + key.append(patternKey, publicStatus); + if (U_FAILURE(publicStatus)) { + return u""; + } + return ures_getStringByKeyWithFallback(res, key.data(), nullptr, &localStatus); +} + +} + + +const char16_t* utils::getPatternForStyle(const Locale& locale, const char* nsName, CldrPatternStyle style, + UErrorCode& status) { + const char* patternKey; + switch (style) { + case CLDR_PATTERN_STYLE_DECIMAL: + patternKey = "decimalFormat"; + break; + case CLDR_PATTERN_STYLE_CURRENCY: + patternKey = "currencyFormat"; + break; + case CLDR_PATTERN_STYLE_ACCOUNTING: + patternKey = "accountingFormat"; + break; + case CLDR_PATTERN_STYLE_PERCENT: + patternKey = "percentFormat"; + break; + case CLDR_PATTERN_STYLE_SCIENTIFIC: + patternKey = "scientificFormat"; + break; + default: + patternKey = "decimalFormat"; // silence compiler error + UPRV_UNREACHABLE; + } + LocalUResourceBundlePointer res(ures_open(nullptr, locale.getName(), &status)); + if (U_FAILURE(status)) { return u""; } + + // Attempt to get the pattern with the native numbering system. + UErrorCode localStatus = U_ZERO_ERROR; + const char16_t* pattern; + pattern = doGetPattern(res.getAlias(), nsName, patternKey, status, localStatus); + if (U_FAILURE(status)) { return u""; } + + // Fall back to latn if native numbering system does not have the right pattern + if (U_FAILURE(localStatus) && uprv_strcmp("latn", nsName) != 0) { + localStatus = U_ZERO_ERROR; + pattern = doGetPattern(res.getAlias(), "latn", patternKey, status, localStatus); + if (U_FAILURE(status)) { return u""; } + } + + return pattern; +} + + +DecNum::DecNum() { + uprv_decContextDefault(&fContext, DEC_INIT_BASE); + uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN); + fContext.traps = 0; // no traps, thank you (what does this even mean?) +} + +DecNum::DecNum(const DecNum& other, UErrorCode& status) + : fContext(other.fContext) { + // Allocate memory for the new DecNum. + U_ASSERT(fContext.digits == other.fData.getCapacity()); + if (fContext.digits > kDefaultDigits) { + void* p = fData.resize(fContext.digits, 0); + if (p == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + } + + // Copy the data from the old DecNum to the new one. + uprv_memcpy(fData.getAlias(), other.fData.getAlias(), sizeof(decNumber)); + uprv_memcpy(fData.getArrayStart(), + other.fData.getArrayStart(), + other.fData.getArrayLimit() - other.fData.getArrayStart()); +} + +void DecNum::setTo(StringPiece str, UErrorCode& status) { + // We need NUL-terminated for decNumber; CharString guarantees this, but not StringPiece. + CharString cstr(str, status); + if (U_FAILURE(status)) { return; } + _setTo(cstr.data(), str.length(), status); +} + +void DecNum::setTo(const char* str, UErrorCode& status) { + _setTo(str, static_cast<int32_t>(uprv_strlen(str)), status); +} + +void DecNum::setTo(double d, UErrorCode& status) { + // Need to check for NaN and Infinity before going into DoubleToStringConverter + if (std::isnan(d) != 0 || std::isfinite(d) == 0) { + status = U_UNSUPPORTED_ERROR; + return; + } + + // First convert from double to string, then string to DecNum. + // Allocate enough room for: all digits, "E-324", and NUL-terminator. + char buffer[DoubleToStringConverter::kBase10MaximalLength + 6]; + bool sign; // unused; always positive + int32_t length; + int32_t point; + DoubleToStringConverter::DoubleToAscii( + d, + DoubleToStringConverter::DtoaMode::SHORTEST, + 0, + buffer, + sizeof(buffer), + &sign, + &length, + &point + ); + + // Read initial result as a string. + _setTo(buffer, length, status); + + // Set exponent and bitmask. Note that DoubleToStringConverter does not do negatives. + fData.getAlias()->exponent += point - length; + fData.getAlias()->bits |= static_cast<uint8_t>(std::signbit(d) ? DECNEG : 0); +} + +void DecNum::_setTo(const char* str, int32_t maxDigits, UErrorCode& status) { + if (maxDigits > kDefaultDigits) { + fData.resize(maxDigits, 0); + fContext.digits = maxDigits; + } else { + fContext.digits = kDefaultDigits; + } + + static_assert(DECDPUN == 1, "Assumes that DECDPUN is set to 1"); + uprv_decNumberFromString(fData.getAlias(), str, &fContext); + + // Check for invalid syntax and set the corresponding error code. + if ((fContext.status & DEC_Conversion_syntax) != 0) { + status = U_DECIMAL_NUMBER_SYNTAX_ERROR; + return; + } else if (fContext.status != 0) { + // Not a syntax error, but some other error, like an exponent that is too large. + status = U_UNSUPPORTED_ERROR; + return; + } + + // For consistency with Java BigDecimal, no support for DecNum that is NaN or Infinity! + if (decNumberIsSpecial(fData.getAlias())) { + status = U_UNSUPPORTED_ERROR; + return; + } +} + +void +DecNum::setTo(const uint8_t* bcd, int32_t length, int32_t scale, bool isNegative, UErrorCode& status) { + if (length > kDefaultDigits) { + fData.resize(length, 0); + fContext.digits = length; + } else { + fContext.digits = kDefaultDigits; + } + + // "digits is of type int32_t, and must have a value in the range 1 through 999,999,999." + if (length < 1 || length > 999999999) { + // Too large for decNumber + status = U_UNSUPPORTED_ERROR; + return; + } + // "The exponent field holds the exponent of the number. Its range is limited by the requirement that + // "the range of the adjusted exponent of the number be balanced and fit within a whole number of + // "decimal digits (in this implementation, be –999,999,999 through +999,999,999). The adjusted + // "exponent is the exponent that would result if the number were expressed with a single digit before + // "the decimal point, and is therefore given by exponent+digits-1." + if (scale > 999999999 - length + 1 || scale < -999999999 - length + 1) { + // Too large for decNumber + status = U_UNSUPPORTED_ERROR; + return; + } + + fData.getAlias()->digits = length; + fData.getAlias()->exponent = scale; + fData.getAlias()->bits = static_cast<uint8_t>(isNegative ? DECNEG : 0); + uprv_decNumberSetBCD(fData, bcd, static_cast<uint32_t>(length)); + if (fContext.status != 0) { + // Some error occurred while constructing the decNumber. + status = U_INTERNAL_PROGRAM_ERROR; + } +} + +void DecNum::normalize() { + uprv_decNumberReduce(fData, fData, &fContext); +} + +void DecNum::multiplyBy(const DecNum& rhs, UErrorCode& status) { + uprv_decNumberMultiply(fData, fData, rhs.fData, &fContext); + if (fContext.status != 0) { + status = U_INTERNAL_PROGRAM_ERROR; + } +} + +void DecNum::divideBy(const DecNum& rhs, UErrorCode& status) { + uprv_decNumberDivide(fData, fData, rhs.fData, &fContext); + if ((fContext.status & DEC_Inexact) != 0) { + // Ignore. + } else if (fContext.status != 0) { + status = U_INTERNAL_PROGRAM_ERROR; + } +} + +bool DecNum::isNegative() const { + return decNumberIsNegative(fData.getAlias()); +} + +bool DecNum::isZero() const { + return decNumberIsZero(fData.getAlias()); +} + +void DecNum::toString(ByteSink& output, UErrorCode& status) const { + if (U_FAILURE(status)) { + return; + } + // "string must be at least dn->digits+14 characters long" + int32_t minCapacity = fData.getAlias()->digits + 14; + MaybeStackArray<char, 30> buffer(minCapacity); + uprv_decNumberToString(fData, buffer.getAlias()); + output.Append(buffer.getAlias(), static_cast<int32_t>(uprv_strlen(buffer.getAlias()))); +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ |