ICU-13634 Implementing localized pattern converter and other pieces.
X-SVN-Rev: 41104
This commit is contained in:
parent
73fddf50d0
commit
f5d2257d34
@ -16,7 +16,7 @@ using namespace icu::number;
|
|||||||
using namespace icu::number::impl;
|
using namespace icu::number::impl;
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::notation(const Notation ¬ation) const {
|
Derived NumberFormatterSettings<Derived>::notation(const Notation& notation) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
// NOTE: Slicing is OK.
|
// NOTE: Slicing is OK.
|
||||||
copy.fMacros.notation = notation;
|
copy.fMacros.notation = notation;
|
||||||
@ -24,7 +24,7 @@ Derived NumberFormatterSettings<Derived>::notation(const Notation ¬ation) con
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::unit(const icu::MeasureUnit &unit) const {
|
Derived NumberFormatterSettings<Derived>::unit(const icu::MeasureUnit& unit) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
// NOTE: Slicing occurs here. However, CurrencyUnit can be restored from MeasureUnit.
|
// NOTE: Slicing occurs here. However, CurrencyUnit can be restored from MeasureUnit.
|
||||||
// TimeUnit may be affected, but TimeUnit is not as relevant to number formatting.
|
// TimeUnit may be affected, but TimeUnit is not as relevant to number formatting.
|
||||||
@ -33,13 +33,13 @@ Derived NumberFormatterSettings<Derived>::unit(const icu::MeasureUnit &unit) con
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::adoptUnit(icu::MeasureUnit *unit) const {
|
Derived NumberFormatterSettings<Derived>::adoptUnit(icu::MeasureUnit* unit) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
// Just copy the unit into the MacroProps by value, and delete it since we have ownership.
|
// Just copy the unit into the MacroProps by value, and delete it since we have ownership.
|
||||||
// NOTE: Slicing occurs here. However, CurrencyUnit can be restored from MeasureUnit.
|
// NOTE: Slicing occurs here. However, CurrencyUnit can be restored from MeasureUnit.
|
||||||
// TimeUnit may be affected, but TimeUnit is not as relevant to number formatting.
|
// TimeUnit may be affected, but TimeUnit is not as relevant to number formatting.
|
||||||
if (unit != nullptr) {
|
if (unit != nullptr) {
|
||||||
// TODO: On nullptr, reset to default value?
|
// TODO: On nullptr, reset to default value?
|
||||||
copy.fMacros.unit = *unit;
|
copy.fMacros.unit = *unit;
|
||||||
delete unit;
|
delete unit;
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ Derived NumberFormatterSettings<Derived>::adoptUnit(icu::MeasureUnit *unit) cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::perUnit(const icu::MeasureUnit &perUnit) const {
|
Derived NumberFormatterSettings<Derived>::perUnit(const icu::MeasureUnit& perUnit) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
// See comments above about slicing.
|
// See comments above about slicing.
|
||||||
copy.fMacros.perUnit = perUnit;
|
copy.fMacros.perUnit = perUnit;
|
||||||
@ -55,11 +55,11 @@ Derived NumberFormatterSettings<Derived>::perUnit(const icu::MeasureUnit &perUni
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::adoptPerUnit(icu::MeasureUnit *perUnit) const {
|
Derived NumberFormatterSettings<Derived>::adoptPerUnit(icu::MeasureUnit* perUnit) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
// See comments above about slicing and ownership.
|
// See comments above about slicing and ownership.
|
||||||
if (perUnit != nullptr) {
|
if (perUnit != nullptr) {
|
||||||
// TODO: On nullptr, reset to default value?
|
// TODO: On nullptr, reset to default value?
|
||||||
copy.fMacros.perUnit = *perUnit;
|
copy.fMacros.perUnit = *perUnit;
|
||||||
delete perUnit;
|
delete perUnit;
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ Derived NumberFormatterSettings<Derived>::adoptPerUnit(icu::MeasureUnit *perUnit
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::rounding(const Rounder &rounder) const {
|
Derived NumberFormatterSettings<Derived>::rounding(const Rounder& rounder) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
// NOTE: Slicing is OK.
|
// NOTE: Slicing is OK.
|
||||||
copy.fMacros.rounder = rounder;
|
copy.fMacros.rounder = rounder;
|
||||||
@ -75,7 +75,7 @@ Derived NumberFormatterSettings<Derived>::rounding(const Rounder &rounder) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::grouping(const UGroupingStrategy &strategy) const {
|
Derived NumberFormatterSettings<Derived>::grouping(const UGroupingStrategy& strategy) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
// NOTE: This is slightly different than how the setting is stored in Java
|
// NOTE: This is slightly different than how the setting is stored in Java
|
||||||
// because we want to put it on the stack.
|
// because we want to put it on the stack.
|
||||||
@ -84,49 +84,49 @@ Derived NumberFormatterSettings<Derived>::grouping(const UGroupingStrategy &stra
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::integerWidth(const IntegerWidth &style) const {
|
Derived NumberFormatterSettings<Derived>::integerWidth(const IntegerWidth& style) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
copy.fMacros.integerWidth = style;
|
copy.fMacros.integerWidth = style;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::symbols(const DecimalFormatSymbols &symbols) const {
|
Derived NumberFormatterSettings<Derived>::symbols(const DecimalFormatSymbols& symbols) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
copy.fMacros.symbols.setTo(symbols);
|
copy.fMacros.symbols.setTo(symbols);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::adoptSymbols(NumberingSystem *ns) const {
|
Derived NumberFormatterSettings<Derived>::adoptSymbols(NumberingSystem* ns) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
copy.fMacros.symbols.setTo(ns);
|
copy.fMacros.symbols.setTo(ns);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::unitWidth(const UNumberUnitWidth &width) const {
|
Derived NumberFormatterSettings<Derived>::unitWidth(const UNumberUnitWidth& width) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
copy.fMacros.unitWidth = width;
|
copy.fMacros.unitWidth = width;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::sign(const UNumberSignDisplay &style) const {
|
Derived NumberFormatterSettings<Derived>::sign(const UNumberSignDisplay& style) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
copy.fMacros.sign = style;
|
copy.fMacros.sign = style;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::decimal(const UNumberDecimalSeparatorDisplay &style) const {
|
Derived NumberFormatterSettings<Derived>::decimal(const UNumberDecimalSeparatorDisplay& style) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
copy.fMacros.decimal = style;
|
copy.fMacros.decimal = style;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Derived NumberFormatterSettings<Derived>::padding(const Padder &padder) const {
|
Derived NumberFormatterSettings<Derived>::padding(const Padder& padder) const {
|
||||||
Derived copy(*this);
|
Derived copy(*this);
|
||||||
copy.fMacros.padder = padder;
|
copy.fMacros.padder = padder;
|
||||||
return copy;
|
return copy;
|
||||||
@ -159,38 +159,38 @@ UnlocalizedNumberFormatter NumberFormatter::with() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalizedNumberFormatter NumberFormatter::withLocale(const Locale &locale) {
|
LocalizedNumberFormatter NumberFormatter::withLocale(const Locale& locale) {
|
||||||
return with().locale(locale);
|
return with().locale(locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the child class constructor that takes the parent class call the parent class's copy constructor
|
// Make the child class constructor that takes the parent class call the parent class's copy constructor
|
||||||
UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(
|
UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(
|
||||||
const NumberFormatterSettings <UnlocalizedNumberFormatter> &other)
|
const NumberFormatterSettings<UnlocalizedNumberFormatter>& other)
|
||||||
: NumberFormatterSettings<UnlocalizedNumberFormatter>(other) {
|
: NumberFormatterSettings<UnlocalizedNumberFormatter>(other) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the child class constructor that takes the parent class call the parent class's copy constructor
|
// Make the child class constructor that takes the parent class call the parent class's copy constructor
|
||||||
// For LocalizedNumberFormatter, also copy over the extra fields
|
// For LocalizedNumberFormatter, also copy over the extra fields
|
||||||
LocalizedNumberFormatter::LocalizedNumberFormatter(
|
LocalizedNumberFormatter::LocalizedNumberFormatter(
|
||||||
const NumberFormatterSettings <LocalizedNumberFormatter> &other)
|
const NumberFormatterSettings<LocalizedNumberFormatter>& other)
|
||||||
: NumberFormatterSettings<LocalizedNumberFormatter>(other) {
|
: NumberFormatterSettings<LocalizedNumberFormatter>(other) {
|
||||||
// No additional copies required
|
// No additional copies required
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalizedNumberFormatter::LocalizedNumberFormatter(const MacroProps ¯os, const Locale &locale) {
|
LocalizedNumberFormatter::LocalizedNumberFormatter(const MacroProps& macros, const Locale& locale) {
|
||||||
fMacros = macros;
|
fMacros = macros;
|
||||||
fMacros.locale = locale;
|
fMacros.locale = locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalizedNumberFormatter UnlocalizedNumberFormatter::locale(const Locale &locale) const {
|
LocalizedNumberFormatter UnlocalizedNumberFormatter::locale(const Locale& locale) const {
|
||||||
return LocalizedNumberFormatter(fMacros, locale);
|
return LocalizedNumberFormatter(fMacros, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolsWrapper::SymbolsWrapper(const SymbolsWrapper &other) {
|
SymbolsWrapper::SymbolsWrapper(const SymbolsWrapper& other) {
|
||||||
doCopyFrom(other);
|
doCopyFrom(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolsWrapper &SymbolsWrapper::operator=(const SymbolsWrapper &other) {
|
SymbolsWrapper& SymbolsWrapper::operator=(const SymbolsWrapper& other) {
|
||||||
if (this == &other) {
|
if (this == &other) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -203,19 +203,19 @@ SymbolsWrapper::~SymbolsWrapper() {
|
|||||||
doCleanup();
|
doCleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolsWrapper::setTo(const DecimalFormatSymbols &dfs) {
|
void SymbolsWrapper::setTo(const DecimalFormatSymbols& dfs) {
|
||||||
doCleanup();
|
doCleanup();
|
||||||
fType = SYMPTR_DFS;
|
fType = SYMPTR_DFS;
|
||||||
fPtr.dfs = new DecimalFormatSymbols(dfs);
|
fPtr.dfs = new DecimalFormatSymbols(dfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolsWrapper::setTo(const NumberingSystem *ns) {
|
void SymbolsWrapper::setTo(const NumberingSystem* ns) {
|
||||||
doCleanup();
|
doCleanup();
|
||||||
fType = SYMPTR_NS;
|
fType = SYMPTR_NS;
|
||||||
fPtr.ns = ns;
|
fPtr.ns = ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolsWrapper::doCopyFrom(const SymbolsWrapper &other) {
|
void SymbolsWrapper::doCopyFrom(const SymbolsWrapper& other) {
|
||||||
fType = other.fType;
|
fType = other.fType;
|
||||||
switch (fType) {
|
switch (fType) {
|
||||||
case SYMPTR_NONE:
|
case SYMPTR_NONE:
|
||||||
@ -276,7 +276,7 @@ LocalizedNumberFormatter::~LocalizedNumberFormatter() {
|
|||||||
delete fCompiled;
|
delete fCompiled;
|
||||||
}
|
}
|
||||||
|
|
||||||
FormattedNumber LocalizedNumberFormatter::formatInt(int64_t value, UErrorCode &status) const {
|
FormattedNumber LocalizedNumberFormatter::formatInt(int64_t value, UErrorCode& status) const {
|
||||||
if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); }
|
if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); }
|
||||||
auto results = new NumberFormatterResults();
|
auto results = new NumberFormatterResults();
|
||||||
if (results == nullptr) {
|
if (results == nullptr) {
|
||||||
@ -287,7 +287,7 @@ FormattedNumber LocalizedNumberFormatter::formatInt(int64_t value, UErrorCode &s
|
|||||||
return formatImpl(results, status);
|
return formatImpl(results, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
FormattedNumber LocalizedNumberFormatter::formatDouble(double value, UErrorCode &status) const {
|
FormattedNumber LocalizedNumberFormatter::formatDouble(double value, UErrorCode& status) const {
|
||||||
if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); }
|
if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); }
|
||||||
auto results = new NumberFormatterResults();
|
auto results = new NumberFormatterResults();
|
||||||
if (results == nullptr) {
|
if (results == nullptr) {
|
||||||
@ -298,7 +298,7 @@ FormattedNumber LocalizedNumberFormatter::formatDouble(double value, UErrorCode
|
|||||||
return formatImpl(results, status);
|
return formatImpl(results, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
FormattedNumber LocalizedNumberFormatter::formatDecimal(StringPiece value, UErrorCode &status) const {
|
FormattedNumber LocalizedNumberFormatter::formatDecimal(StringPiece value, UErrorCode& status) const {
|
||||||
if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); }
|
if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); }
|
||||||
auto results = new NumberFormatterResults();
|
auto results = new NumberFormatterResults();
|
||||||
if (results == nullptr) {
|
if (results == nullptr) {
|
||||||
@ -309,7 +309,8 @@ FormattedNumber LocalizedNumberFormatter::formatDecimal(StringPiece value, UErro
|
|||||||
return formatImpl(results, status);
|
return formatImpl(results, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
FormattedNumber LocalizedNumberFormatter::formatDecimalQuantity(const DecimalQuantity& dq, UErrorCode &status) const {
|
FormattedNumber
|
||||||
|
LocalizedNumberFormatter::formatDecimalQuantity(const DecimalQuantity& dq, UErrorCode& status) const {
|
||||||
if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); }
|
if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); }
|
||||||
auto results = new NumberFormatterResults();
|
auto results = new NumberFormatterResults();
|
||||||
if (results == nullptr) {
|
if (results == nullptr) {
|
||||||
@ -321,15 +322,16 @@ FormattedNumber LocalizedNumberFormatter::formatDecimalQuantity(const DecimalQua
|
|||||||
}
|
}
|
||||||
|
|
||||||
FormattedNumber
|
FormattedNumber
|
||||||
LocalizedNumberFormatter::formatImpl(impl::NumberFormatterResults *results, UErrorCode &status) const {
|
LocalizedNumberFormatter::formatImpl(impl::NumberFormatterResults* results, UErrorCode& status) const {
|
||||||
// fUnsafeCallCount contains memory to be interpreted as an atomic int, most commonly
|
// fUnsafeCallCount contains memory to be interpreted as an atomic int, most commonly
|
||||||
// std::atomic<int32_t>. Since the type of atomic int is platform-dependent, we cast the
|
// std::atomic<int32_t>. Since the type of atomic int is platform-dependent, we cast the
|
||||||
// bytes in fUnsafeCallCount to u_atomic_int32_t, a typedef for the platform-dependent
|
// bytes in fUnsafeCallCount to u_atomic_int32_t, a typedef for the platform-dependent
|
||||||
// atomic int type defined in umutex.h.
|
// atomic int type defined in umutex.h.
|
||||||
static_assert(sizeof(u_atomic_int32_t) <= sizeof(fUnsafeCallCount),
|
static_assert(
|
||||||
"Atomic integer size on this platform exceeds the size allocated by fUnsafeCallCount");
|
sizeof(u_atomic_int32_t) <= sizeof(fUnsafeCallCount),
|
||||||
|
"Atomic integer size on this platform exceeds the size allocated by fUnsafeCallCount");
|
||||||
u_atomic_int32_t* callCount = reinterpret_cast<u_atomic_int32_t*>(
|
u_atomic_int32_t* callCount = reinterpret_cast<u_atomic_int32_t*>(
|
||||||
const_cast<LocalizedNumberFormatter*>(this)->fUnsafeCallCount);
|
const_cast<LocalizedNumberFormatter*>(this)->fUnsafeCallCount);
|
||||||
|
|
||||||
// A positive value in the atomic int indicates that the data structure is not yet ready;
|
// A positive value in the atomic int indicates that the data structure is not yet ready;
|
||||||
// a negative value indicates that it is ready. If, after the increment, the atomic int
|
// a negative value indicates that it is ready. If, after the increment, the atomic int
|
||||||
@ -343,10 +345,9 @@ LocalizedNumberFormatter::formatImpl(impl::NumberFormatterResults *results, UErr
|
|||||||
|
|
||||||
if (currentCount == fMacros.threshold && fMacros.threshold > 0) {
|
if (currentCount == fMacros.threshold && fMacros.threshold > 0) {
|
||||||
// Build the data structure and then use it (slow to fast path).
|
// Build the data structure and then use it (slow to fast path).
|
||||||
const NumberFormatterImpl* compiled =
|
const NumberFormatterImpl* compiled = NumberFormatterImpl::fromMacros(fMacros, status);
|
||||||
NumberFormatterImpl::fromMacros(fMacros, status);
|
|
||||||
U_ASSERT(fCompiled == nullptr);
|
U_ASSERT(fCompiled == nullptr);
|
||||||
const_cast<LocalizedNumberFormatter *>(this)->fCompiled = compiled;
|
const_cast<LocalizedNumberFormatter*>(this)->fCompiled = compiled;
|
||||||
umtx_storeRelease(*callCount, INT32_MIN);
|
umtx_storeRelease(*callCount, INT32_MIN);
|
||||||
compiled->apply(results->quantity, results->string, status);
|
compiled->apply(results->quantity, results->string, status);
|
||||||
} else if (currentCount < 0) {
|
} else if (currentCount < 0) {
|
||||||
@ -375,7 +376,7 @@ UnicodeString FormattedNumber::toString() const {
|
|||||||
return fResults->string.toUnicodeString();
|
return fResults->string.toUnicodeString();
|
||||||
}
|
}
|
||||||
|
|
||||||
Appendable &FormattedNumber::appendTo(Appendable &appendable) {
|
Appendable& FormattedNumber::appendTo(Appendable& appendable) {
|
||||||
if (fResults == nullptr) {
|
if (fResults == nullptr) {
|
||||||
// TODO: http://bugs.icu-project.org/trac/ticket/13437
|
// TODO: http://bugs.icu-project.org/trac/ticket/13437
|
||||||
return appendable;
|
return appendable;
|
||||||
@ -384,7 +385,7 @@ Appendable &FormattedNumber::appendTo(Appendable &appendable) {
|
|||||||
return appendable;
|
return appendable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormattedNumber::populateFieldPosition(FieldPosition &fieldPosition, UErrorCode &status) {
|
void FormattedNumber::populateFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) {
|
||||||
if (U_FAILURE(status)) { return; }
|
if (U_FAILURE(status)) { return; }
|
||||||
if (fResults == nullptr) {
|
if (fResults == nullptr) {
|
||||||
status = fErrorCode;
|
status = fErrorCode;
|
||||||
@ -393,8 +394,7 @@ void FormattedNumber::populateFieldPosition(FieldPosition &fieldPosition, UError
|
|||||||
fResults->string.populateFieldPosition(fieldPosition, 0, status);
|
fResults->string.populateFieldPosition(fieldPosition, 0, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void FormattedNumber::populateFieldPositionIterator(FieldPositionIterator& iterator, UErrorCode& status) {
|
||||||
FormattedNumber::populateFieldPositionIterator(FieldPositionIterator &iterator, UErrorCode &status) {
|
|
||||||
if (U_FAILURE(status)) { return; }
|
if (U_FAILURE(status)) { return; }
|
||||||
if (fResults == nullptr) {
|
if (fResults == nullptr) {
|
||||||
status = fErrorCode;
|
status = fErrorCode;
|
||||||
@ -403,6 +403,33 @@ FormattedNumber::populateFieldPositionIterator(FieldPositionIterator &iterator,
|
|||||||
fResults->string.populateFieldPositionIterator(iterator, status);
|
fResults->string.populateFieldPositionIterator(iterator, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FormattedNumber::getDecimalQuantity(DecimalQuantity& output, UErrorCode& status) const {
|
||||||
|
if (U_FAILURE(status)) { return; }
|
||||||
|
if (fResults == nullptr) {
|
||||||
|
status = fErrorCode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
output = fResults->quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
const UnicodeString FormattedNumber::getPrefix(UErrorCode& status) const {
|
||||||
|
if (fResults == nullptr) {
|
||||||
|
status = fErrorCode;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
// FIXME
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const UnicodeString FormattedNumber::getSuffix(UErrorCode& status) const {
|
||||||
|
if (fResults == nullptr) {
|
||||||
|
status = fErrorCode;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
// FIXME
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
FormattedNumber::~FormattedNumber() {
|
FormattedNumber::~FormattedNumber() {
|
||||||
delete fResults;
|
delete fResults;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,14 @@ using namespace icu::number;
|
|||||||
using namespace icu::number::impl;
|
using namespace icu::number::impl;
|
||||||
|
|
||||||
|
|
||||||
|
UnlocalizedNumberFormatter NumberPropertyMapper::create(const DecimalFormatProperties& properties,
|
||||||
|
const DecimalFormatSymbols& symbols,
|
||||||
|
DecimalFormatProperties& exportedProperties,
|
||||||
|
UErrorCode& status) {
|
||||||
|
// TODO
|
||||||
|
status = U_UNSUPPORTED_ERROR;
|
||||||
|
return NumberFormatter::with();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,6 +5,11 @@
|
|||||||
|
|
||||||
#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT
|
#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT
|
||||||
|
|
||||||
|
// Allow implicit conversion from char16_t* to UnicodeString for this file:
|
||||||
|
// Helpful in toString methods and elsewhere.
|
||||||
|
#define UNISTR_FROM_STRING_EXPLICIT
|
||||||
|
#define UNISTR_FROM_CHAR_EXPLICIT
|
||||||
|
|
||||||
#include "uassert.h"
|
#include "uassert.h"
|
||||||
#include "number_patternstring.h"
|
#include "number_patternstring.h"
|
||||||
#include "unicode/utf16.h"
|
#include "unicode/utf16.h"
|
||||||
@ -633,7 +638,7 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP
|
|||||||
int groupingSize = uprv_min(properties.secondaryGroupingSize, dosMax);
|
int groupingSize = uprv_min(properties.secondaryGroupingSize, dosMax);
|
||||||
int firstGroupingSize = uprv_min(properties.groupingSize, dosMax);
|
int firstGroupingSize = uprv_min(properties.groupingSize, dosMax);
|
||||||
int paddingWidth = uprv_min(properties.formatWidth, dosMax);
|
int paddingWidth = uprv_min(properties.formatWidth, dosMax);
|
||||||
NullableValue <PadPosition> paddingLocation = properties.padPosition;
|
NullableValue<PadPosition> paddingLocation = properties.padPosition;
|
||||||
UnicodeString paddingString = properties.padString;
|
UnicodeString paddingString = properties.padString;
|
||||||
int minInt = uprv_max(uprv_min(properties.minimumIntegerDigits, dosMax), 0);
|
int minInt = uprv_max(uprv_min(properties.minimumIntegerDigits, dosMax), 0);
|
||||||
int maxInt = uprv_min(properties.maximumIntegerDigits, dosMax);
|
int maxInt = uprv_min(properties.maximumIntegerDigits, dosMax);
|
||||||
@ -841,6 +846,144 @@ int PatternStringUtils::escapePaddingString(UnicodeString input, UnicodeString&
|
|||||||
return output.length() - startLength;
|
return output.length() - startLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UnicodeString
|
||||||
|
PatternStringUtils::convertLocalized(UnicodeString input, DecimalFormatSymbols symbols, bool toLocalized,
|
||||||
|
UErrorCode& status) {
|
||||||
|
// Construct a table of strings to be converted between localized and standard.
|
||||||
|
static constexpr int32_t LEN = 21;
|
||||||
|
UnicodeString table[LEN][2];
|
||||||
|
int standIdx = toLocalized ? 0 : 1;
|
||||||
|
int localIdx = toLocalized ? 1 : 0;
|
||||||
|
table[0][standIdx] = u"%";
|
||||||
|
table[0][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
|
||||||
|
table[1][standIdx] = u"‰";
|
||||||
|
table[1][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
|
||||||
|
table[2][standIdx] = u".";
|
||||||
|
table[2][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
|
||||||
|
table[3][standIdx] = u",";
|
||||||
|
table[3][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
|
||||||
|
table[4][standIdx] = u"-";
|
||||||
|
table[4][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
|
||||||
|
table[5][standIdx] = u"+";
|
||||||
|
table[5][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
|
||||||
|
table[6][standIdx] = u";";
|
||||||
|
table[6][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol);
|
||||||
|
table[7][standIdx] = u"@";
|
||||||
|
table[7][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol);
|
||||||
|
table[8][standIdx] = u"E";
|
||||||
|
table[8][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
|
||||||
|
table[9][standIdx] = u"*";
|
||||||
|
table[9][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol);
|
||||||
|
table[10][standIdx] = u"#";
|
||||||
|
table[10][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kDigitSymbol);
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
table[11 + i][standIdx] = u'0' + i;
|
||||||
|
table[11 + i][localIdx] = symbols.getConstDigitSymbol(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case: quotes are NOT allowed to be in any localIdx strings.
|
||||||
|
// Substitute them with '’' instead.
|
||||||
|
for (int32_t i = 0; i < LEN; i++) {
|
||||||
|
table[i][localIdx].findAndReplace(u'\'', u'’');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate through the string and convert.
|
||||||
|
// State table:
|
||||||
|
// 0 => base state
|
||||||
|
// 1 => first char inside a quoted sequence in input and output string
|
||||||
|
// 2 => inside a quoted sequence in input and output string
|
||||||
|
// 3 => first char after a close quote in input string;
|
||||||
|
// close quote still needs to be written to output string
|
||||||
|
// 4 => base state in input string; inside quoted sequence in output string
|
||||||
|
// 5 => first char inside a quoted sequence in input string;
|
||||||
|
// inside quoted sequence in output string
|
||||||
|
UnicodeString result;
|
||||||
|
int state = 0;
|
||||||
|
for (int offset = 0; offset < input.length(); offset++) {
|
||||||
|
UChar ch = input.charAt(offset);
|
||||||
|
|
||||||
|
// Handle a quote character (state shift)
|
||||||
|
if (ch == u'\'') {
|
||||||
|
if (state == 0) {
|
||||||
|
result.append(u'\'');
|
||||||
|
state = 1;
|
||||||
|
continue;
|
||||||
|
} else if (state == 1) {
|
||||||
|
result.append(u'\'');
|
||||||
|
state = 0;
|
||||||
|
continue;
|
||||||
|
} else if (state == 2) {
|
||||||
|
state = 3;
|
||||||
|
continue;
|
||||||
|
} else if (state == 3) {
|
||||||
|
result.append(u'\'');
|
||||||
|
result.append(u'\'');
|
||||||
|
state = 1;
|
||||||
|
continue;
|
||||||
|
} else if (state == 4) {
|
||||||
|
state = 5;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
U_ASSERT(state == 5);
|
||||||
|
result.append(u'\'');
|
||||||
|
result.append(u'\'');
|
||||||
|
state = 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == 0 || state == 3 || state == 4) {
|
||||||
|
for (auto& pair : table) {
|
||||||
|
// Perform a greedy match on this symbol string
|
||||||
|
UnicodeString temp = input.tempSubString(offset, pair[0].length());
|
||||||
|
if (temp == pair[0]) {
|
||||||
|
// Skip ahead past this region for the next iteration
|
||||||
|
offset += pair[0].length() - 1;
|
||||||
|
if (state == 3 || state == 4) {
|
||||||
|
result.append(u'\'');
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
result.append(pair[1]);
|
||||||
|
goto continue_outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No replacement found. Check if a special quote is necessary
|
||||||
|
for (auto& pair : table) {
|
||||||
|
UnicodeString temp = input.tempSubString(offset, pair[1].length());
|
||||||
|
if (temp == pair[1]) {
|
||||||
|
if (state == 0) {
|
||||||
|
result.append(u'\'');
|
||||||
|
state = 4;
|
||||||
|
}
|
||||||
|
result.append(ch);
|
||||||
|
goto continue_outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Still nothing. Copy the char verbatim. (Add a close quote if necessary)
|
||||||
|
if (state == 3 || state == 4) {
|
||||||
|
result.append(u'\'');
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
result.append(ch);
|
||||||
|
} else {
|
||||||
|
U_ASSERT(state == 1 || state == 2 || state == 5);
|
||||||
|
result.append(ch);
|
||||||
|
state = 2;
|
||||||
|
}
|
||||||
|
continue_outer:;
|
||||||
|
}
|
||||||
|
// Resolve final quotes
|
||||||
|
if (state == 3 || state == 4) {
|
||||||
|
result.append(u'\'');
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
if (state != 0) {
|
||||||
|
// Malformed localized pattern: unterminated quote
|
||||||
|
status = U_PATTERN_SYNTAX_ERROR;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix,
|
void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix,
|
||||||
int8_t signum, UNumberSignDisplay signDisplay,
|
int8_t signum, UNumberSignDisplay signDisplay,
|
||||||
StandardPlural::Form plural,
|
StandardPlural::Form plural,
|
||||||
|
@ -74,6 +74,14 @@ NumberParserImpl::createSimpleParser(const Locale& locale, const UnicodeString&
|
|||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NumberParserImpl* NumberParserImpl::createParserFromProperties(
|
||||||
|
const number::impl::DecimalFormatProperties& properties, DecimalFormatSymbols symbols,
|
||||||
|
bool parseCurrency, bool optimize, UErrorCode& status) {
|
||||||
|
// TODO
|
||||||
|
status = U_UNSUPPORTED_ERROR;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
NumberParserImpl::NumberParserImpl(parse_flags_t parseFlags, bool computeLeads)
|
NumberParserImpl::NumberParserImpl(parse_flags_t parseFlags, bool computeLeads)
|
||||||
: fParseFlags(parseFlags), fComputeLeads(computeLeads) {
|
: fParseFlags(parseFlags), fComputeLeads(computeLeads) {
|
||||||
}
|
}
|
||||||
|
@ -2147,11 +2147,10 @@ class U_I18N_API FormattedNumber : public UMemory {
|
|||||||
#ifndef U_HIDE_INTERNAL_API
|
#ifndef U_HIDE_INTERNAL_API
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an IFixedDecimal for plural rule selection.
|
* Gets the raw DecimalQuantity for plural rule selection.
|
||||||
* Internal, not intended for public use.
|
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
const IFixedDecimal& getFixedDecimal(UErrorCode& status) const;
|
void getDecimalQuantity(impl::DecimalQuantity& output, UErrorCode& status) const;
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
const UnicodeString getPrefix(UErrorCode& status) const;
|
const UnicodeString getPrefix(UErrorCode& status) const;
|
||||||
|
@ -166,6 +166,7 @@ class PatternModifierTest : public IntlTest {
|
|||||||
|
|
||||||
class PatternStringTest : public IntlTest {
|
class PatternStringTest : public IntlTest {
|
||||||
public:
|
public:
|
||||||
|
void testLocalized();
|
||||||
void testToPatternSimple();
|
void testToPatternSimple();
|
||||||
void testExceptionOnInvalid();
|
void testExceptionOnInvalid();
|
||||||
void testBug13117();
|
void testBug13117();
|
||||||
|
@ -8,19 +8,42 @@
|
|||||||
#include "numbertest.h"
|
#include "numbertest.h"
|
||||||
#include "number_patternstring.h"
|
#include "number_patternstring.h"
|
||||||
|
|
||||||
void PatternStringTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char *) {
|
void PatternStringTest::runIndexedTest(int32_t index, UBool exec, const char*& name, char*) {
|
||||||
if (exec) {
|
if (exec) {
|
||||||
logln("TestSuite PatternStringTest: ");
|
logln("TestSuite PatternStringTest: ");
|
||||||
}
|
}
|
||||||
TESTCASE_AUTO_BEGIN;
|
TESTCASE_AUTO_BEGIN;
|
||||||
|
TESTCASE_AUTO(testLocalized);
|
||||||
TESTCASE_AUTO(testToPatternSimple);
|
TESTCASE_AUTO(testToPatternSimple);
|
||||||
TESTCASE_AUTO(testExceptionOnInvalid);
|
TESTCASE_AUTO(testExceptionOnInvalid);
|
||||||
TESTCASE_AUTO(testBug13117);
|
TESTCASE_AUTO(testBug13117);
|
||||||
TESTCASE_AUTO_END;
|
TESTCASE_AUTO_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PatternStringTest::testLocalized() {
|
||||||
|
IcuTestErrorCode status(*this, "testLocalized");
|
||||||
|
DecimalFormatSymbols symbols(Locale::getEnglish(), status);
|
||||||
|
symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"a", status);
|
||||||
|
symbols.setSymbol(DecimalFormatSymbols::kPercentSymbol, u"b", status);
|
||||||
|
symbols.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u".", status);
|
||||||
|
symbols.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"'", status);
|
||||||
|
|
||||||
|
UnicodeString standard = u"+-abcb''a''#,##0.0%'a%'";
|
||||||
|
UnicodeString localized = u"’.'ab'c'b''a'''#,##0a0b'a%'";
|
||||||
|
UnicodeString toStandard = u"+-'ab'c'b''a'''#,##0.0%'a%'";
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
"standard to localized",
|
||||||
|
localized,
|
||||||
|
PatternStringUtils::convertLocalized(standard, symbols, true, status));
|
||||||
|
assertEquals(
|
||||||
|
"localized to standard",
|
||||||
|
toStandard,
|
||||||
|
PatternStringUtils::convertLocalized(localized, symbols, false, status));
|
||||||
|
}
|
||||||
|
|
||||||
void PatternStringTest::testToPatternSimple() {
|
void PatternStringTest::testToPatternSimple() {
|
||||||
const char16_t *cases[][2] = {{u"#", u"0"},
|
const char16_t* cases[][2] = {{u"#", u"0"},
|
||||||
{u"0", u"0"},
|
{u"0", u"0"},
|
||||||
{u"#0", u"0"},
|
{u"#0", u"0"},
|
||||||
{u"###", u"0"},
|
{u"###", u"0"},
|
||||||
@ -42,12 +65,12 @@ void PatternStringTest::testToPatternSimple() {
|
|||||||
{u"*'நி'##0", u"*'நி'##0"},};
|
{u"*'நி'##0", u"*'நி'##0"},};
|
||||||
|
|
||||||
UErrorCode status = U_ZERO_ERROR;
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
for (const char16_t **cas : cases) {
|
for (const char16_t** cas : cases) {
|
||||||
UnicodeString input(cas[0]);
|
UnicodeString input(cas[0]);
|
||||||
UnicodeString output(cas[1]);
|
UnicodeString output(cas[1]);
|
||||||
|
|
||||||
DecimalFormatProperties properties = PatternParser::parseToProperties(
|
DecimalFormatProperties properties = PatternParser::parseToProperties(
|
||||||
input, PatternParser::IGNORE_ROUNDING_NEVER, status);
|
input, IGNORE_ROUNDING_NEVER, status);
|
||||||
assertSuccess(input, status);
|
assertSuccess(input, status);
|
||||||
UnicodeString actual = PatternStringUtils::propertiesToPatternString(properties, status);
|
UnicodeString actual = PatternStringUtils::propertiesToPatternString(properties, status);
|
||||||
assertEquals(input, output, actual);
|
assertEquals(input, output, actual);
|
||||||
@ -55,7 +78,7 @@ void PatternStringTest::testToPatternSimple() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PatternStringTest::testExceptionOnInvalid() {
|
void PatternStringTest::testExceptionOnInvalid() {
|
||||||
static const char16_t *invalidPatterns[] = {
|
static const char16_t* invalidPatterns[] = {
|
||||||
u"#.#.#",
|
u"#.#.#",
|
||||||
u"0#",
|
u"0#",
|
||||||
u"0#.",
|
u"0#.",
|
||||||
@ -80,13 +103,9 @@ void PatternStringTest::testExceptionOnInvalid() {
|
|||||||
void PatternStringTest::testBug13117() {
|
void PatternStringTest::testBug13117() {
|
||||||
UErrorCode status = U_ZERO_ERROR;
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
DecimalFormatProperties expected = PatternParser::parseToProperties(
|
DecimalFormatProperties expected = PatternParser::parseToProperties(
|
||||||
u"0",
|
u"0", IGNORE_ROUNDING_NEVER, status);
|
||||||
PatternParser::IGNORE_ROUNDING_NEVER,
|
|
||||||
status);
|
|
||||||
DecimalFormatProperties actual = PatternParser::parseToProperties(
|
DecimalFormatProperties actual = PatternParser::parseToProperties(
|
||||||
u"0;",
|
u"0;", IGNORE_ROUNDING_NEVER, status);
|
||||||
PatternParser::IGNORE_ROUNDING_NEVER,
|
|
||||||
status);
|
|
||||||
assertSuccess("Spot 1", status);
|
assertSuccess("Spot 1", status);
|
||||||
assertTrue("Should not consume negative subpattern", expected == actual);
|
assertTrue("Should not consume negative subpattern", expected == actual);
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ void UniSetsTest::testSetCoverage() {
|
|||||||
const UnicodeSet &minusSign = *get(unisets::MINUS_SIGN);
|
const UnicodeSet &minusSign = *get(unisets::MINUS_SIGN);
|
||||||
const UnicodeSet &percent = *get(unisets::PERCENT_SIGN);
|
const UnicodeSet &percent = *get(unisets::PERCENT_SIGN);
|
||||||
const UnicodeSet &permille = *get(unisets::PERMILLE_SIGN);
|
const UnicodeSet &permille = *get(unisets::PERMILLE_SIGN);
|
||||||
const UnicodeSet &infinity = *get(unisets::INFINITY);
|
const UnicodeSet &infinity = *get(unisets::INFINITY_KEY);
|
||||||
const UnicodeSet &nanLead = *get(unisets::NAN_LEAD);
|
const UnicodeSet &nanLead = *get(unisets::NAN_LEAD);
|
||||||
const UnicodeSet &scientificLead = *get(unisets::SCIENTIFIC_LEAD);
|
const UnicodeSet &scientificLead = *get(unisets::SCIENTIFIC_LEAD);
|
||||||
|
|
||||||
|
@ -1956,7 +1956,10 @@ public class DecimalFormat extends NumberFormat {
|
|||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public synchronized int getMinimumGroupingDigits() {
|
public synchronized int getMinimumGroupingDigits() {
|
||||||
return properties.getMinimumGroupingDigits();
|
if (properties.getMinimumGroupingDigits() > 0) {
|
||||||
|
return properties.getMinimumGroupingDigits();
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user