if (currentCount == fMacros.threshold && fMacros.threshold > 0) {
// Build the data structure and then use it (slow to fast path).
- const NumberFormatterImpl* compiled = NumberFormatterImpl::fromMacros(fMacros, status);
+ const NumberFormatterImpl* compiled = new NumberFormatterImpl(fMacros, status);
+ if (compiled == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return false;
+ }
U_ASSERT(fCompiled == nullptr);
const_cast<LocalizedNumberFormatter*>(this)->fCompiled = compiled;
umtx_storeRelease(*callCount, INT32_MIN);
MicroPropsGenerator::~MicroPropsGenerator() = default;
-NumberFormatterImpl* NumberFormatterImpl::fromMacros(const MacroProps& macros, UErrorCode& status) {
- return new NumberFormatterImpl(macros, true, status);
+NumberFormatterImpl::NumberFormatterImpl(const MacroProps& macros, UErrorCode& status)
+ : NumberFormatterImpl(macros, true, status) {
}
void NumberFormatterImpl::formatStatic(const MacroProps& macros, DecimalQuantity& inValue,
* Builds a "safe" MicroPropsGenerator, which is thread-safe and can be used repeatedly.
* The caller owns the returned NumberFormatterImpl.
*/
- static NumberFormatterImpl *fromMacros(const MacroProps ¯os, UErrorCode &status);
+ NumberFormatterImpl(const MacroProps ¯os, UErrorCode &status);
/**
* Builds and evaluates an "unsafe" MicroPropsGenerator, which is cheaper but can be used only once.
return FormattedNumberRange(status);
}
- formatImpl(results, status);
+ formatImpl(*results, first == second, status);
// Do not save the results object if we encountered a failure.
if (U_SUCCESS(status)) {
}
void LocalizedNumberRangeFormatter::formatImpl(
- UFormattedNumberRangeData* results, UErrorCode& status) const {
-
- MicroProps microsFirst;
- MicroProps microsSecond;
-
- UFormattedNumberData r1;
- r1.quantity = results->quantity1;
- fMacros.formatter1.locale(fMacros.locale).formatImpl(&r1, status);
- if (U_FAILURE(status)) {
- return;
+ UFormattedNumberRangeData& results, bool equalBeforeRounding, UErrorCode& status) const {
+ if (fImpl == nullptr) {
+ // TODO: Fix this once the atomic is ready!
+ auto* nonConstThis = const_cast<LocalizedNumberRangeFormatter*>(this);
+ nonConstThis->fImpl = new NumberRangeFormatterImpl(fMacros, status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (fImpl == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
}
- results->quantity1 = r1.quantity;
-
- UFormattedNumberData r2;
- r2.quantity = results->quantity2;
- fMacros.formatter2.locale(fMacros.locale).formatImpl(&r2, status);
- if (U_FAILURE(status)) {
- return;
- }
- results->quantity2 = r2.quantity;
-
- results->string.append(r1.string, status);
- results->string.append(u" --- ", UNUM_FIELD_COUNT, status);
- results->string.append(r2.string, status);
- if (U_FAILURE(status)) {
- return;
- }
-
- results->identityResult = UNUM_IDENTITY_RESULT_NOT_EQUAL;
+ fImpl->format(results, equalBeforeRounding, status);
}
// Helpful in toString methods and elsewhere.
#define UNISTR_FROM_STRING_EXPLICIT
+#include "unicode/numberrangeformatter.h"
#include "numrange_impl.h"
using namespace icu;
} // namespace
+
+NumberRangeFormatterImpl::NumberRangeFormatterImpl(const RangeMacroProps& macros, UErrorCode& status)
+ : formatterImpl1(macros.formatter1.fMacros, status),
+ formatterImpl2(macros.formatter2.fMacros, status),
+ fSameFormatters(true), // FIXME
+ fCollapse(macros.collapse),
+ fIdentityFallback(macros.identityFallback) {
+}
+
void NumberRangeFormatterImpl::format(UFormattedNumberRangeData& data, bool equalBeforeRounding, UErrorCode& status) const {
if (U_FAILURE(status)) {
return;
// TODO: Use localized pattern
lengthShared += string.insert(UPRV_INDEX_0, u" --- ", UNUM_FIELD_COUNT, status);
length1 += NumberFormatterImpl::writeNumber(micros1, data.quantity1, string, UPRV_INDEX_0, status);
- length2 += NumberFormatterImpl::writeNumber(micros2, data.quantity2, string, UPRV_INDEX_0, status);
+ length2 += NumberFormatterImpl::writeNumber(micros2, data.quantity2, string, UPRV_INDEX_2, status);
// TODO: Support padding?
class NumberRangeFormatterImpl : public UMemory {
public:
+ NumberRangeFormatterImpl(const RangeMacroProps& macros, UErrorCode& status);
+
void format(UFormattedNumberRangeData& data, bool equalBeforeRounding, UErrorCode& status) const;
private:
friend class LocalizedNumberFormatter;
friend class UnlocalizedNumberFormatter;
+
+ // Give NumberRangeFormatter access to the MacroProps
+ friend class impl::NumberRangeFormatterImpl;
};
/**
// To give NumberFormatter::with() access to this class's constructor:
friend class NumberFormatter;
-
- // Give NumberRangeFormatter access to the MacroProps
- friend class NumberRangeFormatterImpl;
};
/**
struct RangeMacroProps;
class DecimalQuantity;
struct UFormattedNumberRangeData;
+class NumberRangeFormatterImpl;
} // namespace impl
* Set if an error occurs while formatting.
* @internal
*/
- void formatImpl(impl::UFormattedNumberRangeData* results, UErrorCode& status) const;
+ void formatImpl(impl::UFormattedNumberRangeData& results, bool equalBeforeRounding,
+ UErrorCode& status) const;
#endif
~LocalizedNumberRangeFormatter();
private:
+ // TODO: This is not thread-safe! Do NOT check this in without an atomic here.
+ impl::NumberRangeFormatterImpl* fImpl = nullptr;
explicit LocalizedNumberRangeFormatter(
const NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>& other);
NumberRangeFormatter::with(),
Locale("en-us"),
u"1 --- 5",
- u"5 --- 5",
- u"5 --- 5",
+ u"~5",
+ u"~5",
u"0 --- 3",
- u"0 --- 0",
+ u"~0",
u"3 --- 3,000",
u"3,000 --- 5,000",
u"4,999 --- 5,001",
- u"5,000 --- 5,000",
+ u"~5,000",
u"5,000 --- 5,000,000");
}