mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
parent
194236a1b4
commit
a2854b615a
32 changed files with 2072 additions and 598 deletions
|
@ -99,7 +99,7 @@ static const char *gNumberElementKeys[DecimalFormatSymbols::kFormatSymbolCount]
|
|||
// Initializes this with the decimal format symbols in the default locale.
|
||||
|
||||
DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode& status)
|
||||
: UObject(), locale(), currPattern(NULL) {
|
||||
: UObject(), locale() {
|
||||
initialize(locale, status, true);
|
||||
}
|
||||
|
||||
|
@ -107,17 +107,17 @@ DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode& status)
|
|||
// Initializes this with the decimal format symbols in the desired locale.
|
||||
|
||||
DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, UErrorCode& status)
|
||||
: UObject(), locale(loc), currPattern(NULL) {
|
||||
: UObject(), locale(loc) {
|
||||
initialize(locale, status);
|
||||
}
|
||||
|
||||
DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, const NumberingSystem& ns, UErrorCode& status)
|
||||
: UObject(), locale(loc), currPattern(NULL) {
|
||||
: UObject(), locale(loc) {
|
||||
initialize(locale, status, false, &ns);
|
||||
}
|
||||
|
||||
DecimalFormatSymbols::DecimalFormatSymbols()
|
||||
: UObject(), locale(Locale::getRoot()), currPattern(NULL) {
|
||||
: UObject(), locale(Locale::getRoot()) {
|
||||
*validLocale = *actualLocale = 0;
|
||||
initialize();
|
||||
}
|
||||
|
@ -169,6 +169,7 @@ DecimalFormatSymbols::operator=(const DecimalFormatSymbols& rhs)
|
|||
fIsCustomIntlCurrencySymbol = rhs.fIsCustomIntlCurrencySymbol;
|
||||
fCodePointZero = rhs.fCodePointZero;
|
||||
currPattern = rhs.currPattern;
|
||||
uprv_strcpy(nsName, rhs.nsName);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -383,6 +384,7 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status,
|
|||
} else {
|
||||
nsName = gLatn;
|
||||
}
|
||||
uprv_strcpy(this->nsName, nsName);
|
||||
|
||||
// Open resource bundles
|
||||
const char* locStr = loc.getName();
|
||||
|
@ -517,7 +519,7 @@ DecimalFormatSymbols::initialize() {
|
|||
fCodePointZero = 0x30;
|
||||
U_ASSERT(fCodePointZero == fSymbols[kZeroDigitSymbol].char32At(0));
|
||||
currPattern = nullptr;
|
||||
|
||||
nsName[0] = 0;
|
||||
}
|
||||
|
||||
void DecimalFormatSymbols::setCurrency(const UChar* currency, UErrorCode& status) {
|
||||
|
|
|
@ -153,6 +153,9 @@ public:
|
|||
|
||||
virtual ~FormattedValueStringBuilderImpl();
|
||||
|
||||
FormattedValueStringBuilderImpl(FormattedValueStringBuilderImpl&&) = default;
|
||||
FormattedValueStringBuilderImpl& operator=(FormattedValueStringBuilderImpl&&) = default;
|
||||
|
||||
// Implementation of FormattedValue (const):
|
||||
|
||||
UnicodeString toString(UErrorCode& status) const U_OVERRIDE;
|
||||
|
|
|
@ -202,6 +202,7 @@
|
|||
<ClCompile Include="number_mapper.cpp" />
|
||||
<ClCompile Include="number_multiplier.cpp" />
|
||||
<ClCompile Include="number_currencysymbols.cpp" />
|
||||
<ClCompile Include="number_simple.cpp" />
|
||||
<ClCompile Include="number_skeletons.cpp" />
|
||||
<ClCompile Include="number_symbolswrapper.cpp" />
|
||||
<ClCompile Include="number_capi.cpp" />
|
||||
|
|
|
@ -609,6 +609,9 @@
|
|||
<ClCompile Include="number_currencysymbols.cpp">
|
||||
<Filter>formatting</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="number_simple.cpp">
|
||||
<Filter>formatting</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="number_skeletons.cpp">
|
||||
<Filter>formatting</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -435,6 +435,7 @@
|
|||
<ClCompile Include="number_mapper.cpp" />
|
||||
<ClCompile Include="number_multiplier.cpp" />
|
||||
<ClCompile Include="number_currencysymbols.cpp" />
|
||||
<ClCompile Include="number_simple.cpp" />
|
||||
<ClCompile Include="number_skeletons.cpp" />
|
||||
<ClCompile Include="number_symbolswrapper.cpp" />
|
||||
<ClCompile Include="number_capi.cpp" />
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#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;
|
||||
|
@ -35,6 +37,24 @@ struct UNumberFormatterData : public UMemory,
|
|||
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)
|
||||
|
@ -46,6 +66,8 @@ struct UFormattedNumberImpl : public UFormattedValueImpl, public UFormattedNumbe
|
|||
|
||||
FormattedNumber fImpl;
|
||||
UFormattedNumberData fData;
|
||||
|
||||
void setTo(FormattedNumber value);
|
||||
};
|
||||
|
||||
UFormattedNumberImpl::UFormattedNumberImpl()
|
||||
|
@ -58,6 +80,10 @@ UFormattedNumberImpl::~UFormattedNumberImpl() {
|
|||
fImpl.fData = nullptr;
|
||||
}
|
||||
|
||||
void UFormattedNumberImpl::setTo(FormattedNumber value) {
|
||||
fData = std::move(*value.fData);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
U_NAMESPACE_END
|
||||
|
@ -225,6 +251,144 @@ unumf_close(UNumberFormatter* f) {
|
|||
}
|
||||
|
||||
|
||||
///// SIMPLE NUMBER FORMATTER /////
|
||||
|
||||
U_CAPI USimpleNumber* U_EXPORT2
|
||||
usnum_openForInt64(int64_t value, UErrorCode* ec) {
|
||||
auto* impl = new USimpleNumberData();
|
||||
if (impl == nullptr) {
|
||||
*ec = U_MEMORY_ALLOCATION_ERROR;
|
||||
return nullptr;
|
||||
}
|
||||
impl->fNumber = SimpleNumber::forInt64(value, *ec);
|
||||
return impl->exportForC();
|
||||
}
|
||||
|
||||
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_formatAndAdoptNumber(
|
||||
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)) {
|
||||
delete number;
|
||||
return;
|
||||
}
|
||||
auto localResult = formatter->fFormatter.format(std::move(number->fNumber), *ec);
|
||||
result->setTo(std::move(localResult));
|
||||
delete number;
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ int32_t NumberFormatterImpl::formatStatic(const MacroProps ¯os, UFormattedNu
|
|||
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);
|
||||
int32_t length = writeNumber(micros.simple, inValue, outString, 0, status);
|
||||
length += writeAffixes(micros, outString, 0, length, status);
|
||||
results->outputUnit = std::move(micros.outputUnit);
|
||||
results->gender = micros.gender;
|
||||
|
@ -61,7 +61,7 @@ int32_t NumberFormatterImpl::format(UFormattedNumberData *results, UErrorCode &s
|
|||
MicroProps micros;
|
||||
preProcess(inValue, micros, status);
|
||||
if (U_FAILURE(status)) { return 0; }
|
||||
int32_t length = writeNumber(micros, inValue, outString, 0, status);
|
||||
int32_t length = writeNumber(micros.simple, inValue, outString, 0, status);
|
||||
length += writeAffixes(micros, outString, 0, length, status);
|
||||
results->outputUnit = std::move(micros.outputUnit);
|
||||
results->gender = micros.gender;
|
||||
|
@ -186,7 +186,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
|
|||
|
||||
// Resolve the symbols. Do this here because currency may need to customize them.
|
||||
if (macros.symbols.isDecimalFormatSymbols()) {
|
||||
fMicros.symbols = macros.symbols.getDecimalFormatSymbols();
|
||||
fMicros.simple.symbols = macros.symbols.getDecimalFormatSymbols();
|
||||
} else {
|
||||
LocalPointer<DecimalFormatSymbols> newSymbols(
|
||||
new DecimalFormatSymbols(macros.locale, *ns, status), status);
|
||||
|
@ -199,15 +199,15 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
fMicros.symbols = newSymbols.getAlias();
|
||||
fMicros.simple.symbols = newSymbols.getAlias();
|
||||
fSymbols.adoptInstead(newSymbols.orphan());
|
||||
}
|
||||
|
||||
// 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 && fMicros.symbols->getCurrencyPattern() != nullptr) {
|
||||
pattern = fMicros.symbols->getCurrencyPattern();
|
||||
if (isCurrency && fMicros.simple.symbols->getCurrencyPattern() != nullptr) {
|
||||
pattern = fMicros.simple.symbols->getCurrencyPattern();
|
||||
}
|
||||
if (pattern == nullptr) {
|
||||
CldrPatternStyle patternStyle;
|
||||
|
@ -291,14 +291,14 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
|
|||
|
||||
// Grouping strategy
|
||||
if (!macros.grouper.isBogus()) {
|
||||
fMicros.grouping = macros.grouper;
|
||||
fMicros.simple.grouping = macros.grouper;
|
||||
} else if (isCompactNotation) {
|
||||
// Compact notation uses minGrouping by default since ICU 59
|
||||
fMicros.grouping = Grouper::forStrategy(UNUM_GROUPING_MIN2);
|
||||
fMicros.simple.grouping = Grouper::forStrategy(UNUM_GROUPING_MIN2);
|
||||
} else {
|
||||
fMicros.grouping = Grouper::forStrategy(UNUM_GROUPING_AUTO);
|
||||
fMicros.simple.grouping = Grouper::forStrategy(UNUM_GROUPING_AUTO);
|
||||
}
|
||||
fMicros.grouping.setLocaleData(*fPatternInfo, macros.locale);
|
||||
fMicros.simple.grouping.setLocaleData(*fPatternInfo, macros.locale);
|
||||
|
||||
// Padding strategy
|
||||
if (!macros.padder.isBogus()) {
|
||||
|
@ -323,17 +323,17 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
|
|||
|
||||
// Decimal mark display
|
||||
if (macros.decimal != UNUM_DECIMAL_SEPARATOR_COUNT) {
|
||||
fMicros.decimal = macros.decimal;
|
||||
fMicros.simple.decimal = macros.decimal;
|
||||
} else {
|
||||
fMicros.decimal = UNUM_DECIMAL_SEPARATOR_AUTO;
|
||||
fMicros.simple.decimal = UNUM_DECIMAL_SEPARATOR_AUTO;
|
||||
}
|
||||
|
||||
// Use monetary separator symbols
|
||||
fMicros.useCurrency = isCurrency;
|
||||
fMicros.simple.useCurrency = isCurrency;
|
||||
|
||||
// Inner modifier (scientific notation)
|
||||
if (macros.notation.fType == Notation::NTN_SCIENTIFIC) {
|
||||
auto newScientificHandler = new ScientificHandler(¯os.notation, fMicros.symbols, chain);
|
||||
auto newScientificHandler = new ScientificHandler(¯os.notation, fMicros.simple.symbols, chain);
|
||||
if (newScientificHandler == nullptr) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return nullptr;
|
||||
|
@ -362,13 +362,13 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
|
|||
patternModifier->setPatternAttributes(fMicros.sign, isPermille, macros.approximately);
|
||||
if (patternModifier->needsPlurals()) {
|
||||
patternModifier->setSymbols(
|
||||
fMicros.symbols,
|
||||
fMicros.simple.symbols,
|
||||
currency,
|
||||
unitWidth,
|
||||
resolvePluralRules(macros.rules, macros.locale, status),
|
||||
status);
|
||||
} else {
|
||||
patternModifier->setSymbols(fMicros.symbols, currency, unitWidth, nullptr, status);
|
||||
patternModifier->setSymbols(fMicros.simple.symbols, currency, unitWidth, nullptr, status);
|
||||
}
|
||||
if (safe) {
|
||||
fImmutablePatternModifier.adoptInsteadAndCheckErrorCode(patternModifier->createImmutable(status),
|
||||
|
@ -380,7 +380,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
|
|||
|
||||
// currencyAsDecimal
|
||||
if (affixProvider->currencyAsDecimal()) {
|
||||
fMicros.currencyAsDecimal = patternModifier->getCurrencySymbolForUnitWidth(status);
|
||||
fMicros.simple.currencyAsDecimal = patternModifier->getCurrencySymbolForUnitWidth(status);
|
||||
}
|
||||
|
||||
// Outer modifier (CLDR units and currency long names)
|
||||
|
@ -481,8 +481,10 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
|
|||
}
|
||||
|
||||
const PluralRules*
|
||||
NumberFormatterImpl::resolvePluralRules(const PluralRules* rulesPtr, const Locale& locale,
|
||||
UErrorCode& status) {
|
||||
NumberFormatterImpl::resolvePluralRules(
|
||||
const PluralRules* rulesPtr,
|
||||
const Locale& locale,
|
||||
UErrorCode& status) {
|
||||
if (rulesPtr != nullptr) {
|
||||
return rulesPtr;
|
||||
}
|
||||
|
@ -493,8 +495,12 @@ NumberFormatterImpl::resolvePluralRules(const PluralRules* rulesPtr, const Local
|
|||
return fRules.getAlias();
|
||||
}
|
||||
|
||||
int32_t NumberFormatterImpl::writeAffixes(const MicroProps& micros, FormattedStringBuilder& string,
|
||||
int32_t start, int32_t end, UErrorCode& status) {
|
||||
int32_t NumberFormatterImpl::writeAffixes(
|
||||
const MicroProps& micros,
|
||||
FormattedStringBuilder& string,
|
||||
int32_t start,
|
||||
int32_t end,
|
||||
UErrorCode& status) {
|
||||
U_ASSERT(micros.modOuter != nullptr);
|
||||
// Always apply the inner modifier (which is "strong").
|
||||
int32_t length = micros.modInner->apply(string, start, end, status);
|
||||
|
@ -508,9 +514,12 @@ int32_t NumberFormatterImpl::writeAffixes(const MicroProps& micros, FormattedStr
|
|||
return length;
|
||||
}
|
||||
|
||||
int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuantity& quantity,
|
||||
FormattedStringBuilder& string, int32_t index,
|
||||
UErrorCode& status) {
|
||||
int32_t NumberFormatterImpl::writeNumber(
|
||||
const SimpleMicroProps& micros,
|
||||
DecimalQuantity& quantity,
|
||||
FormattedStringBuilder& string,
|
||||
int32_t index,
|
||||
UErrorCode& status) {
|
||||
int32_t length = 0;
|
||||
if (quantity.isInfinite()) {
|
||||
length += string.insert(
|
||||
|
@ -528,7 +537,12 @@ int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuanti
|
|||
|
||||
} else {
|
||||
// Add the integer digits
|
||||
length += writeIntegerDigits(micros, quantity, string, length + index, status);
|
||||
length += writeIntegerDigits(
|
||||
micros,
|
||||
quantity,
|
||||
string,
|
||||
length + index,
|
||||
status);
|
||||
|
||||
// Add the decimal point
|
||||
if (quantity.getLowerDisplayMagnitude() < 0 || micros.decimal == UNUM_DECIMAL_SEPARATOR_ALWAYS) {
|
||||
|
@ -573,9 +587,12 @@ int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuanti
|
|||
return length;
|
||||
}
|
||||
|
||||
int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps& micros, DecimalQuantity& quantity,
|
||||
FormattedStringBuilder& string, int32_t index,
|
||||
UErrorCode& status) {
|
||||
int32_t NumberFormatterImpl::writeIntegerDigits(
|
||||
const SimpleMicroProps& micros,
|
||||
DecimalQuantity& quantity,
|
||||
FormattedStringBuilder& string,
|
||||
int32_t index,
|
||||
UErrorCode& status) {
|
||||
int length = 0;
|
||||
int integerCount = quantity.getUpperDisplayMagnitude() + 1;
|
||||
for (int i = 0; i < integerCount; i++) {
|
||||
|
@ -605,9 +622,12 @@ int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps& micros, Decima
|
|||
return length;
|
||||
}
|
||||
|
||||
int32_t NumberFormatterImpl::writeFractionDigits(const MicroProps& micros, DecimalQuantity& quantity,
|
||||
FormattedStringBuilder& string, int32_t index,
|
||||
UErrorCode& status) {
|
||||
int32_t NumberFormatterImpl::writeFractionDigits(
|
||||
const SimpleMicroProps& micros,
|
||||
DecimalQuantity& quantity,
|
||||
FormattedStringBuilder& string,
|
||||
int32_t index,
|
||||
UErrorCode& status) {
|
||||
int length = 0;
|
||||
int fractionCount = -quantity.getLowerDisplayMagnitude();
|
||||
for (int i = 0; i < fractionCount; i++) {
|
||||
|
|
|
@ -79,14 +79,22 @@ class NumberFormatterImpl : public UMemory {
|
|||
* Synthesizes the output string from a MicroProps and DecimalQuantity.
|
||||
* This method formats only the main number, not affixes.
|
||||
*/
|
||||
static int32_t writeNumber(const MicroProps& micros, DecimalQuantity& quantity,
|
||||
FormattedStringBuilder& string, int32_t index, UErrorCode& status);
|
||||
static int32_t writeNumber(
|
||||
const SimpleMicroProps& micros,
|
||||
DecimalQuantity& quantity,
|
||||
FormattedStringBuilder& string,
|
||||
int32_t index,
|
||||
UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Adds the affixes. Intended to be called immediately after formatNumber.
|
||||
*/
|
||||
static int32_t writeAffixes(const MicroProps& micros, FormattedStringBuilder& string, int32_t start,
|
||||
int32_t end, UErrorCode& status);
|
||||
static int32_t writeAffixes(
|
||||
const MicroProps& micros,
|
||||
FormattedStringBuilder& string,
|
||||
int32_t start,
|
||||
int32_t end,
|
||||
UErrorCode& status);
|
||||
|
||||
private:
|
||||
// Head of the MicroPropsGenerator linked list. Subclasses' processQuantity
|
||||
|
@ -146,12 +154,20 @@ class NumberFormatterImpl : public UMemory {
|
|||
macrosToMicroGenerator(const MacroProps ¯os, bool safe, UErrorCode &status);
|
||||
|
||||
static int32_t
|
||||
writeIntegerDigits(const MicroProps µs, DecimalQuantity &quantity, FormattedStringBuilder &string,
|
||||
int32_t index, UErrorCode &status);
|
||||
writeIntegerDigits(
|
||||
const SimpleMicroProps& micros,
|
||||
DecimalQuantity &quantity,
|
||||
FormattedStringBuilder &string,
|
||||
int32_t index,
|
||||
UErrorCode &status);
|
||||
|
||||
static int32_t
|
||||
writeFractionDigits(const MicroProps µs, DecimalQuantity &quantity, FormattedStringBuilder &string,
|
||||
int32_t index, UErrorCode &status);
|
||||
writeFractionDigits(
|
||||
const SimpleMicroProps& micros,
|
||||
DecimalQuantity &quantity,
|
||||
FormattedStringBuilder &string,
|
||||
int32_t index,
|
||||
UErrorCode &status);
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
|
|
@ -67,33 +67,39 @@ class IntMeasures : public MaybeStackArray<int64_t, 2> {
|
|||
UErrorCode status = U_ZERO_ERROR;
|
||||
};
|
||||
|
||||
struct SimpleMicroProps : public UMemory {
|
||||
Grouper grouping;
|
||||
bool useCurrency = false;
|
||||
UNumberDecimalSeparatorDisplay decimal = UNUM_DECIMAL_SEPARATOR_AUTO;
|
||||
|
||||
// Currency symbol to be used as the decimal separator
|
||||
UnicodeString currencyAsDecimal = ICU_Utility::makeBogusString();
|
||||
|
||||
// Note: This struct has no direct ownership of the following pointer.
|
||||
const DecimalFormatSymbols* symbols = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* MicroProps is the first MicroPropsGenerator that should be should be called,
|
||||
* producing an initialized MicroProps instance that will be passed on and
|
||||
* modified throughout the rest of the chain of MicroPropsGenerator instances.
|
||||
*/
|
||||
struct MicroProps : public MicroPropsGenerator {
|
||||
SimpleMicroProps simple;
|
||||
|
||||
// NOTE: All of these fields are properly initialized in NumberFormatterImpl.
|
||||
RoundingImpl rounder;
|
||||
Grouper grouping;
|
||||
Padder padding;
|
||||
IntegerWidth integerWidth;
|
||||
UNumberSignDisplay sign;
|
||||
UNumberDecimalSeparatorDisplay decimal;
|
||||
bool useCurrency;
|
||||
char nsName[9];
|
||||
|
||||
// Currency symbol to be used as the decimal separator
|
||||
UnicodeString currencyAsDecimal = ICU_Utility::makeBogusString();
|
||||
|
||||
// No ownership: must point at a string which will outlive MicroProps
|
||||
// instances, e.g. a string with static storage duration, or just a string
|
||||
// that will never be deallocated or modified.
|
||||
const char *gender;
|
||||
|
||||
// Note: This struct has no direct ownership of the following pointers.
|
||||
const DecimalFormatSymbols* symbols;
|
||||
|
||||
// Pointers to Modifiers provided by the number formatting pipeline (when
|
||||
// the value is known):
|
||||
|
|
|
@ -62,12 +62,21 @@ Modifier::Parameters::Parameters(
|
|||
|
||||
ModifierStore::~ModifierStore() = default;
|
||||
|
||||
AdoptingModifierStore::~AdoptingModifierStore() {
|
||||
AdoptingSignumModifierStore::~AdoptingSignumModifierStore() {
|
||||
for (const Modifier *mod : mods) {
|
||||
delete mod;
|
||||
}
|
||||
}
|
||||
|
||||
AdoptingSignumModifierStore&
|
||||
AdoptingSignumModifierStore::operator=(AdoptingSignumModifierStore&& other) U_NOEXCEPT {
|
||||
for (size_t i=0; i<SIGNUM_COUNT; i++) {
|
||||
this->mods[i] = other.mods[i];
|
||||
other.mods[i] = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
int32_t ConstantAffixModifier::apply(FormattedStringBuilder &output, int leftIndex, int rightIndex,
|
||||
UErrorCode &status) const {
|
||||
|
|
|
@ -272,13 +272,45 @@ class U_I18N_API EmptyModifier : public Modifier, public UMemory {
|
|||
bool fStrong;
|
||||
};
|
||||
|
||||
/** An adopting Modifier store that varies by signum but not plural form. */
|
||||
class U_I18N_API AdoptingSignumModifierStore : public UMemory {
|
||||
public:
|
||||
virtual ~AdoptingSignumModifierStore();
|
||||
|
||||
AdoptingSignumModifierStore() = default;
|
||||
|
||||
// No copying!
|
||||
AdoptingSignumModifierStore(const AdoptingSignumModifierStore &other) = delete;
|
||||
AdoptingSignumModifierStore& operator=(const AdoptingSignumModifierStore& other) = delete;
|
||||
|
||||
// Moving is OK
|
||||
AdoptingSignumModifierStore(AdoptingSignumModifierStore &&other) U_NOEXCEPT {
|
||||
*this = std::move(other);
|
||||
}
|
||||
AdoptingSignumModifierStore& operator=(AdoptingSignumModifierStore&& other) U_NOEXCEPT;
|
||||
|
||||
/** Take ownership of the Modifier and slot it in at the given Signum. */
|
||||
void adoptModifier(Signum signum, const Modifier* mod) {
|
||||
U_ASSERT(mods[signum] == nullptr);
|
||||
mods[signum] = mod;
|
||||
}
|
||||
|
||||
inline const Modifier*& operator[](Signum signum) {
|
||||
return mods[signum];
|
||||
}
|
||||
inline Modifier const* operator[](Signum signum) const {
|
||||
return mods[signum];
|
||||
}
|
||||
|
||||
private:
|
||||
const Modifier* mods[SIGNUM_COUNT] = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* This implementation of ModifierStore adopts Modifier pointers.
|
||||
*/
|
||||
class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory {
|
||||
public:
|
||||
virtual ~AdoptingModifierStore();
|
||||
|
||||
static constexpr StandardPlural::Form DEFAULT_STANDARD_PLURAL = StandardPlural::OTHER;
|
||||
|
||||
AdoptingModifierStore() = default;
|
||||
|
@ -286,46 +318,36 @@ class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory {
|
|||
// No copying!
|
||||
AdoptingModifierStore(const AdoptingModifierStore &other) = delete;
|
||||
|
||||
/**
|
||||
* Sets the Modifier with the specified signum and plural form.
|
||||
*/
|
||||
void adoptModifier(Signum signum, StandardPlural::Form plural, const Modifier *mod) {
|
||||
U_ASSERT(mods[getModIndex(signum, plural)] == nullptr);
|
||||
mods[getModIndex(signum, plural)] = mod;
|
||||
// Moving is OK
|
||||
AdoptingModifierStore(AdoptingModifierStore &&other) = default;
|
||||
|
||||
/** Sets the modifiers for a specific plural form. */
|
||||
void adoptSignumModifierStore(StandardPlural::Form plural, AdoptingSignumModifierStore other) {
|
||||
mods[plural] = std::move(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Modifier with the specified signum.
|
||||
* The modifier will apply to all plural forms.
|
||||
*/
|
||||
void adoptModifierWithoutPlural(Signum signum, const Modifier *mod) {
|
||||
U_ASSERT(mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] == nullptr);
|
||||
mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] = mod;
|
||||
/** Sets the modifiers for the default plural form. */
|
||||
void adoptSignumModifierStoreNoPlural(AdoptingSignumModifierStore other) {
|
||||
mods[DEFAULT_STANDARD_PLURAL] = std::move(other);
|
||||
}
|
||||
|
||||
/** Returns a reference to the modifier; no ownership change. */
|
||||
const Modifier *getModifier(Signum signum, StandardPlural::Form plural) const U_OVERRIDE {
|
||||
const Modifier* modifier = mods[getModIndex(signum, plural)];
|
||||
const Modifier* modifier = mods[plural][signum];
|
||||
if (modifier == nullptr && plural != DEFAULT_STANDARD_PLURAL) {
|
||||
modifier = mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)];
|
||||
modifier = mods[DEFAULT_STANDARD_PLURAL][signum];
|
||||
}
|
||||
return modifier;
|
||||
}
|
||||
|
||||
/** Returns a reference to the modifier; no ownership change. */
|
||||
const Modifier *getModifierWithoutPlural(Signum signum) const {
|
||||
return mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)];
|
||||
return mods[DEFAULT_STANDARD_PLURAL][signum];
|
||||
}
|
||||
|
||||
private:
|
||||
// NOTE: mods is zero-initialized (to nullptr)
|
||||
const Modifier *mods[4 * StandardPlural::COUNT] = {};
|
||||
|
||||
inline static int32_t getModIndex(Signum signum, StandardPlural::Form plural) {
|
||||
U_ASSERT(signum >= 0 && signum < SIGNUM_COUNT);
|
||||
U_ASSERT(plural >= 0 && plural < StandardPlural::COUNT);
|
||||
return static_cast<int32_t>(plural) * SIGNUM_COUNT + signum;
|
||||
}
|
||||
AdoptingSignumModifierStore mods[StandardPlural::COUNT] = {};
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
|
|
@ -60,6 +60,21 @@ bool MutablePatternModifier::needsPlurals() const {
|
|||
// Silently ignore any error codes.
|
||||
}
|
||||
|
||||
AdoptingSignumModifierStore MutablePatternModifier::createImmutableForPlural(StandardPlural::Form plural, UErrorCode& status) {
|
||||
AdoptingSignumModifierStore pm;
|
||||
|
||||
setNumberProperties(SIGNUM_POS, plural);
|
||||
pm.adoptModifier(SIGNUM_POS, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_NEG_ZERO, plural);
|
||||
pm.adoptModifier(SIGNUM_NEG_ZERO, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_POS_ZERO, plural);
|
||||
pm.adoptModifier(SIGNUM_POS_ZERO, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_NEG, plural);
|
||||
pm.adoptModifier(SIGNUM_NEG, createConstantModifier(status));
|
||||
|
||||
return pm;
|
||||
}
|
||||
|
||||
ImmutablePatternModifier* MutablePatternModifier::createImmutable(UErrorCode& status) {
|
||||
// TODO: Move StandardPlural VALUES to standardplural.h
|
||||
static const StandardPlural::Form STANDARD_PLURAL_VALUES[] = {
|
||||
|
@ -79,14 +94,7 @@ ImmutablePatternModifier* MutablePatternModifier::createImmutable(UErrorCode& st
|
|||
if (needsPlurals()) {
|
||||
// Slower path when we require the plural keyword.
|
||||
for (StandardPlural::Form plural : STANDARD_PLURAL_VALUES) {
|
||||
setNumberProperties(SIGNUM_POS, plural);
|
||||
pm->adoptModifier(SIGNUM_POS, plural, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_NEG_ZERO, plural);
|
||||
pm->adoptModifier(SIGNUM_NEG_ZERO, plural, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_POS_ZERO, plural);
|
||||
pm->adoptModifier(SIGNUM_POS_ZERO, plural, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_NEG, plural);
|
||||
pm->adoptModifier(SIGNUM_NEG, plural, createConstantModifier(status));
|
||||
pm->adoptSignumModifierStore(plural, createImmutableForPlural(plural, status));
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
delete pm;
|
||||
|
@ -95,14 +103,7 @@ ImmutablePatternModifier* MutablePatternModifier::createImmutable(UErrorCode& st
|
|||
return new ImmutablePatternModifier(pm, fRules); // adopts pm
|
||||
} else {
|
||||
// Faster path when plural keyword is not needed.
|
||||
setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT);
|
||||
pm->adoptModifierWithoutPlural(SIGNUM_POS, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_NEG_ZERO, StandardPlural::Form::COUNT);
|
||||
pm->adoptModifierWithoutPlural(SIGNUM_NEG_ZERO, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_POS_ZERO, StandardPlural::Form::COUNT);
|
||||
pm->adoptModifierWithoutPlural(SIGNUM_POS_ZERO, createConstantModifier(status));
|
||||
setNumberProperties(SIGNUM_NEG, StandardPlural::Form::COUNT);
|
||||
pm->adoptModifierWithoutPlural(SIGNUM_NEG, createConstantModifier(status));
|
||||
pm->adoptSignumModifierStoreNoPlural(createImmutableForPlural(StandardPlural::Form::COUNT, status));
|
||||
if (U_FAILURE(status)) {
|
||||
delete pm;
|
||||
return nullptr;
|
||||
|
|
|
@ -156,6 +156,9 @@ class U_I18N_API MutablePatternModifier
|
|||
*/
|
||||
bool needsPlurals() const;
|
||||
|
||||
/** Creates a quantity-dependent Modifier for the specified plural form. */
|
||||
AdoptingSignumModifierStore createImmutableForPlural(StandardPlural::Form plural, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which is immutable
|
||||
* and can be saved for future use. The number properties in the current instance are mutated; all other properties
|
||||
|
|
255
icu4c/source/i18n/number_simple.cpp
Normal file
255
icu4c/source/i18n/number_simple.cpp
Normal file
|
@ -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 */
|
|
@ -35,6 +35,9 @@ public:
|
|||
UFormattedNumberData() : FormattedValueStringBuilderImpl(kUndefinedField) {}
|
||||
virtual ~UFormattedNumberData();
|
||||
|
||||
UFormattedNumberData(UFormattedNumberData&&) = default;
|
||||
UFormattedNumberData& operator=(UFormattedNumberData&&) = default;
|
||||
|
||||
// The formatted quantity.
|
||||
DecimalQuantity quantity;
|
||||
|
||||
|
|
|
@ -239,7 +239,7 @@ void NumberRangeFormatterImpl::formatSingleValue(UFormattedNumberRangeData& data
|
|||
UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) { return; }
|
||||
if (fSameFormatters) {
|
||||
int32_t length = NumberFormatterImpl::writeNumber(micros1, data.quantity1, data.getStringRef(), 0, status);
|
||||
int32_t length = NumberFormatterImpl::writeNumber(micros1.simple, data.quantity1, data.getStringRef(), 0, status);
|
||||
NumberFormatterImpl::writeAffixes(micros1, data.getStringRef(), 0, length, status);
|
||||
} else {
|
||||
formatRange(data, micros1, micros2, status);
|
||||
|
@ -256,7 +256,7 @@ void NumberRangeFormatterImpl::formatApproximately (UFormattedNumberRangeData& d
|
|||
MicroProps microsAppx;
|
||||
data.quantity1.resetExponent();
|
||||
fApproximatelyFormatter.preProcess(data.quantity1, microsAppx, status);
|
||||
int32_t length = NumberFormatterImpl::writeNumber(microsAppx, data.quantity1, data.getStringRef(), 0, status);
|
||||
int32_t length = NumberFormatterImpl::writeNumber(microsAppx.simple, data.quantity1, data.getStringRef(), 0, status);
|
||||
length += microsAppx.modInner->apply(data.getStringRef(), 0, length, status);
|
||||
length += microsAppx.modMiddle->apply(data.getStringRef(), 0, length, status);
|
||||
microsAppx.modOuter->apply(data.getStringRef(), 0, length, status);
|
||||
|
@ -384,10 +384,10 @@ void NumberRangeFormatterImpl::formatRange(UFormattedNumberRangeData& data,
|
|||
}
|
||||
}
|
||||
|
||||
length1 += NumberFormatterImpl::writeNumber(micros1, data.quantity1, string, UPRV_INDEX_0, status);
|
||||
length1 += NumberFormatterImpl::writeNumber(micros1.simple, data.quantity1, string, UPRV_INDEX_0, status);
|
||||
// ICU-21684: Write the second number to a temp string to avoid repeated insert operations
|
||||
FormattedStringBuilder tempString;
|
||||
NumberFormatterImpl::writeNumber(micros2, data.quantity2, tempString, 0, status);
|
||||
NumberFormatterImpl::writeNumber(micros2.simple, data.quantity2, tempString, 0, status);
|
||||
length2 += string.insert(UPRV_INDEX_2, tempString, status);
|
||||
|
||||
// TODO: Support padding?
|
||||
|
|
|
@ -122,6 +122,7 @@ number_patternmodifier.cpp
|
|||
number_patternstring.cpp
|
||||
number_rounding.cpp
|
||||
number_scientific.cpp
|
||||
number_simple.cpp
|
||||
number_skeletons.cpp
|
||||
number_symbolswrapper.cpp
|
||||
number_usageprefs.cpp
|
||||
|
|
|
@ -456,6 +456,12 @@ public:
|
|||
* @internal
|
||||
*/
|
||||
inline const char16_t* getCurrencyPattern(void) const;
|
||||
|
||||
/**
|
||||
* Returns the numbering system with which this DecimalFormatSymbols was initialized.
|
||||
* @internal
|
||||
*/
|
||||
inline const char* getNumberingSystemName(void) const;
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
|
||||
private:
|
||||
|
@ -500,12 +506,13 @@ private:
|
|||
|
||||
char actualLocale[ULOC_FULLNAME_CAPACITY];
|
||||
char validLocale[ULOC_FULLNAME_CAPACITY];
|
||||
const char16_t* currPattern;
|
||||
const char16_t* currPattern = nullptr;
|
||||
|
||||
UnicodeString currencySpcBeforeSym[UNUM_CURRENCY_SPACING_COUNT];
|
||||
UnicodeString currencySpcAfterSym[UNUM_CURRENCY_SPACING_COUNT];
|
||||
UBool fIsCustomCurrencySymbol;
|
||||
UBool fIsCustomIntlCurrencySymbol;
|
||||
char nsName[kInternalNumSysNameCapacity+1] = {};
|
||||
};
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -591,6 +598,10 @@ inline const char16_t*
|
|||
DecimalFormatSymbols::getCurrencyPattern() const {
|
||||
return currPattern;
|
||||
}
|
||||
inline const char*
|
||||
DecimalFormatSymbols::getNumberingSystemName() const {
|
||||
return nsName;
|
||||
}
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
215
icu4c/source/i18n/unicode/formattednumber.h
Normal file
215
icu4c/source/i18n/unicode/formattednumber.h
Normal file
|
@ -0,0 +1,215 @@
|
|||
// © 2022 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html
|
||||
|
||||
#ifndef __FORMATTEDNUMBER_H__
|
||||
#define __FORMATTEDNUMBER_H__
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if U_SHOW_CPLUSPLUS_API
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/uobject.h"
|
||||
#include "unicode/formattedvalue.h"
|
||||
#include "unicode/measunit.h"
|
||||
#include "unicode/udisplayoptions.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief C API: Formatted number result from various number formatting functions.
|
||||
*
|
||||
* See also {@link icu::FormattedValue} for additional things you can do with a FormattedNumber.
|
||||
*/
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class FieldPositionIteratorHandler;
|
||||
|
||||
namespace number { // icu::number
|
||||
|
||||
namespace impl {
|
||||
class DecimalQuantity;
|
||||
class UFormattedNumberData;
|
||||
struct UFormattedNumberImpl;
|
||||
} // icu::number::impl
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The result of a number formatting operation. This class allows the result to be exported in several data types,
|
||||
* including a UnicodeString and a FieldPositionIterator.
|
||||
*
|
||||
* Instances of this class are immutable and thread-safe.
|
||||
*
|
||||
* @stable ICU 60
|
||||
*/
|
||||
class U_I18N_API FormattedNumber : public UMemory, public FormattedValue {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default constructor; makes an empty FormattedNumber.
|
||||
* @stable ICU 64
|
||||
*/
|
||||
FormattedNumber()
|
||||
: fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {}
|
||||
|
||||
/**
|
||||
* Move constructor: Leaves the source FormattedNumber in an undefined state.
|
||||
* @stable ICU 62
|
||||
*/
|
||||
FormattedNumber(FormattedNumber&& src) U_NOEXCEPT;
|
||||
|
||||
/**
|
||||
* Destruct an instance of FormattedNumber.
|
||||
* @stable ICU 60
|
||||
*/
|
||||
virtual ~FormattedNumber() U_OVERRIDE;
|
||||
|
||||
/** Copying not supported; use move constructor instead. */
|
||||
FormattedNumber(const FormattedNumber&) = delete;
|
||||
|
||||
/** Copying not supported; use move assignment instead. */
|
||||
FormattedNumber& operator=(const FormattedNumber&) = delete;
|
||||
|
||||
/**
|
||||
* Move assignment: Leaves the source FormattedNumber in an undefined state.
|
||||
* @stable ICU 62
|
||||
*/
|
||||
FormattedNumber& operator=(FormattedNumber&& src) U_NOEXCEPT;
|
||||
|
||||
// Copybrief: this method is older than the parent method
|
||||
/**
|
||||
* @copybrief FormattedValue::toString()
|
||||
*
|
||||
* For more information, see FormattedValue::toString()
|
||||
*
|
||||
* @stable ICU 62
|
||||
*/
|
||||
UnicodeString toString(UErrorCode& status) const U_OVERRIDE;
|
||||
|
||||
// Copydoc: this method is new in ICU 64
|
||||
/** @copydoc FormattedValue::toTempString() */
|
||||
UnicodeString toTempString(UErrorCode& status) const U_OVERRIDE;
|
||||
|
||||
// Copybrief: this method is older than the parent method
|
||||
/**
|
||||
* @copybrief FormattedValue::appendTo()
|
||||
*
|
||||
* For more information, see FormattedValue::appendTo()
|
||||
*
|
||||
* @stable ICU 62
|
||||
*/
|
||||
Appendable &appendTo(Appendable& appendable, UErrorCode& status) const U_OVERRIDE;
|
||||
|
||||
// Copydoc: this method is new in ICU 64
|
||||
/** @copydoc FormattedValue::nextPosition() */
|
||||
UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Export the formatted number as a "numeric string" conforming to the
|
||||
* syntax defined in the Decimal Arithmetic Specification, available at
|
||||
* http://speleotrove.com/decimal
|
||||
*
|
||||
* This endpoint is useful for obtaining the exact number being printed
|
||||
* after scaling and rounding have been applied by the number formatter.
|
||||
*
|
||||
* Example call site:
|
||||
*
|
||||
* auto decimalNumber = fn.toDecimalNumber<std::string>(status);
|
||||
*
|
||||
* @tparam StringClass A string class compatible with StringByteSink;
|
||||
* for example, std::string.
|
||||
* @param status Set if an error occurs.
|
||||
* @return A StringClass containing the numeric string.
|
||||
* @stable ICU 65
|
||||
*/
|
||||
template<typename StringClass>
|
||||
inline StringClass toDecimalNumber(UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Gets the resolved output unit.
|
||||
*
|
||||
* The output unit is dependent upon the localized preferences for the usage
|
||||
* specified via NumberFormatterSettings::usage(), and may be a unit with
|
||||
* UMEASURE_UNIT_MIXED unit complexity (MeasureUnit::getComplexity()), such
|
||||
* as "foot-and-inch" or "hour-and-minute-and-second".
|
||||
*
|
||||
* @return `MeasureUnit`.
|
||||
* @stable ICU 68
|
||||
*/
|
||||
MeasureUnit getOutputUnit(UErrorCode& status) const;
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
|
||||
/**
|
||||
* Gets the noun class of the formatted output. Returns `UNDEFINED` when the noun class
|
||||
* is not supported yet.
|
||||
*
|
||||
* @return UDisplayOptionsNounClass
|
||||
* @draft ICU 72
|
||||
*/
|
||||
UDisplayOptionsNounClass getNounClass(UErrorCode &status) const;
|
||||
|
||||
#endif // U_HIDE_DRAFT_API
|
||||
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
|
||||
/**
|
||||
* Gets the raw DecimalQuantity for plural rule selection.
|
||||
* @internal
|
||||
*/
|
||||
void getDecimalQuantity(impl::DecimalQuantity& output, UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Populates the mutable builder type FieldPositionIteratorHandler.
|
||||
* @internal
|
||||
*/
|
||||
void getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const;
|
||||
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
|
||||
private:
|
||||
// Can't use LocalPointer because UFormattedNumberData is forward-declared
|
||||
impl::UFormattedNumberData *fData;
|
||||
|
||||
// Error code for the terminal methods
|
||||
UErrorCode fErrorCode;
|
||||
|
||||
/**
|
||||
* Internal constructor from data type. Adopts the data pointer.
|
||||
* @internal (private)
|
||||
*/
|
||||
explicit FormattedNumber(impl::UFormattedNumberData *results)
|
||||
: fData(results), fErrorCode(U_ZERO_ERROR) {}
|
||||
|
||||
explicit FormattedNumber(UErrorCode errorCode)
|
||||
: fData(nullptr), fErrorCode(errorCode) {}
|
||||
|
||||
void toDecimalNumber(ByteSink& sink, UErrorCode& status) const;
|
||||
|
||||
// To give LocalizedNumberFormatter format methods access to this class's constructor:
|
||||
friend class LocalizedNumberFormatter;
|
||||
friend class SimpleNumberFormatter;
|
||||
|
||||
// To give C API access to internals
|
||||
friend struct impl::UFormattedNumberImpl;
|
||||
};
|
||||
|
||||
template<typename StringClass>
|
||||
StringClass FormattedNumber::toDecimalNumber(UErrorCode& status) const {
|
||||
StringClass result;
|
||||
StringByteSink<StringClass> sink(&result);
|
||||
toDecimalNumber(sink, status);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace number
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
||||
#endif /* U_SHOW_CPLUSPLUS_API */
|
||||
|
||||
#endif // __FORMATTEDNUMBER_H__
|
||||
|
|
@ -16,17 +16,17 @@
|
|||
#include "unicode/dcfmtsym.h"
|
||||
#include "unicode/displayoptions.h"
|
||||
#include "unicode/fieldpos.h"
|
||||
#include "unicode/formattedvalue.h"
|
||||
#include "unicode/fpositer.h"
|
||||
#include "unicode/measunit.h"
|
||||
#include "unicode/nounit.h"
|
||||
#include "unicode/parseerr.h"
|
||||
#include "unicode/plurrule.h"
|
||||
#include "unicode/ucurr.h"
|
||||
#include "unicode/udisplayoptions.h"
|
||||
#include "unicode/unum.h"
|
||||
#include "unicode/unumberformatter.h"
|
||||
#include "unicode/uobject.h"
|
||||
#include "unicode/unumberoptions.h"
|
||||
#include "unicode/formattednumber.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
|
@ -112,6 +112,7 @@ namespace number { // icu::number
|
|||
// Forward declarations:
|
||||
class UnlocalizedNumberFormatter;
|
||||
class LocalizedNumberFormatter;
|
||||
class SimpleNumberFormatter;
|
||||
class FormattedNumber;
|
||||
class Notation;
|
||||
class ScientificNotation;
|
||||
|
@ -166,6 +167,8 @@ struct UFormattedNumberImpl;
|
|||
class MutablePatternModifier;
|
||||
class ImmutablePatternModifier;
|
||||
struct DecimalFormatWarehouse;
|
||||
struct SimpleMicroProps;
|
||||
class AdoptingSignumModifierStore;
|
||||
|
||||
/**
|
||||
* Used for NumberRangeFormatter and implemented in numrange_fluent.cpp.
|
||||
|
@ -1436,9 +1439,11 @@ class U_I18N_API Grouper : public UMemory {
|
|||
// To allow MacroProps/MicroProps to initialize empty instances:
|
||||
friend struct MacroProps;
|
||||
friend struct MicroProps;
|
||||
friend struct SimpleMicroProps;
|
||||
|
||||
// To allow NumberFormatterImpl to access isBogus() and perform other operations:
|
||||
friend class NumberFormatterImpl;
|
||||
friend class ::icu::number::SimpleNumberFormatter;
|
||||
|
||||
// To allow NumberParserImpl to perform setLocaleData():
|
||||
friend class ::icu::numparse::impl::NumberParserImpl;
|
||||
|
@ -2692,173 +2697,6 @@ class U_I18N_API LocalizedNumberFormatter
|
|||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The result of a number formatting operation. This class allows the result to be exported in several data types,
|
||||
* including a UnicodeString and a FieldPositionIterator.
|
||||
*
|
||||
* Instances of this class are immutable and thread-safe.
|
||||
*
|
||||
* @stable ICU 60
|
||||
*/
|
||||
class U_I18N_API FormattedNumber : public UMemory, public FormattedValue {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default constructor; makes an empty FormattedNumber.
|
||||
* @stable ICU 64
|
||||
*/
|
||||
FormattedNumber()
|
||||
: fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {}
|
||||
|
||||
/**
|
||||
* Move constructor: Leaves the source FormattedNumber in an undefined state.
|
||||
* @stable ICU 62
|
||||
*/
|
||||
FormattedNumber(FormattedNumber&& src) U_NOEXCEPT;
|
||||
|
||||
/**
|
||||
* Destruct an instance of FormattedNumber.
|
||||
* @stable ICU 60
|
||||
*/
|
||||
virtual ~FormattedNumber() U_OVERRIDE;
|
||||
|
||||
/** Copying not supported; use move constructor instead. */
|
||||
FormattedNumber(const FormattedNumber&) = delete;
|
||||
|
||||
/** Copying not supported; use move assignment instead. */
|
||||
FormattedNumber& operator=(const FormattedNumber&) = delete;
|
||||
|
||||
/**
|
||||
* Move assignment: Leaves the source FormattedNumber in an undefined state.
|
||||
* @stable ICU 62
|
||||
*/
|
||||
FormattedNumber& operator=(FormattedNumber&& src) U_NOEXCEPT;
|
||||
|
||||
// Copybrief: this method is older than the parent method
|
||||
/**
|
||||
* @copybrief FormattedValue::toString()
|
||||
*
|
||||
* For more information, see FormattedValue::toString()
|
||||
*
|
||||
* @stable ICU 62
|
||||
*/
|
||||
UnicodeString toString(UErrorCode& status) const U_OVERRIDE;
|
||||
|
||||
// Copydoc: this method is new in ICU 64
|
||||
/** @copydoc FormattedValue::toTempString() */
|
||||
UnicodeString toTempString(UErrorCode& status) const U_OVERRIDE;
|
||||
|
||||
// Copybrief: this method is older than the parent method
|
||||
/**
|
||||
* @copybrief FormattedValue::appendTo()
|
||||
*
|
||||
* For more information, see FormattedValue::appendTo()
|
||||
*
|
||||
* @stable ICU 62
|
||||
*/
|
||||
Appendable &appendTo(Appendable& appendable, UErrorCode& status) const U_OVERRIDE;
|
||||
|
||||
// Copydoc: this method is new in ICU 64
|
||||
/** @copydoc FormattedValue::nextPosition() */
|
||||
UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Export the formatted number as a "numeric string" conforming to the
|
||||
* syntax defined in the Decimal Arithmetic Specification, available at
|
||||
* http://speleotrove.com/decimal
|
||||
*
|
||||
* This endpoint is useful for obtaining the exact number being printed
|
||||
* after scaling and rounding have been applied by the number formatter.
|
||||
*
|
||||
* Example call site:
|
||||
*
|
||||
* auto decimalNumber = fn.toDecimalNumber<std::string>(status);
|
||||
*
|
||||
* @tparam StringClass A string class compatible with StringByteSink;
|
||||
* for example, std::string.
|
||||
* @param status Set if an error occurs.
|
||||
* @return A StringClass containing the numeric string.
|
||||
* @stable ICU 65
|
||||
*/
|
||||
template<typename StringClass>
|
||||
inline StringClass toDecimalNumber(UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Gets the resolved output unit.
|
||||
*
|
||||
* The output unit is dependent upon the localized preferences for the usage
|
||||
* specified via NumberFormatterSettings::usage(), and may be a unit with
|
||||
* UMEASURE_UNIT_MIXED unit complexity (MeasureUnit::getComplexity()), such
|
||||
* as "foot-and-inch" or "hour-and-minute-and-second".
|
||||
*
|
||||
* @return `MeasureUnit`.
|
||||
* @stable ICU 68
|
||||
*/
|
||||
MeasureUnit getOutputUnit(UErrorCode& status) const;
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
|
||||
/**
|
||||
* Gets the noun class of the formatted output. Returns `UNDEFINED` when the noun class
|
||||
* is not supported yet.
|
||||
*
|
||||
* @return UDisplayOptionsNounClass
|
||||
* @draft ICU 72
|
||||
*/
|
||||
UDisplayOptionsNounClass getNounClass(UErrorCode &status) const;
|
||||
|
||||
#endif // U_HIDE_DRAFT_API
|
||||
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
|
||||
/**
|
||||
* Gets the raw DecimalQuantity for plural rule selection.
|
||||
* @internal
|
||||
*/
|
||||
void getDecimalQuantity(impl::DecimalQuantity& output, UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Populates the mutable builder type FieldPositionIteratorHandler.
|
||||
* @internal
|
||||
*/
|
||||
void getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const;
|
||||
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
|
||||
private:
|
||||
// Can't use LocalPointer because UFormattedNumberData is forward-declared
|
||||
const impl::UFormattedNumberData *fData;
|
||||
|
||||
// Error code for the terminal methods
|
||||
UErrorCode fErrorCode;
|
||||
|
||||
/**
|
||||
* Internal constructor from data type. Adopts the data pointer.
|
||||
* @internal (private)
|
||||
*/
|
||||
explicit FormattedNumber(impl::UFormattedNumberData *results)
|
||||
: fData(results), fErrorCode(U_ZERO_ERROR) {}
|
||||
|
||||
explicit FormattedNumber(UErrorCode errorCode)
|
||||
: fData(nullptr), fErrorCode(errorCode) {}
|
||||
|
||||
void toDecimalNumber(ByteSink& sink, UErrorCode& status) const;
|
||||
|
||||
// To give LocalizedNumberFormatter format methods access to this class's constructor:
|
||||
friend class LocalizedNumberFormatter;
|
||||
|
||||
// To give C API access to internals
|
||||
friend struct impl::UFormattedNumberImpl;
|
||||
};
|
||||
|
||||
template<typename StringClass>
|
||||
StringClass FormattedNumber::toDecimalNumber(UErrorCode& status) const {
|
||||
StringClass result;
|
||||
StringByteSink<StringClass> sink(&result);
|
||||
toDecimalNumber(sink, status);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* See the main description in numberformatter.h for documentation and examples.
|
||||
*
|
||||
|
|
329
icu4c/source/i18n/unicode/simplenumberformatter.h
Normal file
329
icu4c/source/i18n/unicode/simplenumberformatter.h
Normal file
|
@ -0,0 +1,329 @@
|
|||
// © 2022 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html
|
||||
|
||||
#ifndef __SIMPLENUMBERFORMATTERH__
|
||||
#define __SIMPLENUMBERFORMATTERH__
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if U_SHOW_CPLUSPLUS_API
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/dcfmtsym.h"
|
||||
#include "unicode/usimplenumberformatter.h"
|
||||
#include "unicode/formattednumber.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief C++ API: Simple number formatting focused on low memory and code size.
|
||||
*
|
||||
* These functions render locale-aware number strings but without the bells and whistles found in
|
||||
* other number formatting APIs such as those in numberformatter.h, like units and currencies.
|
||||
*
|
||||
* <pre>
|
||||
* SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("de-CH", status);
|
||||
* FormattedNumber result = snf.formatInt64(-1000007, status);
|
||||
* assertEquals("", u"-1’000’007", result.toString(status));
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
namespace number { // icu::number
|
||||
|
||||
|
||||
namespace impl {
|
||||
class UFormattedNumberData;
|
||||
struct SimpleMicroProps;
|
||||
class AdoptingSignumModifierStore;
|
||||
} // icu::number::impl
|
||||
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
|
||||
|
||||
/**
|
||||
* An input type for SimpleNumberFormatter.
|
||||
*
|
||||
* This class is mutable and not intended for public subclassing. This class is movable but not copyable.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
class U_I18N_API SimpleNumber : public UMemory {
|
||||
public:
|
||||
/**
|
||||
* Creates a SimpleNumber for an integer.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
static SimpleNumber forInt64(int64_t value, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Changes the value of the SimpleNumber by a power of 10.
|
||||
*
|
||||
* This function immediately mutates the inner value.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
void multiplyByPowerOfTen(int32_t power, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Rounds the value currently stored in the SimpleNumber to the given power of 10.
|
||||
*
|
||||
* This function immediately mutates the inner value.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
void roundTo(int32_t power, UNumberFormatRoundingMode roundingMode, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Truncates the most significant digits to the given maximum number of integer digits.
|
||||
*
|
||||
* This function immediately mutates the inner value.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
void truncateStart(uint32_t maximumIntegerDigits, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Pads the beginning of the number with zeros up to the given minimum number of integer digits.
|
||||
*
|
||||
* This setting is applied upon formatting the number.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
void setMinimumIntegerDigits(uint32_t minimumIntegerDigits, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Pads the end of the number with zeros up to the given minimum number of fraction digits.
|
||||
*
|
||||
* This setting is applied upon formatting the number.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
void setMinimumFractionDigits(uint32_t minimumFractionDigits, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Sets the sign of the number: an explicit plus sign, explicit minus sign, or no sign.
|
||||
*
|
||||
* This setting is applied upon formatting the number.
|
||||
*
|
||||
* NOTE: This does not support accounting sign notation.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
void setSign(USimpleNumberSign sign, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Creates a new, empty SimpleNumber that does not contain a value.
|
||||
*
|
||||
* NOTE: This number will fail to format; use forInt64() to create a SimpleNumber with a value.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
SimpleNumber() = default;
|
||||
|
||||
/**
|
||||
* Destruct this SimpleNumber, cleaning up any memory it might own.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
~SimpleNumber() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* SimpleNumber move constructor.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
SimpleNumber(SimpleNumber&& other) U_NOEXCEPT {
|
||||
fData = other.fData;
|
||||
fSign = other.fSign;
|
||||
other.fData = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* SimpleNumber move assignment.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
SimpleNumber& operator=(SimpleNumber&& other) U_NOEXCEPT {
|
||||
cleanup();
|
||||
fData = other.fData;
|
||||
fSign = other.fSign;
|
||||
other.fData = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
SimpleNumber(impl::UFormattedNumberData* data, UErrorCode& status);
|
||||
SimpleNumber(const SimpleNumber&) = delete;
|
||||
SimpleNumber& operator=(const SimpleNumber&) = delete;
|
||||
|
||||
void cleanup();
|
||||
|
||||
impl::UFormattedNumberData* fData = nullptr;
|
||||
USimpleNumberSign fSign = UNUM_SIMPLE_NUMBER_NO_SIGN;
|
||||
|
||||
friend class SimpleNumberFormatter;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A special NumberFormatter focused on smaller binary size and memory use.
|
||||
*
|
||||
* SimpleNumberFormatter is capable of basic number formatting, including grouping separators,
|
||||
* sign display, and rounding. It is not capable of currencies, compact notation, or units.
|
||||
*
|
||||
* This class is immutable and not intended for public subclassing. This class is movable but not copyable.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
class U_I18N_API SimpleNumberFormatter : public UMemory {
|
||||
public:
|
||||
/**
|
||||
* Creates a new SimpleNumberFormatter with all locale defaults.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
static SimpleNumberFormatter forLocale(
|
||||
const icu::Locale &locale,
|
||||
UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Creates a new SimpleNumberFormatter, overriding the grouping strategy.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
static SimpleNumberFormatter forLocaleAndGroupingStrategy(
|
||||
const icu::Locale &locale,
|
||||
UNumberGroupingStrategy groupingStrategy,
|
||||
UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Creates a new SimpleNumberFormatter, overriding the grouping strategy and symbols.
|
||||
*
|
||||
* IMPORTANT: For efficiency, this function borrows the symbols. The symbols MUST remain valid
|
||||
* for the lifetime of the SimpleNumberFormatter.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
static SimpleNumberFormatter forLocaleAndSymbolsAndGroupingStrategy(
|
||||
const icu::Locale &locale,
|
||||
const DecimalFormatSymbols &symbols,
|
||||
UNumberGroupingStrategy groupingStrategy,
|
||||
UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Formats a value using this SimpleNumberFormatter.
|
||||
*
|
||||
* The SimpleNumber argument is "consumed". A new SimpleNumber object should be created for
|
||||
* every formatting operation.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
FormattedNumber format(SimpleNumber value, UErrorCode &status) const;
|
||||
|
||||
/**
|
||||
* Formats an integer using this SimpleNumberFormatter.
|
||||
*
|
||||
* For more control over the formatting, use SimpleNumber.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
FormattedNumber formatInt64(int64_t value, UErrorCode &status) const {
|
||||
return format(SimpleNumber::forInt64(value, status), status);
|
||||
}
|
||||
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
/**
|
||||
* Run the formatter with the internal types.
|
||||
* @internal
|
||||
*/
|
||||
void formatImpl(impl::UFormattedNumberData* data, USimpleNumberSign sign, UErrorCode& status) const;
|
||||
#endif // U_HIDE_INTERNAL_API
|
||||
|
||||
/**
|
||||
* Destruct this SimpleNumberFormatter, cleaning up any memory it might own.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
~SimpleNumberFormatter() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a shell, initialized but non-functional SimpleNumberFormatter.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
SimpleNumberFormatter() = default;
|
||||
|
||||
/**
|
||||
* SimpleNumberFormatter: Move constructor.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
SimpleNumberFormatter(SimpleNumberFormatter&& other) U_NOEXCEPT {
|
||||
fGroupingStrategy = other.fGroupingStrategy;
|
||||
fOwnedSymbols = other.fOwnedSymbols;
|
||||
fMicros = other.fMicros;
|
||||
fPatternModifier = other.fPatternModifier;
|
||||
other.fOwnedSymbols = nullptr;
|
||||
other.fMicros = nullptr;
|
||||
other.fPatternModifier = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* SimpleNumberFormatter: Move assignment.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
SimpleNumberFormatter& operator=(SimpleNumberFormatter&& other) U_NOEXCEPT {
|
||||
cleanup();
|
||||
fGroupingStrategy = other.fGroupingStrategy;
|
||||
fOwnedSymbols = other.fOwnedSymbols;
|
||||
fMicros = other.fMicros;
|
||||
fPatternModifier = other.fPatternModifier;
|
||||
other.fOwnedSymbols = nullptr;
|
||||
other.fMicros = nullptr;
|
||||
other.fPatternModifier = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void initialize(
|
||||
const icu::Locale &locale,
|
||||
const DecimalFormatSymbols &symbols,
|
||||
UNumberGroupingStrategy groupingStrategy,
|
||||
UErrorCode &status);
|
||||
|
||||
void cleanup();
|
||||
|
||||
SimpleNumberFormatter(const SimpleNumberFormatter&) = delete;
|
||||
|
||||
SimpleNumberFormatter& operator=(const SimpleNumberFormatter&) = delete;
|
||||
|
||||
UNumberGroupingStrategy fGroupingStrategy = UNUM_GROUPING_AUTO;
|
||||
|
||||
// Owned Pointers:
|
||||
DecimalFormatSymbols* fOwnedSymbols = nullptr; // can be empty
|
||||
impl::SimpleMicroProps* fMicros = nullptr;
|
||||
impl::AdoptingSignumModifierStore* fPatternModifier = nullptr;
|
||||
};
|
||||
|
||||
|
||||
#endif // U_HIDE_DRAFT_API
|
||||
|
||||
} // namespace number
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
||||
#endif /* U_SHOW_CPLUSPLUS_API */
|
||||
|
||||
#endif // __SIMPLENUMBERFORMATTERH__
|
||||
|
224
icu4c/source/i18n/unicode/uformattednumber.h
Normal file
224
icu4c/source/i18n/unicode/uformattednumber.h
Normal file
|
@ -0,0 +1,224 @@
|
|||
// © 2022 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html
|
||||
|
||||
#ifndef __UFORMATTEDNUMBER_H__
|
||||
#define __UFORMATTEDNUMBER_H__
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/ufieldpositer.h"
|
||||
#include "unicode/uformattedvalue.h"
|
||||
#include "unicode/umisc.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief C API: Formatted number result from various number formatting functions.
|
||||
*
|
||||
* Create a `UFormattedNumber` to hold the result of a number formatting operation. The same
|
||||
* `UFormattedNumber` can be reused multiple times.
|
||||
*
|
||||
* <pre>
|
||||
* LocalUFormattedNumberPointer uresult(unumf_openResult(status));
|
||||
*
|
||||
* // pass uresult.getAlias() to your number formatter
|
||||
*
|
||||
* int32_t length;
|
||||
* const UChar* s = ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), &length, status));
|
||||
*
|
||||
* // The string result is in `s` with the given `length` (it is also NUL-terminated).
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
|
||||
struct UFormattedNumber;
|
||||
/**
|
||||
* C-compatible version of icu::number::FormattedNumber.
|
||||
*
|
||||
* NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead.
|
||||
*
|
||||
* @stable ICU 62
|
||||
*/
|
||||
typedef struct UFormattedNumber UFormattedNumber;
|
||||
|
||||
|
||||
/**
|
||||
* Creates an object to hold the result of a UNumberFormatter
|
||||
* operation. The object can be used repeatedly; it is cleared whenever
|
||||
* passed to a format function.
|
||||
*
|
||||
* @param ec Set if an error occurs.
|
||||
* @stable ICU 62
|
||||
*/
|
||||
U_CAPI UFormattedNumber* U_EXPORT2
|
||||
unumf_openResult(UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a representation of a UFormattedNumber as a UFormattedValue,
|
||||
* which can be subsequently passed to any API requiring that type.
|
||||
*
|
||||
* The returned object is owned by the UFormattedNumber and is valid
|
||||
* only as long as the UFormattedNumber is present and unchanged in memory.
|
||||
*
|
||||
* You can think of this method as a cast between types.
|
||||
*
|
||||
* @param uresult The object containing the formatted string.
|
||||
* @param ec Set if an error occurs.
|
||||
* @return A UFormattedValue owned by the input object.
|
||||
* @stable ICU 64
|
||||
*/
|
||||
U_CAPI const UFormattedValue* U_EXPORT2
|
||||
unumf_resultAsValue(const UFormattedNumber* uresult, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Extracts the result number string out of a UFormattedNumber to a UChar buffer if possible.
|
||||
* If bufferCapacity is greater than the required length, a terminating NUL is written.
|
||||
* If bufferCapacity is less than the required length, an error code is set.
|
||||
*
|
||||
* Also see ufmtval_getString, which returns a NUL-terminated string:
|
||||
*
|
||||
* int32_t len;
|
||||
* const UChar* str = ufmtval_getString(unumf_resultAsValue(uresult, &ec), &len, &ec);
|
||||
*
|
||||
* NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead.
|
||||
*
|
||||
* @param uresult The object containing the formatted number.
|
||||
* @param buffer Where to save the string output.
|
||||
* @param bufferCapacity The number of UChars available in the buffer.
|
||||
* @param ec Set if an error occurs.
|
||||
* @return The required length.
|
||||
* @stable ICU 62
|
||||
*/
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t bufferCapacity,
|
||||
UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the start and end indices of the next occurrence of the given <em>field</em> in the
|
||||
* output string. This allows you to determine the locations of, for example, the integer part,
|
||||
* fraction part, or symbols.
|
||||
*
|
||||
* This is a simpler but less powerful alternative to {@link ufmtval_nextPosition}.
|
||||
*
|
||||
* If a field occurs just once, calling this method will find that occurrence and return it. If a
|
||||
* field occurs multiple times, this method may be called repeatedly with the following pattern:
|
||||
*
|
||||
* <pre>
|
||||
* UFieldPosition ufpos = {UNUM_GROUPING_SEPARATOR_FIELD, 0, 0};
|
||||
* while (unumf_resultNextFieldPosition(uresult, ufpos, &ec)) {
|
||||
* // do something with ufpos.
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* This method is useful if you know which field to query. If you want all available field position
|
||||
* information, use unumf_resultGetAllFieldPositions().
|
||||
*
|
||||
* NOTE: All fields of the UFieldPosition must be initialized before calling this method.
|
||||
*
|
||||
* @param uresult The object containing the formatted number.
|
||||
* @param ufpos
|
||||
* Input+output variable. On input, the "field" property determines which field to look up,
|
||||
* and the "endIndex" property determines where to begin the search. On output, the
|
||||
* "beginIndex" field is set to the beginning of the first occurrence of the field after the
|
||||
* input "endIndex", and "endIndex" is set to the end of that occurrence of the field
|
||||
* (exclusive index). If a field position is not found, the FieldPosition is not changed and
|
||||
* the method returns false.
|
||||
* @param ec Set if an error occurs.
|
||||
* @stable ICU 62
|
||||
*/
|
||||
U_CAPI UBool U_EXPORT2
|
||||
unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* ufpos, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Populates the given iterator with all fields in the formatted output string. This allows you to
|
||||
* determine the locations of the integer part, fraction part, and sign.
|
||||
*
|
||||
* This is an alternative to the more powerful {@link ufmtval_nextPosition} API.
|
||||
*
|
||||
* If you need information on only one field, use {@link ufmtval_nextPosition} or
|
||||
* {@link unumf_resultNextFieldPosition}.
|
||||
*
|
||||
* @param uresult The object containing the formatted number.
|
||||
* @param ufpositer
|
||||
* A pointer to a UFieldPositionIterator created by {@link #ufieldpositer_open}. Iteration
|
||||
* information already present in the UFieldPositionIterator is deleted, and the iterator is reset
|
||||
* to apply to the fields in the formatted string created by this function call. The field values
|
||||
* and indexes returned by {@link #ufieldpositer_next} represent fields denoted by
|
||||
* the UNumberFormatFields enum. Fields are not returned in a guaranteed order. Fields cannot
|
||||
* overlap, but they may nest. For example, 1234 could format as "1,234" which might consist of a
|
||||
* grouping separator field for ',' and an integer field encompassing the entire string.
|
||||
* @param ec Set if an error occurs.
|
||||
* @stable ICU 62
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer,
|
||||
UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Extracts the formatted number as a "numeric string" conforming to the
|
||||
* syntax defined in the Decimal Arithmetic Specification, available at
|
||||
* http://speleotrove.com/decimal
|
||||
*
|
||||
* This endpoint is useful for obtaining the exact number being printed
|
||||
* after scaling and rounding have been applied by the number formatter.
|
||||
*
|
||||
* @param uresult The input object containing the formatted number.
|
||||
* @param dest the 8-bit char buffer into which the decimal number is placed
|
||||
* @param destCapacity The size, in chars, of the destination buffer. May be zero
|
||||
* for precomputing the required size.
|
||||
* @param ec receives any error status.
|
||||
* If U_BUFFER_OVERFLOW_ERROR: Returns number of chars for
|
||||
* preflighting.
|
||||
* @return Number of chars in the data. Does not include a trailing NUL.
|
||||
* @stable ICU 68
|
||||
*/
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
unumf_resultToDecimalNumber(
|
||||
const UFormattedNumber* uresult,
|
||||
char* dest,
|
||||
int32_t destCapacity,
|
||||
UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Releases the UFormattedNumber created by unumf_openResult().
|
||||
*
|
||||
* @param uresult An object created by unumf_openResult().
|
||||
* @stable ICU 62
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
unumf_closeResult(UFormattedNumber* uresult);
|
||||
|
||||
|
||||
#if U_SHOW_CPLUSPLUS_API
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \class LocalUFormattedNumberPointer
|
||||
* "Smart pointer" class; closes a UFormattedNumber via unumf_closeResult().
|
||||
* For most methods see the LocalPointerBase base class.
|
||||
*
|
||||
* Usage:
|
||||
* <pre>
|
||||
* LocalUFormattedNumberPointer uformatter(unumf_openResult(...));
|
||||
* // no need to explicitly call unumf_closeResult()
|
||||
* </pre>
|
||||
*
|
||||
* @see LocalPointerBase
|
||||
* @see LocalPointer
|
||||
* @stable ICU 62
|
||||
*/
|
||||
U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedNumberPointer, UFormattedNumber, unumf_closeResult);
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif // U_SHOW_CPLUSPLUS_API
|
||||
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
#endif //__UFORMATTEDNUMBER_H__
|
|
@ -25,6 +25,7 @@
|
|||
#include "unicode/uformattable.h"
|
||||
#include "unicode/udisplaycontext.h"
|
||||
#include "unicode/ufieldpositer.h"
|
||||
#include "unicode/unumberoptions.h"
|
||||
|
||||
#if U_SHOW_CPLUSPLUS_API
|
||||
#include "unicode/localpointer.h"
|
||||
|
@ -271,55 +272,6 @@ typedef enum UNumberFormatStyle {
|
|||
UNUM_IGNORE = UNUM_PATTERN_DECIMAL
|
||||
} UNumberFormatStyle;
|
||||
|
||||
/** The possible number format rounding modes.
|
||||
*
|
||||
* <p>
|
||||
* For more detail on rounding modes, see:
|
||||
* https://unicode-org.github.io/icu/userguide/format_parse/numbers/rounding-modes
|
||||
*
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
typedef enum UNumberFormatRoundingMode {
|
||||
UNUM_ROUND_CEILING,
|
||||
UNUM_ROUND_FLOOR,
|
||||
UNUM_ROUND_DOWN,
|
||||
UNUM_ROUND_UP,
|
||||
/**
|
||||
* Half-even rounding
|
||||
* @stable, ICU 3.8
|
||||
*/
|
||||
UNUM_ROUND_HALFEVEN,
|
||||
#ifndef U_HIDE_DEPRECATED_API
|
||||
/**
|
||||
* Half-even rounding, misspelled name
|
||||
* @deprecated, ICU 3.8
|
||||
*/
|
||||
UNUM_FOUND_HALFEVEN = UNUM_ROUND_HALFEVEN,
|
||||
#endif /* U_HIDE_DEPRECATED_API */
|
||||
UNUM_ROUND_HALFDOWN = UNUM_ROUND_HALFEVEN + 1,
|
||||
UNUM_ROUND_HALFUP,
|
||||
/**
|
||||
* ROUND_UNNECESSARY reports an error if formatted result is not exact.
|
||||
* @stable ICU 4.8
|
||||
*/
|
||||
UNUM_ROUND_UNNECESSARY,
|
||||
/**
|
||||
* Rounds ties toward the odd number.
|
||||
* @stable ICU 69
|
||||
*/
|
||||
UNUM_ROUND_HALF_ODD,
|
||||
/**
|
||||
* Rounds ties toward +∞.
|
||||
* @stable ICU 69
|
||||
*/
|
||||
UNUM_ROUND_HALF_CEILING,
|
||||
/**
|
||||
* Rounds ties toward -∞.
|
||||
* @stable ICU 69
|
||||
*/
|
||||
UNUM_ROUND_HALF_FLOOR,
|
||||
} UNumberFormatRoundingMode;
|
||||
|
||||
/** The possible number format pad positions.
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
|
|
|
@ -9,9 +9,8 @@
|
|||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/parseerr.h"
|
||||
#include "unicode/ufieldpositer.h"
|
||||
#include "unicode/umisc.h"
|
||||
#include "unicode/uformattedvalue.h"
|
||||
#include "unicode/unumberoptions.h"
|
||||
#include "unicode/uformattednumber.h"
|
||||
|
||||
|
||||
/**
|
||||
|
@ -243,107 +242,6 @@ typedef enum UNumberUnitWidth {
|
|||
UNUM_UNIT_WIDTH_COUNT = 7
|
||||
} UNumberUnitWidth;
|
||||
|
||||
/**
|
||||
* An enum declaring the strategy for when and how to display grouping separators (i.e., the
|
||||
* separator, often a comma or period, after every 2-3 powers of ten). The choices are several
|
||||
* pre-built strategies for different use cases that employ locale data whenever possible. Example
|
||||
* outputs for 1234 and 1234567 in <em>en-IN</em>:
|
||||
*
|
||||
* <ul>
|
||||
* <li>OFF: 1234 and 12345
|
||||
* <li>MIN2: 1234 and 12,34,567
|
||||
* <li>AUTO: 1,234 and 12,34,567
|
||||
* <li>ON_ALIGNED: 1,234 and 12,34,567
|
||||
* <li>THOUSANDS: 1,234 and 1,234,567
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* The default is AUTO, which displays grouping separators unless the locale data says that grouping
|
||||
* is not customary. To force grouping for all numbers greater than 1000 consistently across locales,
|
||||
* use ON_ALIGNED. On the other hand, to display grouping less frequently than the default, use MIN2
|
||||
* or OFF. See the docs of each option for details.
|
||||
*
|
||||
* <p>
|
||||
* Note: This enum specifies the strategy for grouping sizes. To set which character to use as the
|
||||
* grouping separator, use the "symbols" setter.
|
||||
*
|
||||
* @stable ICU 63
|
||||
*/
|
||||
typedef enum UNumberGroupingStrategy {
|
||||
/**
|
||||
* Do not display grouping separators in any locale.
|
||||
*
|
||||
* @stable ICU 61
|
||||
*/
|
||||
UNUM_GROUPING_OFF,
|
||||
|
||||
/**
|
||||
* Display grouping using locale defaults, except do not show grouping on values smaller than
|
||||
* 10000 (such that there is a <em>minimum of two digits</em> before the first separator).
|
||||
*
|
||||
* <p>
|
||||
* Note that locales may restrict grouping separators to be displayed only on 1 million or
|
||||
* greater (for example, ee and hu) or disable grouping altogether (for example, bg currency).
|
||||
*
|
||||
* <p>
|
||||
* Locale data is used to determine whether to separate larger numbers into groups of 2
|
||||
* (customary in South Asia) or groups of 3 (customary in Europe and the Americas).
|
||||
*
|
||||
* @stable ICU 61
|
||||
*/
|
||||
UNUM_GROUPING_MIN2,
|
||||
|
||||
/**
|
||||
* Display grouping using the default strategy for all locales. This is the default behavior.
|
||||
*
|
||||
* <p>
|
||||
* Note that locales may restrict grouping separators to be displayed only on 1 million or
|
||||
* greater (for example, ee and hu) or disable grouping altogether (for example, bg currency).
|
||||
*
|
||||
* <p>
|
||||
* Locale data is used to determine whether to separate larger numbers into groups of 2
|
||||
* (customary in South Asia) or groups of 3 (customary in Europe and the Americas).
|
||||
*
|
||||
* @stable ICU 61
|
||||
*/
|
||||
UNUM_GROUPING_AUTO,
|
||||
|
||||
/**
|
||||
* Always display the grouping separator on values of at least 1000.
|
||||
*
|
||||
* <p>
|
||||
* This option ignores the locale data that restricts or disables grouping, described in MIN2 and
|
||||
* AUTO. This option may be useful to normalize the alignment of numbers, such as in a
|
||||
* spreadsheet.
|
||||
*
|
||||
* <p>
|
||||
* Locale data is used to determine whether to separate larger numbers into groups of 2
|
||||
* (customary in South Asia) or groups of 3 (customary in Europe and the Americas).
|
||||
*
|
||||
* @stable ICU 61
|
||||
*/
|
||||
UNUM_GROUPING_ON_ALIGNED,
|
||||
|
||||
/**
|
||||
* Use the Western defaults: groups of 3 and enabled for all numbers 1000 or greater. Do not use
|
||||
* locale data for determining the grouping strategy.
|
||||
*
|
||||
* @stable ICU 61
|
||||
*/
|
||||
UNUM_GROUPING_THOUSANDS
|
||||
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
,
|
||||
/**
|
||||
* One more than the highest UNumberGroupingStrategy value.
|
||||
*
|
||||
* @internal ICU 62: The numeric value may change over time; see ICU ticket #12420.
|
||||
*/
|
||||
UNUM_GROUPING_COUNT
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
|
||||
} UNumberGroupingStrategy;
|
||||
|
||||
/**
|
||||
* An enum declaring how to denote positive and negative numbers. Example outputs when formatting
|
||||
* 123, 0, and -123 in <em>en-US</em>:
|
||||
|
@ -528,16 +426,6 @@ struct UNumberFormatter;
|
|||
*/
|
||||
typedef struct UNumberFormatter UNumberFormatter;
|
||||
|
||||
struct UFormattedNumber;
|
||||
/**
|
||||
* C-compatible version of icu::number::FormattedNumber.
|
||||
*
|
||||
* NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead.
|
||||
*
|
||||
* @stable ICU 62
|
||||
*/
|
||||
typedef struct UFormattedNumber UFormattedNumber;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new UNumberFormatter for the given skeleton string and locale. This is currently the only
|
||||
|
@ -584,17 +472,6 @@ unumf_openForSkeletonAndLocaleWithError(
|
|||
const UChar* skeleton, int32_t skeletonLen, const char* locale, UParseError* perror, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Creates an object to hold the result of a UNumberFormatter
|
||||
* operation. The object can be used repeatedly; it is cleared whenever
|
||||
* passed to a format function.
|
||||
*
|
||||
* @param ec Set if an error occurs.
|
||||
* @stable ICU 62
|
||||
*/
|
||||
U_CAPI UFormattedNumber* U_EXPORT2
|
||||
unumf_openResult(UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Uses a UNumberFormatter to format an integer to a UFormattedNumber. A string, field position, and other
|
||||
|
@ -659,135 +536,6 @@ U_CAPI void U_EXPORT2
|
|||
unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen,
|
||||
UFormattedNumber* uresult, UErrorCode* ec);
|
||||
|
||||
/**
|
||||
* Returns a representation of a UFormattedNumber as a UFormattedValue,
|
||||
* which can be subsequently passed to any API requiring that type.
|
||||
*
|
||||
* The returned object is owned by the UFormattedNumber and is valid
|
||||
* only as long as the UFormattedNumber is present and unchanged in memory.
|
||||
*
|
||||
* You can think of this method as a cast between types.
|
||||
*
|
||||
* @param uresult The object containing the formatted string.
|
||||
* @param ec Set if an error occurs.
|
||||
* @return A UFormattedValue owned by the input object.
|
||||
* @stable ICU 64
|
||||
*/
|
||||
U_CAPI const UFormattedValue* U_EXPORT2
|
||||
unumf_resultAsValue(const UFormattedNumber* uresult, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Extracts the result number string out of a UFormattedNumber to a UChar buffer if possible.
|
||||
* If bufferCapacity is greater than the required length, a terminating NUL is written.
|
||||
* If bufferCapacity is less than the required length, an error code is set.
|
||||
*
|
||||
* Also see ufmtval_getString, which returns a NUL-terminated string:
|
||||
*
|
||||
* int32_t len;
|
||||
* const UChar* str = ufmtval_getString(unumf_resultAsValue(uresult, &ec), &len, &ec);
|
||||
*
|
||||
* NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead.
|
||||
*
|
||||
* @param uresult The object containing the formatted number.
|
||||
* @param buffer Where to save the string output.
|
||||
* @param bufferCapacity The number of UChars available in the buffer.
|
||||
* @param ec Set if an error occurs.
|
||||
* @return The required length.
|
||||
* @stable ICU 62
|
||||
*/
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t bufferCapacity,
|
||||
UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the start and end indices of the next occurrence of the given <em>field</em> in the
|
||||
* output string. This allows you to determine the locations of, for example, the integer part,
|
||||
* fraction part, or symbols.
|
||||
*
|
||||
* This is a simpler but less powerful alternative to {@link ufmtval_nextPosition}.
|
||||
*
|
||||
* If a field occurs just once, calling this method will find that occurrence and return it. If a
|
||||
* field occurs multiple times, this method may be called repeatedly with the following pattern:
|
||||
*
|
||||
* <pre>
|
||||
* UFieldPosition ufpos = {UNUM_GROUPING_SEPARATOR_FIELD, 0, 0};
|
||||
* while (unumf_resultNextFieldPosition(uresult, ufpos, &ec)) {
|
||||
* // do something with ufpos.
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* This method is useful if you know which field to query. If you want all available field position
|
||||
* information, use unumf_resultGetAllFieldPositions().
|
||||
*
|
||||
* NOTE: All fields of the UFieldPosition must be initialized before calling this method.
|
||||
*
|
||||
* @param uresult The object containing the formatted number.
|
||||
* @param ufpos
|
||||
* Input+output variable. On input, the "field" property determines which field to look up,
|
||||
* and the "endIndex" property determines where to begin the search. On output, the
|
||||
* "beginIndex" field is set to the beginning of the first occurrence of the field after the
|
||||
* input "endIndex", and "endIndex" is set to the end of that occurrence of the field
|
||||
* (exclusive index). If a field position is not found, the FieldPosition is not changed and
|
||||
* the method returns false.
|
||||
* @param ec Set if an error occurs.
|
||||
* @stable ICU 62
|
||||
*/
|
||||
U_CAPI UBool U_EXPORT2
|
||||
unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* ufpos, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Populates the given iterator with all fields in the formatted output string. This allows you to
|
||||
* determine the locations of the integer part, fraction part, and sign.
|
||||
*
|
||||
* This is an alternative to the more powerful {@link ufmtval_nextPosition} API.
|
||||
*
|
||||
* If you need information on only one field, use {@link ufmtval_nextPosition} or
|
||||
* {@link unumf_resultNextFieldPosition}.
|
||||
*
|
||||
* @param uresult The object containing the formatted number.
|
||||
* @param ufpositer
|
||||
* A pointer to a UFieldPositionIterator created by {@link #ufieldpositer_open}. Iteration
|
||||
* information already present in the UFieldPositionIterator is deleted, and the iterator is reset
|
||||
* to apply to the fields in the formatted string created by this function call. The field values
|
||||
* and indexes returned by {@link #ufieldpositer_next} represent fields denoted by
|
||||
* the UNumberFormatFields enum. Fields are not returned in a guaranteed order. Fields cannot
|
||||
* overlap, but they may nest. For example, 1234 could format as "1,234" which might consist of a
|
||||
* grouping separator field for ',' and an integer field encompassing the entire string.
|
||||
* @param ec Set if an error occurs.
|
||||
* @stable ICU 62
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer,
|
||||
UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Extracts the formatted number as a "numeric string" conforming to the
|
||||
* syntax defined in the Decimal Arithmetic Specification, available at
|
||||
* http://speleotrove.com/decimal
|
||||
*
|
||||
* This endpoint is useful for obtaining the exact number being printed
|
||||
* after scaling and rounding have been applied by the number formatter.
|
||||
*
|
||||
* @param uresult The input object containing the formatted number.
|
||||
* @param dest the 8-bit char buffer into which the decimal number is placed
|
||||
* @param destCapacity The size, in chars, of the destination buffer. May be zero
|
||||
* for precomputing the required size.
|
||||
* @param ec receives any error status.
|
||||
* If U_BUFFER_OVERFLOW_ERROR: Returns number of chars for
|
||||
* preflighting.
|
||||
* @return Number of chars in the data. Does not include a trailing NUL.
|
||||
* @stable ICU 68
|
||||
*/
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
unumf_resultToDecimalNumber(
|
||||
const UFormattedNumber* uresult,
|
||||
char* dest,
|
||||
int32_t destCapacity,
|
||||
UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -800,15 +548,6 @@ U_CAPI void U_EXPORT2
|
|||
unumf_close(UNumberFormatter* uformatter);
|
||||
|
||||
|
||||
/**
|
||||
* Releases the UFormattedNumber created by unumf_openResult().
|
||||
*
|
||||
* @param uresult An object created by unumf_openResult().
|
||||
* @stable ICU 62
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
unumf_closeResult(UFormattedNumber* uresult);
|
||||
|
||||
|
||||
#if U_SHOW_CPLUSPLUS_API
|
||||
U_NAMESPACE_BEGIN
|
||||
|
@ -830,23 +569,6 @@ U_NAMESPACE_BEGIN
|
|||
*/
|
||||
U_DEFINE_LOCAL_OPEN_POINTER(LocalUNumberFormatterPointer, UNumberFormatter, unumf_close);
|
||||
|
||||
/**
|
||||
* \class LocalUFormattedNumberPointer
|
||||
* "Smart pointer" class; closes a UFormattedNumber via unumf_closeResult().
|
||||
* For most methods see the LocalPointerBase base class.
|
||||
*
|
||||
* Usage:
|
||||
* <pre>
|
||||
* LocalUFormattedNumberPointer uformatter(unumf_openResult(...));
|
||||
* // no need to explicitly call unumf_closeResult()
|
||||
* </pre>
|
||||
*
|
||||
* @see LocalPointerBase
|
||||
* @see LocalPointer
|
||||
* @stable ICU 62
|
||||
*/
|
||||
U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedNumberPointer, UFormattedNumber, unumf_closeResult);
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif // U_SHOW_CPLUSPLUS_API
|
||||
|
||||
|
|
173
icu4c/source/i18n/unicode/unumberoptions.h
Normal file
173
icu4c/source/i18n/unicode/unumberoptions.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
// © 2017 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html
|
||||
|
||||
#ifndef __UNUMBEROPTIONS_H__
|
||||
#define __UNUMBEROPTIONS_H__
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief C API: Header-only input options for various number formatting APIs.
|
||||
*
|
||||
* You do not normally need to include this header file directly, because it is included in all
|
||||
* files that use these enums.
|
||||
*/
|
||||
|
||||
|
||||
/** The possible number format rounding modes.
|
||||
*
|
||||
* <p>
|
||||
* For more detail on rounding modes, see:
|
||||
* https://unicode-org.github.io/icu/userguide/format_parse/numbers/rounding-modes
|
||||
*
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
typedef enum UNumberFormatRoundingMode {
|
||||
UNUM_ROUND_CEILING,
|
||||
UNUM_ROUND_FLOOR,
|
||||
UNUM_ROUND_DOWN,
|
||||
UNUM_ROUND_UP,
|
||||
/**
|
||||
* Half-even rounding
|
||||
* @stable, ICU 3.8
|
||||
*/
|
||||
UNUM_ROUND_HALFEVEN,
|
||||
#ifndef U_HIDE_DEPRECATED_API
|
||||
/**
|
||||
* Half-even rounding, misspelled name
|
||||
* @deprecated, ICU 3.8
|
||||
*/
|
||||
UNUM_FOUND_HALFEVEN = UNUM_ROUND_HALFEVEN,
|
||||
#endif /* U_HIDE_DEPRECATED_API */
|
||||
UNUM_ROUND_HALFDOWN = UNUM_ROUND_HALFEVEN + 1,
|
||||
UNUM_ROUND_HALFUP,
|
||||
/**
|
||||
* ROUND_UNNECESSARY reports an error if formatted result is not exact.
|
||||
* @stable ICU 4.8
|
||||
*/
|
||||
UNUM_ROUND_UNNECESSARY,
|
||||
/**
|
||||
* Rounds ties toward the odd number.
|
||||
* @stable ICU 69
|
||||
*/
|
||||
UNUM_ROUND_HALF_ODD,
|
||||
/**
|
||||
* Rounds ties toward +∞.
|
||||
* @stable ICU 69
|
||||
*/
|
||||
UNUM_ROUND_HALF_CEILING,
|
||||
/**
|
||||
* Rounds ties toward -∞.
|
||||
* @stable ICU 69
|
||||
*/
|
||||
UNUM_ROUND_HALF_FLOOR,
|
||||
} UNumberFormatRoundingMode;
|
||||
|
||||
|
||||
/**
|
||||
* An enum declaring the strategy for when and how to display grouping separators (i.e., the
|
||||
* separator, often a comma or period, after every 2-3 powers of ten). The choices are several
|
||||
* pre-built strategies for different use cases that employ locale data whenever possible. Example
|
||||
* outputs for 1234 and 1234567 in <em>en-IN</em>:
|
||||
*
|
||||
* <ul>
|
||||
* <li>OFF: 1234 and 12345
|
||||
* <li>MIN2: 1234 and 12,34,567
|
||||
* <li>AUTO: 1,234 and 12,34,567
|
||||
* <li>ON_ALIGNED: 1,234 and 12,34,567
|
||||
* <li>THOUSANDS: 1,234 and 1,234,567
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* The default is AUTO, which displays grouping separators unless the locale data says that grouping
|
||||
* is not customary. To force grouping for all numbers greater than 1000 consistently across locales,
|
||||
* use ON_ALIGNED. On the other hand, to display grouping less frequently than the default, use MIN2
|
||||
* or OFF. See the docs of each option for details.
|
||||
*
|
||||
* <p>
|
||||
* Note: This enum specifies the strategy for grouping sizes. To set which character to use as the
|
||||
* grouping separator, use the "symbols" setter.
|
||||
*
|
||||
* @stable ICU 63
|
||||
*/
|
||||
typedef enum UNumberGroupingStrategy {
|
||||
/**
|
||||
* Do not display grouping separators in any locale.
|
||||
*
|
||||
* @stable ICU 61
|
||||
*/
|
||||
UNUM_GROUPING_OFF,
|
||||
|
||||
/**
|
||||
* Display grouping using locale defaults, except do not show grouping on values smaller than
|
||||
* 10000 (such that there is a <em>minimum of two digits</em> before the first separator).
|
||||
*
|
||||
* <p>
|
||||
* Note that locales may restrict grouping separators to be displayed only on 1 million or
|
||||
* greater (for example, ee and hu) or disable grouping altogether (for example, bg currency).
|
||||
*
|
||||
* <p>
|
||||
* Locale data is used to determine whether to separate larger numbers into groups of 2
|
||||
* (customary in South Asia) or groups of 3 (customary in Europe and the Americas).
|
||||
*
|
||||
* @stable ICU 61
|
||||
*/
|
||||
UNUM_GROUPING_MIN2,
|
||||
|
||||
/**
|
||||
* Display grouping using the default strategy for all locales. This is the default behavior.
|
||||
*
|
||||
* <p>
|
||||
* Note that locales may restrict grouping separators to be displayed only on 1 million or
|
||||
* greater (for example, ee and hu) or disable grouping altogether (for example, bg currency).
|
||||
*
|
||||
* <p>
|
||||
* Locale data is used to determine whether to separate larger numbers into groups of 2
|
||||
* (customary in South Asia) or groups of 3 (customary in Europe and the Americas).
|
||||
*
|
||||
* @stable ICU 61
|
||||
*/
|
||||
UNUM_GROUPING_AUTO,
|
||||
|
||||
/**
|
||||
* Always display the grouping separator on values of at least 1000.
|
||||
*
|
||||
* <p>
|
||||
* This option ignores the locale data that restricts or disables grouping, described in MIN2 and
|
||||
* AUTO. This option may be useful to normalize the alignment of numbers, such as in a
|
||||
* spreadsheet.
|
||||
*
|
||||
* <p>
|
||||
* Locale data is used to determine whether to separate larger numbers into groups of 2
|
||||
* (customary in South Asia) or groups of 3 (customary in Europe and the Americas).
|
||||
*
|
||||
* @stable ICU 61
|
||||
*/
|
||||
UNUM_GROUPING_ON_ALIGNED,
|
||||
|
||||
/**
|
||||
* Use the Western defaults: groups of 3 and enabled for all numbers 1000 or greater. Do not use
|
||||
* locale data for determining the grouping strategy.
|
||||
*
|
||||
* @stable ICU 61
|
||||
*/
|
||||
UNUM_GROUPING_THOUSANDS
|
||||
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
,
|
||||
/**
|
||||
* One more than the highest UNumberGroupingStrategy value.
|
||||
*
|
||||
* @internal ICU 62: The numeric value may change over time; see ICU ticket #12420.
|
||||
*/
|
||||
UNUM_GROUPING_COUNT
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
|
||||
} UNumberGroupingStrategy;
|
||||
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
#endif //__UNUMBEROPTIONS_H__
|
273
icu4c/source/i18n/unicode/usimplenumberformatter.h
Normal file
273
icu4c/source/i18n/unicode/usimplenumberformatter.h
Normal file
|
@ -0,0 +1,273 @@
|
|||
// © 2022 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html
|
||||
|
||||
#ifndef __USIMPLENUMBERFORMATTER_H__
|
||||
#define __USIMPLENUMBERFORMATTER_H__
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/uformattednumber.h"
|
||||
#include "unicode/unumberoptions.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief C API: Simple number formatting focused on low memory and code size.
|
||||
*
|
||||
* These functions render locale-aware number strings but without the bells and whistles found in
|
||||
* other number formatting APIs such as those in unumberformatter.h, like units and currencies.
|
||||
*
|
||||
* <pre>
|
||||
* LocalUSimpleNumberFormatterPointer uformatter(usnumf_openForLocale("de-CH", status));
|
||||
* LocalUFormattedNumberPointer uresult(unumf_openResult(status));
|
||||
* usnumf_formatInt64(uformatter.getAlias(), 55, uresult.getAlias(), status);
|
||||
* assertEquals("",
|
||||
* u"55",
|
||||
* ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
|
||||
|
||||
/**
|
||||
* An explicit sign option for a SimpleNumber.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
typedef enum USimpleNumberSign {
|
||||
/**
|
||||
* Render a plus sign.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
UNUM_SIMPLE_NUMBER_PLUS_SIGN,
|
||||
/**
|
||||
* Render no sign.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
UNUM_SIMPLE_NUMBER_NO_SIGN,
|
||||
/**
|
||||
* Render a minus sign.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
UNUM_SIMPLE_NUMBER_MINUS_SIGN,
|
||||
} USimpleNumberSign;
|
||||
|
||||
|
||||
struct USimpleNumber;
|
||||
/**
|
||||
* C-compatible version of icu::number::SimpleNumber.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
typedef struct USimpleNumber USimpleNumber;
|
||||
|
||||
|
||||
struct USimpleNumberFormatter;
|
||||
/**
|
||||
* C-compatible version of icu::number::SimpleNumberFormatter.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
typedef struct USimpleNumberFormatter USimpleNumberFormatter;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new USimpleNumber to be formatted with a USimpleNumberFormatter.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI USimpleNumber* U_EXPORT2
|
||||
usnum_openForInt64(int64_t value, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Changes the value of the USimpleNumber by a power of 10.
|
||||
*
|
||||
* This function immediately mutates the inner value.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
usnum_multiplyByPowerOfTen(USimpleNumber* unumber, int32_t power, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Rounds the value currently stored in the USimpleNumber to the given power of 10.
|
||||
*
|
||||
* This function immediately mutates the inner value.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
usnum_roundTo(USimpleNumber* unumber, int32_t power, UNumberFormatRoundingMode roundingMode, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Pads the beginning of the number with zeros up to the given minimum number of integer digits.
|
||||
*
|
||||
* This setting is applied upon formatting the number.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
usnum_setMinimumIntegerDigits(USimpleNumber* unumber, int32_t minimumIntegerDigits, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Pads the end of the number with zeros up to the given minimum number of fraction digits.
|
||||
*
|
||||
* This setting is applied upon formatting the number.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
usnum_setMinimumFractionDigits(USimpleNumber* unumber, int32_t minimumFractionDigits, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Truncates digits from the beginning of the number to the given maximum number of integer digits.
|
||||
*
|
||||
* This function immediately mutates the inner value.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
usnum_truncateStart(USimpleNumber* unumber, int32_t maximumIntegerDigits, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Sets the sign of the number: an explicit plus sign, explicit minus sign, or no sign.
|
||||
*
|
||||
* This setting is applied upon formatting the number.
|
||||
*
|
||||
* NOTE: This does not support accounting sign notation.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
usnum_setSign(USimpleNumber* unumber, USimpleNumberSign sign, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new USimpleNumberFormatter with all locale defaults.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI USimpleNumberFormatter* U_EXPORT2
|
||||
usnumf_openForLocale(const char* locale, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new USimpleNumberFormatter, overriding the grouping strategy.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI USimpleNumberFormatter* U_EXPORT2
|
||||
usnumf_openForLocaleAndGroupingStrategy(
|
||||
const char* locale, UNumberGroupingStrategy groupingStrategy, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Formats a number using this SimpleNumberFormatter.
|
||||
*
|
||||
* The USimpleNumber is adopted and must not be freed after calling this function,
|
||||
* even if the function sets an error code. If you use LocalUSimpleNumberPointer,
|
||||
* call `.orphan()` when passing it to this function.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
usnumf_formatAndAdoptNumber(
|
||||
const USimpleNumberFormatter* uformatter,
|
||||
USimpleNumber* unumber,
|
||||
UFormattedNumber* uresult,
|
||||
UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Formats an integer using this SimpleNumberFormatter.
|
||||
*
|
||||
* For more control over the formatting, use USimpleNumber.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
usnumf_formatInt64(
|
||||
const USimpleNumberFormatter* uformatter,
|
||||
int64_t value,
|
||||
UFormattedNumber* uresult,
|
||||
UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Frees the memory held by a USimpleNumber.
|
||||
*
|
||||
* NOTE: Normally, a USimpleNumber should be adopted by usnumf_formatAndAdoptNumber.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
usnum_close(USimpleNumber* unumber);
|
||||
|
||||
|
||||
/**
|
||||
* Frees the memory held by a USimpleNumberFormatter.
|
||||
*
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
usnumf_close(USimpleNumberFormatter* uformatter);
|
||||
|
||||
|
||||
#if U_SHOW_CPLUSPLUS_API
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \class LocalUSimpleNumberPointer
|
||||
* "Smart pointer" class; closes a USimpleNumber via usnum_close().
|
||||
* For most methods see the LocalPointerBase base class.
|
||||
*
|
||||
* NOTE: Normally, a USimpleNumber should be adopted by usnumf_formatAndAdoptNumber.
|
||||
* If you use LocalUSimpleNumberPointer, call `.orphan()` when passing to that function.
|
||||
*
|
||||
* Usage:
|
||||
* <pre>
|
||||
* LocalUSimpleNumberPointer uformatter(usnumf_openForInteger(...));
|
||||
* // no need to explicitly call usnum_close()
|
||||
* </pre>
|
||||
*
|
||||
* @see LocalPointerBase
|
||||
* @see LocalPointer
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_DEFINE_LOCAL_OPEN_POINTER(LocalUSimpleNumberPointer, USimpleNumber, usnum_close);
|
||||
|
||||
/**
|
||||
* \class LocalUSimpleNumberFormatterPointer
|
||||
* "Smart pointer" class; closes a USimpleNumberFormatter via usnumf_close().
|
||||
* For most methods see the LocalPointerBase base class.
|
||||
*
|
||||
* Usage:
|
||||
* <pre>
|
||||
* LocalUSimpleNumberFormatterPointer uformatter(usnumf_openForLocale(...));
|
||||
* // no need to explicitly call usnumf_close()
|
||||
* </pre>
|
||||
*
|
||||
* @see LocalPointerBase
|
||||
* @see LocalPointer
|
||||
* @draft ICU 73
|
||||
*/
|
||||
U_DEFINE_LOCAL_OPEN_POINTER(LocalUSimpleNumberFormatterPointer, USimpleNumberFormatter, usnumf_close);
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif // U_SHOW_CPLUSPLUS_API
|
||||
|
||||
#endif // U_HIDE_DRAFT_API
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
#endif //__USIMPLENUMBERFORMATTER_H__
|
|
@ -1007,6 +1007,9 @@ group: numberformatter
|
|||
number_scientific.o
|
||||
currpinf.o
|
||||
numrange_fluent.o numrange_impl.o
|
||||
# NOTE: This could go into its own dependency block, but it would require
|
||||
# refactoring more of the dependencies (e.g. removing class methods).
|
||||
number_simple.o
|
||||
deps
|
||||
decnumber double_conversion formattable units unitsformatter
|
||||
listformatter number_representation number_output
|
||||
|
|
|
@ -69,7 +69,8 @@ string_segment_test.o \
|
|||
numbertest_parse.o numbertest_doubleconversion.o numbertest_skeletons.o \
|
||||
static_unisets_test.o numfmtdatadriventest.o numbertest_range.o erarulestest.o \
|
||||
formattedvaluetest.o formatted_string_builder_test.o numbertest_permutation.o \
|
||||
units_data_test.o units_router_test.o units_test.o displayoptions_test.o
|
||||
units_data_test.o units_router_test.o units_test.o displayoptions_test.o \
|
||||
numbertest_simple.o
|
||||
|
||||
DEPS = $(OBJECTS:.o=.d)
|
||||
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
<ClCompile Include="numbertest_doubleconversion.cpp" />
|
||||
<ClCompile Include="numbertest_skeletons.cpp" />
|
||||
<ClCompile Include="numbertest_range.cpp" />
|
||||
<ClCompile Include="numbertest_simple.cpp" />
|
||||
<ClCompile Include="numbertest_permutation.cpp" />
|
||||
<ClCompile Include="numfmtst.cpp" />
|
||||
<ClCompile Include="numfmtdatadriventest.cpp" />
|
||||
|
|
|
@ -298,6 +298,9 @@
|
|||
<ClCompile Include="numbertest_range.cpp">
|
||||
<Filter>formatting</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="numbertest_simple.cpp">
|
||||
<Filter>formatting</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="numbertest_permutation.cpp">
|
||||
<Filter>formatting</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -365,6 +365,18 @@ class NumberRangeFormatterTest : public IntlTestWithFieldPosition {
|
|||
const char16_t* expected);
|
||||
};
|
||||
|
||||
class SimpleNumberFormatterTest : public IntlTestWithFieldPosition {
|
||||
public:
|
||||
void testBasic();
|
||||
void testWithOptions();
|
||||
void testSymbols();
|
||||
void testSign();
|
||||
void testCopyMove();
|
||||
void testCAPI();
|
||||
|
||||
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override;
|
||||
};
|
||||
|
||||
class NumberPermutationTest : public IntlTest {
|
||||
public:
|
||||
void testPermutations();
|
||||
|
@ -403,7 +415,8 @@ class NumberTest : public IntlTest {
|
|||
TESTCLASS(7, NumberParserTest);
|
||||
TESTCLASS(8, NumberSkeletonTest);
|
||||
TESTCLASS(9, NumberRangeFormatterTest);
|
||||
TESTCLASS(10, NumberPermutationTest);
|
||||
TESTCLASS(10, SimpleNumberFormatterTest);
|
||||
TESTCLASS(11, NumberPermutationTest);
|
||||
default: name = ""; break; // needed to end loop
|
||||
}
|
||||
}
|
||||
|
|
206
icu4c/source/test/intltest/numbertest_simple.cpp
Normal file
206
icu4c/source/test/intltest/numbertest_simple.cpp
Normal file
|
@ -0,0 +1,206 @@
|
|||
// © 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
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "numbertest.h"
|
||||
#include "unicode/simplenumberformatter.h"
|
||||
|
||||
|
||||
void SimpleNumberFormatterTest::runIndexedTest(int32_t index, UBool exec, const char*& name, char*) {
|
||||
if (exec) {
|
||||
logln("TestSuite SimpleNumberFormatterTest: ");
|
||||
}
|
||||
TESTCASE_AUTO_BEGIN;
|
||||
TESTCASE_AUTO(testBasic);
|
||||
TESTCASE_AUTO(testWithOptions);
|
||||
TESTCASE_AUTO(testSymbols);
|
||||
TESTCASE_AUTO(testSign);
|
||||
TESTCASE_AUTO(testCopyMove);
|
||||
TESTCASE_AUTO(testCAPI);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
||||
void SimpleNumberFormatterTest::testBasic() {
|
||||
IcuTestErrorCode status(*this, "testBasic");
|
||||
|
||||
SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("de-CH", status);
|
||||
FormattedNumber result = snf.formatInt64(-1000007, status);
|
||||
|
||||
static const UFieldPosition expectedFieldPositions[] = {
|
||||
// field, begin index, end index
|
||||
{UNUM_SIGN_FIELD, 0, 1},
|
||||
{UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
|
||||
{UNUM_GROUPING_SEPARATOR_FIELD, 6, 7},
|
||||
{UNUM_INTEGER_FIELD, 1, 10},
|
||||
};
|
||||
checkFormattedValue(
|
||||
u"testBasic",
|
||||
result,
|
||||
u"-1’000’007",
|
||||
UFIELD_CATEGORY_NUMBER,
|
||||
expectedFieldPositions,
|
||||
UPRV_LENGTHOF(expectedFieldPositions));
|
||||
}
|
||||
|
||||
void SimpleNumberFormatterTest::testWithOptions() {
|
||||
IcuTestErrorCode status(*this, "testWithOptions");
|
||||
|
||||
SimpleNumber num = SimpleNumber::forInt64(1250000, status);
|
||||
num.setMinimumIntegerDigits(6, status);
|
||||
num.setMinimumFractionDigits(2, status);
|
||||
num.multiplyByPowerOfTen(-2, status);
|
||||
num.roundTo(3, UNUM_ROUND_HALFUP, status);
|
||||
num.truncateStart(4, status);
|
||||
SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("bn", status);
|
||||
FormattedNumber result = snf.format(std::move(num), status);
|
||||
|
||||
static const UFieldPosition expectedFieldPositions[] = {
|
||||
// field, begin index, end index
|
||||
{UNUM_GROUPING_SEPARATOR_FIELD, 1, 2},
|
||||
{UNUM_GROUPING_SEPARATOR_FIELD, 4, 5},
|
||||
{UNUM_INTEGER_FIELD, 0, 8},
|
||||
{UNUM_DECIMAL_SEPARATOR_FIELD, 8, 9},
|
||||
{UNUM_FRACTION_FIELD, 9, 11},
|
||||
};
|
||||
checkFormattedValue(
|
||||
u"testWithOptions",
|
||||
result,
|
||||
u"০,০৩,০০০.০০",
|
||||
UFIELD_CATEGORY_NUMBER,
|
||||
expectedFieldPositions,
|
||||
UPRV_LENGTHOF(expectedFieldPositions));
|
||||
}
|
||||
|
||||
void SimpleNumberFormatterTest::testSymbols() {
|
||||
IcuTestErrorCode status(*this, "testSymbols");
|
||||
|
||||
LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols("bn", status), status);
|
||||
SimpleNumberFormatter snf = SimpleNumberFormatter::forLocaleAndSymbolsAndGroupingStrategy(
|
||||
"en-US",
|
||||
*symbols,
|
||||
UNUM_GROUPING_ON_ALIGNED,
|
||||
status
|
||||
);
|
||||
auto result = snf.formatInt64(987654321, status);
|
||||
|
||||
assertEquals("bn symbols with en-US pattern",
|
||||
u"৯৮৭,৬৫৪,৩২১",
|
||||
result.toTempString(status));
|
||||
}
|
||||
|
||||
void SimpleNumberFormatterTest::testSign() {
|
||||
IcuTestErrorCode status(*this, "testSign");
|
||||
|
||||
SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("und", status);
|
||||
|
||||
struct TestCase {
|
||||
int64_t input;
|
||||
USimpleNumberSign sign;
|
||||
const char16_t* expected;
|
||||
} cases[] = {
|
||||
{ 1, UNUM_SIMPLE_NUMBER_NO_SIGN, u"1" },
|
||||
{ 1, UNUM_SIMPLE_NUMBER_PLUS_SIGN, u"+1" },
|
||||
{ 1, UNUM_SIMPLE_NUMBER_MINUS_SIGN, u"-1" },
|
||||
{ 0, UNUM_SIMPLE_NUMBER_NO_SIGN, u"0" },
|
||||
{ 0, UNUM_SIMPLE_NUMBER_PLUS_SIGN, u"+0" },
|
||||
{ 0, UNUM_SIMPLE_NUMBER_MINUS_SIGN, u"-0" },
|
||||
{ -1, UNUM_SIMPLE_NUMBER_NO_SIGN, u"1" },
|
||||
{ -1, UNUM_SIMPLE_NUMBER_PLUS_SIGN, u"+1" },
|
||||
{ -1, UNUM_SIMPLE_NUMBER_MINUS_SIGN, u"-1" },
|
||||
};
|
||||
for (auto& cas : cases) {
|
||||
SimpleNumber num = SimpleNumber::forInt64(cas.input, status);
|
||||
num.setSign(cas.sign, status);
|
||||
auto result = snf.format(std::move(num), status);
|
||||
assertEquals("", cas.expected, result.toTempString(status));
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleNumberFormatterTest::testCopyMove() {
|
||||
IcuTestErrorCode status(*this, "testCopyMove");
|
||||
|
||||
SimpleNumberFormatter snf0 = SimpleNumberFormatter::forLocale("und", status);
|
||||
|
||||
SimpleNumber sn0 = SimpleNumber::forInt64(55, status);
|
||||
SimpleNumber sn1 = std::move(sn0);
|
||||
|
||||
snf0.format(std::move(sn0), status);
|
||||
status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Use of moved number");
|
||||
|
||||
assertEquals("Move number constructor",
|
||||
u"55",
|
||||
snf0.format(std::move(sn1), status).toTempString(status));
|
||||
|
||||
SimpleNumber sn2;
|
||||
snf0.format(std::move(sn2), status);
|
||||
status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default constructed number");
|
||||
|
||||
sn0 = SimpleNumber::forInt64(44, status);
|
||||
|
||||
assertEquals("Move number assignment",
|
||||
u"44",
|
||||
snf0.format(std::move(sn0), status).toTempString(status));
|
||||
|
||||
SimpleNumberFormatter snf1 = std::move(snf0);
|
||||
|
||||
snf0.format(SimpleNumber::forInt64(22, status), status);
|
||||
status.expectErrorAndReset(U_INVALID_STATE_ERROR, "Use of moved formatter");
|
||||
|
||||
assertEquals("Move formatter constructor",
|
||||
u"33",
|
||||
snf1.format(SimpleNumber::forInt64(33, status), status).toTempString(status));
|
||||
|
||||
SimpleNumberFormatter snf2;
|
||||
snf2.format(SimpleNumber::forInt64(22, status), status);
|
||||
status.expectErrorAndReset(U_INVALID_STATE_ERROR, "Default constructed formatter");
|
||||
|
||||
snf0 = std::move(snf1);
|
||||
|
||||
assertEquals("Move formatter assignment",
|
||||
u"22",
|
||||
snf0.format(SimpleNumber::forInt64(22, status), status).toTempString(status));
|
||||
|
||||
snf0 = SimpleNumberFormatter::forLocale("de", status);
|
||||
sn0 = SimpleNumber::forInt64(22, status);
|
||||
sn0 = SimpleNumber::forInt64(11, status);
|
||||
|
||||
assertEquals("Move assignment with nonempty fields",
|
||||
u"11",
|
||||
snf0.format(std::move(sn0), status).toTempString(status));
|
||||
}
|
||||
|
||||
void SimpleNumberFormatterTest::testCAPI() {
|
||||
IcuTestErrorCode status(*this, "testCAPI");
|
||||
|
||||
LocalUSimpleNumberFormatterPointer uformatter(usnumf_openForLocale("de-CH", status));
|
||||
LocalUFormattedNumberPointer uresult(unumf_openResult(status));
|
||||
usnumf_formatInt64(uformatter.getAlias(), 55, uresult.getAlias(), status);
|
||||
assertEquals("",
|
||||
u"55",
|
||||
ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
|
||||
|
||||
LocalUSimpleNumberPointer unumber(usnum_openForInt64(44, status));
|
||||
usnumf_formatAndAdoptNumber(uformatter.getAlias(), unumber.orphan(), uresult.getAlias(), status);
|
||||
assertEquals("",
|
||||
u"44",
|
||||
ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
|
||||
|
||||
unumber.adoptInstead(usnum_openForInt64(2335, status));
|
||||
usnum_multiplyByPowerOfTen(unumber.getAlias(), -2, status);
|
||||
usnum_roundTo(unumber.getAlias(), -1, UNUM_ROUND_HALFEVEN, status);
|
||||
usnum_truncateStart(unumber.getAlias(), 1, status);
|
||||
usnum_setMinimumFractionDigits(unumber.getAlias(), 3, status);
|
||||
usnum_setMinimumIntegerDigits(unumber.getAlias(), 3, status);
|
||||
usnumf_formatAndAdoptNumber(uformatter.getAlias(), unumber.orphan(), uresult.getAlias(), status);
|
||||
assertEquals("",
|
||||
u"003.400",
|
||||
ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue