2018-08-29 08:22:21 +00:00
|
|
|
// © 2018 and later: Unicode, Inc. and others.
|
|
|
|
// License & terms of use: http://www.unicode.org/copyright.html
|
|
|
|
|
|
|
|
#include "unicode/utypes.h"
|
|
|
|
|
2018-09-15 01:08:41 +00:00
|
|
|
#if !UCONFIG_NO_FORMATTING
|
2018-08-29 08:22:21 +00:00
|
|
|
|
|
|
|
// Allow implicit conversion from char16_t* to UnicodeString for this file:
|
|
|
|
// Helpful in toString methods and elsewhere.
|
|
|
|
#define UNISTR_FROM_STRING_EXPLICIT
|
|
|
|
|
2018-09-06 00:42:41 +00:00
|
|
|
#include "numrange_impl.h"
|
2018-08-29 08:22:21 +00:00
|
|
|
#include "util.h"
|
|
|
|
#include "number_utypes.h"
|
|
|
|
|
|
|
|
using namespace icu;
|
|
|
|
using namespace icu::number;
|
|
|
|
using namespace icu::number::impl;
|
|
|
|
|
|
|
|
|
2018-09-07 12:30:37 +00:00
|
|
|
// This function needs to be declared in this namespace so it can be friended.
|
|
|
|
// NOTE: In Java, this logic is handled in the resolve() function.
|
|
|
|
void icu::number::impl::touchRangeLocales(RangeMacroProps& macros) {
|
|
|
|
macros.formatter1.fMacros.locale = macros.locale;
|
|
|
|
macros.formatter2.fMacros.locale = macros.locale;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-29 08:22:21 +00:00
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::numberFormatterBoth(const UnlocalizedNumberFormatter& formatter) const& {
|
|
|
|
Derived copy(*this);
|
|
|
|
copy.fMacros.formatter1 = formatter;
|
2018-09-06 04:46:37 +00:00
|
|
|
copy.fMacros.singleFormatter = true;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(copy.fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::numberFormatterBoth(const UnlocalizedNumberFormatter& formatter) && {
|
|
|
|
Derived move(std::move(*this));
|
|
|
|
move.fMacros.formatter1 = formatter;
|
2018-09-06 04:46:37 +00:00
|
|
|
move.fMacros.singleFormatter = true;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(move.fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
return move;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::numberFormatterBoth(UnlocalizedNumberFormatter&& formatter) const& {
|
|
|
|
Derived copy(*this);
|
2018-09-06 04:46:37 +00:00
|
|
|
copy.fMacros.formatter1 = std::move(formatter);
|
|
|
|
copy.fMacros.singleFormatter = true;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(copy.fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::numberFormatterBoth(UnlocalizedNumberFormatter&& formatter) && {
|
|
|
|
Derived move(std::move(*this));
|
2018-09-06 04:46:37 +00:00
|
|
|
move.fMacros.formatter1 = std::move(formatter);
|
|
|
|
move.fMacros.singleFormatter = true;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(move.fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
return move;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::numberFormatterFirst(const UnlocalizedNumberFormatter& formatter) const& {
|
|
|
|
Derived copy(*this);
|
|
|
|
copy.fMacros.formatter1 = formatter;
|
2018-09-06 04:46:37 +00:00
|
|
|
copy.fMacros.singleFormatter = false;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(copy.fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::numberFormatterFirst(const UnlocalizedNumberFormatter& formatter) && {
|
|
|
|
Derived move(std::move(*this));
|
|
|
|
move.fMacros.formatter1 = formatter;
|
2018-09-06 04:46:37 +00:00
|
|
|
move.fMacros.singleFormatter = false;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(move.fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
return move;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::numberFormatterFirst(UnlocalizedNumberFormatter&& formatter) const& {
|
|
|
|
Derived copy(*this);
|
|
|
|
copy.fMacros.formatter1 = std::move(formatter);
|
2018-09-06 04:46:37 +00:00
|
|
|
copy.fMacros.singleFormatter = false;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(copy.fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::numberFormatterFirst(UnlocalizedNumberFormatter&& formatter) && {
|
|
|
|
Derived move(std::move(*this));
|
|
|
|
move.fMacros.formatter1 = std::move(formatter);
|
2018-09-06 04:46:37 +00:00
|
|
|
move.fMacros.singleFormatter = false;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(move.fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
return move;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::numberFormatterSecond(const UnlocalizedNumberFormatter& formatter) const& {
|
|
|
|
Derived copy(*this);
|
|
|
|
copy.fMacros.formatter2 = formatter;
|
2018-09-06 04:46:37 +00:00
|
|
|
copy.fMacros.singleFormatter = false;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(copy.fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::numberFormatterSecond(const UnlocalizedNumberFormatter& formatter) && {
|
|
|
|
Derived move(std::move(*this));
|
|
|
|
move.fMacros.formatter2 = formatter;
|
2018-09-06 04:46:37 +00:00
|
|
|
move.fMacros.singleFormatter = false;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(move.fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
return move;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::numberFormatterSecond(UnlocalizedNumberFormatter&& formatter) const& {
|
|
|
|
Derived copy(*this);
|
|
|
|
copy.fMacros.formatter2 = std::move(formatter);
|
2018-09-06 04:46:37 +00:00
|
|
|
copy.fMacros.singleFormatter = false;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(copy.fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::numberFormatterSecond(UnlocalizedNumberFormatter&& formatter) && {
|
|
|
|
Derived move(std::move(*this));
|
|
|
|
move.fMacros.formatter2 = std::move(formatter);
|
2018-09-06 04:46:37 +00:00
|
|
|
move.fMacros.singleFormatter = false;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(move.fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
return move;
|
|
|
|
}
|
|
|
|
|
2018-09-06 06:04:32 +00:00
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::collapse(UNumberRangeCollapse collapse) const& {
|
|
|
|
Derived copy(*this);
|
|
|
|
copy.fMacros.collapse = collapse;
|
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::collapse(UNumberRangeCollapse collapse) && {
|
|
|
|
Derived move(std::move(*this));
|
|
|
|
move.fMacros.collapse = collapse;
|
|
|
|
return move;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::identityFallback(UNumberRangeIdentityFallback identityFallback) const& {
|
|
|
|
Derived copy(*this);
|
|
|
|
copy.fMacros.identityFallback = identityFallback;
|
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Derived>
|
|
|
|
Derived NumberRangeFormatterSettings<Derived>::identityFallback(UNumberRangeIdentityFallback identityFallback) && {
|
|
|
|
Derived move(std::move(*this));
|
|
|
|
move.fMacros.identityFallback = identityFallback;
|
|
|
|
return move;
|
|
|
|
}
|
|
|
|
|
2018-08-29 08:22:21 +00:00
|
|
|
// Declare all classes that implement NumberRangeFormatterSettings
|
|
|
|
// See https://stackoverflow.com/a/495056/1407170
|
|
|
|
template
|
|
|
|
class icu::number::NumberRangeFormatterSettings<icu::number::UnlocalizedNumberRangeFormatter>;
|
|
|
|
template
|
|
|
|
class icu::number::NumberRangeFormatterSettings<icu::number::LocalizedNumberRangeFormatter>;
|
|
|
|
|
|
|
|
|
|
|
|
UnlocalizedNumberRangeFormatter NumberRangeFormatter::with() {
|
|
|
|
UnlocalizedNumberRangeFormatter result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
LocalizedNumberRangeFormatter NumberRangeFormatter::withLocale(const Locale& locale) {
|
|
|
|
return with().locale(locale);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T> using NFS = NumberRangeFormatterSettings<T>;
|
|
|
|
using LNF = LocalizedNumberRangeFormatter;
|
|
|
|
using UNF = UnlocalizedNumberRangeFormatter;
|
|
|
|
|
|
|
|
UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(const UNF& other)
|
|
|
|
: UNF(static_cast<const NFS<UNF>&>(other)) {}
|
|
|
|
|
|
|
|
UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(const NFS<UNF>& other)
|
|
|
|
: NFS<UNF>(other) {
|
|
|
|
// No additional fields to assign
|
|
|
|
}
|
|
|
|
|
2018-09-15 01:08:41 +00:00
|
|
|
// Make default copy constructor call the NumberRangeFormatterSettings copy constructor.
|
2018-08-29 08:22:21 +00:00
|
|
|
UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(UNF&& src) U_NOEXCEPT
|
|
|
|
: UNF(static_cast<NFS<UNF>&&>(src)) {}
|
|
|
|
|
|
|
|
UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(NFS<UNF>&& src) U_NOEXCEPT
|
|
|
|
: NFS<UNF>(std::move(src)) {
|
|
|
|
// No additional fields to assign
|
|
|
|
}
|
|
|
|
|
|
|
|
UnlocalizedNumberRangeFormatter& UnlocalizedNumberRangeFormatter::operator=(const UNF& other) {
|
|
|
|
NFS<UNF>::operator=(static_cast<const NFS<UNF>&>(other));
|
|
|
|
// No additional fields to assign
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
UnlocalizedNumberRangeFormatter& UnlocalizedNumberRangeFormatter::operator=(UNF&& src) U_NOEXCEPT {
|
|
|
|
NFS<UNF>::operator=(static_cast<NFS<UNF>&&>(src));
|
|
|
|
// No additional fields to assign
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2018-09-15 01:08:41 +00:00
|
|
|
// Make default copy constructor call the NumberRangeFormatterSettings copy constructor.
|
2018-08-29 08:22:21 +00:00
|
|
|
LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(const LNF& other)
|
|
|
|
: LNF(static_cast<const NFS<LNF>&>(other)) {}
|
|
|
|
|
|
|
|
LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(const NFS<LNF>& other)
|
|
|
|
: NFS<LNF>(other) {
|
|
|
|
// No additional fields to assign
|
|
|
|
}
|
|
|
|
|
|
|
|
LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT
|
|
|
|
: LNF(static_cast<NFS<LNF>&&>(src)) {}
|
|
|
|
|
|
|
|
LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(NFS<LNF>&& src) U_NOEXCEPT
|
|
|
|
: NFS<LNF>(std::move(src)) {
|
2018-09-18 09:14:24 +00:00
|
|
|
// Steal the compiled formatter
|
|
|
|
LNF&& _src = static_cast<LNF&&>(src);
|
2018-09-21 23:31:47 +00:00
|
|
|
auto* stolen = _src.fAtomicFormatter.exchange(nullptr);
|
|
|
|
delete fAtomicFormatter.exchange(stolen);
|
2018-08-29 08:22:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LocalizedNumberRangeFormatter& LocalizedNumberRangeFormatter::operator=(const LNF& other) {
|
|
|
|
NFS<LNF>::operator=(static_cast<const NFS<LNF>&>(other));
|
2018-09-18 09:14:24 +00:00
|
|
|
// Do not steal; just clear
|
2018-09-21 23:31:47 +00:00
|
|
|
delete fAtomicFormatter.exchange(nullptr);
|
2018-08-29 08:22:21 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
LocalizedNumberRangeFormatter& LocalizedNumberRangeFormatter::operator=(LNF&& src) U_NOEXCEPT {
|
|
|
|
NFS<LNF>::operator=(static_cast<NFS<LNF>&&>(src));
|
2018-09-18 09:14:24 +00:00
|
|
|
// Steal the compiled formatter
|
2018-09-21 23:31:47 +00:00
|
|
|
auto* stolen = src.fAtomicFormatter.exchange(nullptr);
|
|
|
|
delete fAtomicFormatter.exchange(stolen);
|
2018-08-29 08:22:21 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-06 06:47:58 +00:00
|
|
|
LocalizedNumberRangeFormatter::~LocalizedNumberRangeFormatter() {
|
2018-09-21 23:31:47 +00:00
|
|
|
delete fAtomicFormatter.exchange(nullptr);
|
2018-09-06 06:47:58 +00:00
|
|
|
}
|
2018-08-29 08:22:21 +00:00
|
|
|
|
|
|
|
LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(const RangeMacroProps& macros, const Locale& locale) {
|
|
|
|
fMacros = macros;
|
|
|
|
fMacros.locale = locale;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(RangeMacroProps&& macros, const Locale& locale) {
|
|
|
|
fMacros = std::move(macros);
|
|
|
|
fMacros.locale = locale;
|
2018-09-07 12:30:37 +00:00
|
|
|
touchRangeLocales(fMacros);
|
2018-08-29 08:22:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LocalizedNumberRangeFormatter UnlocalizedNumberRangeFormatter::locale(const Locale& locale) const& {
|
|
|
|
return LocalizedNumberRangeFormatter(fMacros, locale);
|
|
|
|
}
|
|
|
|
|
|
|
|
LocalizedNumberRangeFormatter UnlocalizedNumberRangeFormatter::locale(const Locale& locale)&& {
|
|
|
|
return LocalizedNumberRangeFormatter(std::move(fMacros), locale);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FormattedNumberRange LocalizedNumberRangeFormatter::formatFormattableRange(
|
|
|
|
const Formattable& first, const Formattable& second, UErrorCode& status) const {
|
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return FormattedNumberRange(U_ILLEGAL_ARGUMENT_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto results = new UFormattedNumberRangeData();
|
|
|
|
if (results == nullptr) {
|
|
|
|
status = U_MEMORY_ALLOCATION_ERROR;
|
|
|
|
return FormattedNumberRange(status);
|
|
|
|
}
|
|
|
|
|
|
|
|
first.populateDecimalQuantity(results->quantity1, status);
|
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return FormattedNumberRange(status);
|
|
|
|
}
|
|
|
|
|
|
|
|
second.populateDecimalQuantity(results->quantity2, status);
|
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return FormattedNumberRange(status);
|
|
|
|
}
|
|
|
|
|
2018-09-06 01:37:48 +00:00
|
|
|
formatImpl(*results, first == second, status);
|
2018-08-29 08:22:21 +00:00
|
|
|
|
|
|
|
// Do not save the results object if we encountered a failure.
|
|
|
|
if (U_SUCCESS(status)) {
|
|
|
|
return FormattedNumberRange(results);
|
|
|
|
} else {
|
|
|
|
delete results;
|
|
|
|
return FormattedNumberRange(status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LocalizedNumberRangeFormatter::formatImpl(
|
2018-09-06 01:37:48 +00:00
|
|
|
UFormattedNumberRangeData& results, bool equalBeforeRounding, UErrorCode& status) const {
|
2018-09-21 23:31:47 +00:00
|
|
|
auto* impl = getFormatter(status);
|
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (impl == nullptr) {
|
|
|
|
status = U_INTERNAL_PROGRAM_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
impl->format(results, equalBeforeRounding, status);
|
|
|
|
}
|
|
|
|
|
|
|
|
const impl::NumberRangeFormatterImpl*
|
|
|
|
LocalizedNumberRangeFormatter::getFormatter(UErrorCode& status) const {
|
|
|
|
// TODO: Move this into umutex.h? (similar logic also in decimfmt.cpp)
|
|
|
|
// See ICU-20146
|
|
|
|
|
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// First try to get the pre-computed formatter
|
|
|
|
auto* ptr = fAtomicFormatter.load();
|
|
|
|
if (ptr != nullptr) {
|
|
|
|
return ptr;
|
2018-08-29 08:22:21 +00:00
|
|
|
}
|
2018-09-21 23:31:47 +00:00
|
|
|
|
|
|
|
// Try computing the formatter on our own
|
|
|
|
auto* temp = new NumberRangeFormatterImpl(fMacros, status);
|
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (temp == nullptr) {
|
|
|
|
status = U_MEMORY_ALLOCATION_ERROR;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note: ptr starts as nullptr; during compare_exchange,
|
|
|
|
// it is set to what is actually stored in the atomic
|
|
|
|
// if another thread beat us to computing the formatter object.
|
|
|
|
auto* nonConstThis = const_cast<LocalizedNumberRangeFormatter*>(this);
|
|
|
|
if (!nonConstThis->fAtomicFormatter.compare_exchange_strong(ptr, temp)) {
|
|
|
|
// Another thread beat us to computing the formatter
|
|
|
|
delete temp;
|
|
|
|
return ptr;
|
|
|
|
} else {
|
|
|
|
// Our copy of the formatter got stored in the atomic
|
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
2018-08-29 08:22:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FormattedNumberRange::FormattedNumberRange(FormattedNumberRange&& src) U_NOEXCEPT
|
|
|
|
: fResults(src.fResults), fErrorCode(src.fErrorCode) {
|
|
|
|
// Disown src.fResults to prevent double-deletion
|
|
|
|
src.fResults = nullptr;
|
|
|
|
src.fErrorCode = U_INVALID_STATE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
FormattedNumberRange& FormattedNumberRange::operator=(FormattedNumberRange&& src) U_NOEXCEPT {
|
|
|
|
delete fResults;
|
|
|
|
fResults = src.fResults;
|
|
|
|
fErrorCode = src.fErrorCode;
|
|
|
|
// Disown src.fResults to prevent double-deletion
|
|
|
|
src.fResults = nullptr;
|
|
|
|
src.fErrorCode = U_INVALID_STATE_ERROR;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
UnicodeString FormattedNumberRange::toString(UErrorCode& status) const {
|
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return ICU_Utility::makeBogusString();
|
|
|
|
}
|
|
|
|
if (fResults == nullptr) {
|
|
|
|
status = fErrorCode;
|
|
|
|
return ICU_Utility::makeBogusString();
|
|
|
|
}
|
|
|
|
return fResults->string.toUnicodeString();
|
|
|
|
}
|
|
|
|
|
2018-08-30 23:20:13 +00:00
|
|
|
Appendable& FormattedNumberRange::appendTo(Appendable& appendable, UErrorCode& status) const {
|
2018-08-29 08:22:21 +00:00
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return appendable;
|
|
|
|
}
|
|
|
|
if (fResults == nullptr) {
|
|
|
|
status = fErrorCode;
|
|
|
|
return appendable;
|
|
|
|
}
|
|
|
|
appendable.appendString(fResults->string.chars(), fResults->string.length());
|
|
|
|
return appendable;
|
|
|
|
}
|
|
|
|
|
|
|
|
UBool FormattedNumberRange::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const {
|
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (fResults == nullptr) {
|
|
|
|
status = fErrorCode;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
// NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
|
|
|
|
return fResults->string.nextFieldPosition(fieldPosition, status) ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FormattedNumberRange::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const {
|
|
|
|
FieldPositionIteratorHandler fpih(&iterator, status);
|
|
|
|
getAllFieldPositionsImpl(fpih, status);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FormattedNumberRange::getAllFieldPositionsImpl(
|
|
|
|
FieldPositionIteratorHandler& fpih, UErrorCode& status) const {
|
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (fResults == nullptr) {
|
|
|
|
status = fErrorCode;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fResults->string.getAllFieldPositions(fpih, status);
|
|
|
|
}
|
|
|
|
|
|
|
|
UnicodeString FormattedNumberRange::getFirstDecimal(UErrorCode& status) const {
|
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return ICU_Utility::makeBogusString();
|
|
|
|
}
|
|
|
|
if (fResults == nullptr) {
|
|
|
|
status = fErrorCode;
|
|
|
|
return ICU_Utility::makeBogusString();
|
|
|
|
}
|
|
|
|
return fResults->quantity1.toScientificString();
|
|
|
|
}
|
|
|
|
|
|
|
|
UnicodeString FormattedNumberRange::getSecondDecimal(UErrorCode& status) const {
|
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return ICU_Utility::makeBogusString();
|
|
|
|
}
|
|
|
|
if (fResults == nullptr) {
|
|
|
|
status = fErrorCode;
|
|
|
|
return ICU_Utility::makeBogusString();
|
|
|
|
}
|
|
|
|
return fResults->quantity2.toScientificString();
|
|
|
|
}
|
|
|
|
|
2018-08-30 00:42:17 +00:00
|
|
|
UNumberRangeIdentityResult FormattedNumberRange::getIdentityResult(UErrorCode& status) const {
|
2018-08-29 08:22:21 +00:00
|
|
|
if (U_FAILURE(status)) {
|
2018-08-30 00:42:17 +00:00
|
|
|
return UNUM_IDENTITY_RESULT_NOT_EQUAL;
|
2018-08-29 08:22:21 +00:00
|
|
|
}
|
|
|
|
if (fResults == nullptr) {
|
|
|
|
status = fErrorCode;
|
2018-08-30 00:42:17 +00:00
|
|
|
return UNUM_IDENTITY_RESULT_NOT_EQUAL;
|
2018-08-29 08:22:21 +00:00
|
|
|
}
|
2018-08-30 00:42:17 +00:00
|
|
|
return fResults->identityResult;
|
2018-08-29 08:22:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FormattedNumberRange::~FormattedNumberRange() {
|
|
|
|
delete fResults;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* #if !UCONFIG_NO_FORMATTING */
|