Home | History | Annotate | Download | only in i18n
      1 //  2017 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 
      4 #include "unicode/utypes.h"
      5 
      6 #if !UCONFIG_NO_FORMATTING
      7 
      8 #include "uassert.h"
      9 #include "unicode/numberformatter.h"
     10 #include "number_decimalquantity.h"
     11 #include "number_formatimpl.h"
     12 #include "umutex.h"
     13 #include "number_asformat.h"
     14 #include "number_skeletons.h"
     15 #include "number_utils.h"
     16 #include "number_utypes.h"
     17 #include "util.h"
     18 #include "fphdlimp.h"
     19 
     20 using namespace icu;
     21 using namespace icu::number;
     22 using namespace icu::number::impl;
     23 
     24 template<typename Derived>
     25 Derived NumberFormatterSettings<Derived>::notation(const Notation& notation) const& {
     26     Derived copy(*this);
     27     // NOTE: Slicing is OK.
     28     copy.fMacros.notation = notation;
     29     return copy;
     30 }
     31 
     32 template<typename Derived>
     33 Derived NumberFormatterSettings<Derived>::notation(const Notation& notation)&& {
     34     Derived move(std::move(*this));
     35     // NOTE: Slicing is OK.
     36     move.fMacros.notation = notation;
     37     return move;
     38 }
     39 
     40 template<typename Derived>
     41 Derived NumberFormatterSettings<Derived>::unit(const icu::MeasureUnit& unit) const& {
     42     Derived copy(*this);
     43     // NOTE: Slicing occurs here. However, CurrencyUnit can be restored from MeasureUnit.
     44     // TimeUnit may be affected, but TimeUnit is not as relevant to number formatting.
     45     copy.fMacros.unit = unit;
     46     return copy;
     47 }
     48 
     49 template<typename Derived>
     50 Derived NumberFormatterSettings<Derived>::unit(const icu::MeasureUnit& unit)&& {
     51     Derived move(std::move(*this));
     52     // See comments above about slicing.
     53     move.fMacros.unit = unit;
     54     return move;
     55 }
     56 
     57 template<typename Derived>
     58 Derived NumberFormatterSettings<Derived>::adoptUnit(icu::MeasureUnit* unit) const& {
     59     Derived copy(*this);
     60     // Just move the unit into the MacroProps by value, and delete it since we have ownership.
     61     // NOTE: Slicing occurs here. However, CurrencyUnit can be restored from MeasureUnit.
     62     // TimeUnit may be affected, but TimeUnit is not as relevant to number formatting.
     63     if (unit != nullptr) {
     64         // TODO: On nullptr, reset to default value?
     65         copy.fMacros.unit = std::move(*unit);
     66         delete unit;
     67     }
     68     return copy;
     69 }
     70 
     71 template<typename Derived>
     72 Derived NumberFormatterSettings<Derived>::adoptUnit(icu::MeasureUnit* unit)&& {
     73     Derived move(std::move(*this));
     74     // See comments above about slicing and ownership.
     75     if (unit != nullptr) {
     76         // TODO: On nullptr, reset to default value?
     77         move.fMacros.unit = std::move(*unit);
     78         delete unit;
     79     }
     80     return move;
     81 }
     82 
     83 template<typename Derived>
     84 Derived NumberFormatterSettings<Derived>::perUnit(const icu::MeasureUnit& perUnit) const& {
     85     Derived copy(*this);
     86     // See comments above about slicing.
     87     copy.fMacros.perUnit = perUnit;
     88     return copy;
     89 }
     90 
     91 template<typename Derived>
     92 Derived NumberFormatterSettings<Derived>::perUnit(const icu::MeasureUnit& perUnit)&& {
     93     Derived move(std::move(*this));
     94     // See comments above about slicing.
     95     move.fMacros.perUnit = perUnit;
     96     return move;
     97 }
     98 
     99 template<typename Derived>
    100 Derived NumberFormatterSettings<Derived>::adoptPerUnit(icu::MeasureUnit* perUnit) const& {
    101     Derived copy(*this);
    102     // See comments above about slicing and ownership.
    103     if (perUnit != nullptr) {
    104         // TODO: On nullptr, reset to default value?
    105         copy.fMacros.perUnit = std::move(*perUnit);
    106         delete perUnit;
    107     }
    108     return copy;
    109 }
    110 
    111 template<typename Derived>
    112 Derived NumberFormatterSettings<Derived>::adoptPerUnit(icu::MeasureUnit* perUnit)&& {
    113     Derived move(std::move(*this));
    114     // See comments above about slicing and ownership.
    115     if (perUnit != nullptr) {
    116         // TODO: On nullptr, reset to default value?
    117         move.fMacros.perUnit = std::move(*perUnit);
    118         delete perUnit;
    119     }
    120     return move;
    121 }
    122 
    123 template<typename Derived>
    124 Derived NumberFormatterSettings<Derived>::precision(const Precision& precision) const& {
    125     Derived copy(*this);
    126     // NOTE: Slicing is OK.
    127     copy.fMacros.precision = precision;
    128     return copy;
    129 }
    130 
    131 template<typename Derived>
    132 Derived NumberFormatterSettings<Derived>::precision(const Precision& precision)&& {
    133     Derived move(std::move(*this));
    134     // NOTE: Slicing is OK.
    135     move.fMacros.precision = precision;
    136     return move;
    137 }
    138 
    139 template<typename Derived>
    140 Derived NumberFormatterSettings<Derived>::roundingMode(UNumberFormatRoundingMode roundingMode) const& {
    141     Derived copy(*this);
    142     copy.fMacros.roundingMode = roundingMode;
    143     return copy;
    144 }
    145 
    146 template<typename Derived>
    147 Derived NumberFormatterSettings<Derived>::roundingMode(UNumberFormatRoundingMode roundingMode)&& {
    148     Derived move(std::move(*this));
    149     move.fMacros.roundingMode = roundingMode;
    150     return move;
    151 }
    152 
    153 template<typename Derived>
    154 Derived NumberFormatterSettings<Derived>::grouping(UGroupingStrategy strategy) const& {
    155     Derived copy(*this);
    156     // NOTE: This is slightly different than how the setting is stored in Java
    157     // because we want to put it on the stack.
    158     copy.fMacros.grouper = Grouper::forStrategy(strategy);
    159     return copy;
    160 }
    161 
    162 template<typename Derived>
    163 Derived NumberFormatterSettings<Derived>::grouping(UGroupingStrategy strategy)&& {
    164     Derived move(std::move(*this));
    165     move.fMacros.grouper = Grouper::forStrategy(strategy);
    166     return move;
    167 }
    168 
    169 template<typename Derived>
    170 Derived NumberFormatterSettings<Derived>::integerWidth(const IntegerWidth& style) const& {
    171     Derived copy(*this);
    172     copy.fMacros.integerWidth = style;
    173     return copy;
    174 }
    175 
    176 template<typename Derived>
    177 Derived NumberFormatterSettings<Derived>::integerWidth(const IntegerWidth& style)&& {
    178     Derived move(std::move(*this));
    179     move.fMacros.integerWidth = style;
    180     return move;
    181 }
    182 
    183 template<typename Derived>
    184 Derived NumberFormatterSettings<Derived>::symbols(const DecimalFormatSymbols& symbols) const& {
    185     Derived copy(*this);
    186     copy.fMacros.symbols.setTo(symbols);
    187     return copy;
    188 }
    189 
    190 template<typename Derived>
    191 Derived NumberFormatterSettings<Derived>::symbols(const DecimalFormatSymbols& symbols)&& {
    192     Derived move(std::move(*this));
    193     move.fMacros.symbols.setTo(symbols);
    194     return move;
    195 }
    196 
    197 template<typename Derived>
    198 Derived NumberFormatterSettings<Derived>::adoptSymbols(NumberingSystem* ns) const& {
    199     Derived copy(*this);
    200     copy.fMacros.symbols.setTo(ns);
    201     return copy;
    202 }
    203 
    204 template<typename Derived>
    205 Derived NumberFormatterSettings<Derived>::adoptSymbols(NumberingSystem* ns)&& {
    206     Derived move(std::move(*this));
    207     move.fMacros.symbols.setTo(ns);
    208     return move;
    209 }
    210 
    211 template<typename Derived>
    212 Derived NumberFormatterSettings<Derived>::unitWidth(UNumberUnitWidth width) const& {
    213     Derived copy(*this);
    214     copy.fMacros.unitWidth = width;
    215     return copy;
    216 }
    217 
    218 template<typename Derived>
    219 Derived NumberFormatterSettings<Derived>::unitWidth(UNumberUnitWidth width)&& {
    220     Derived move(std::move(*this));
    221     move.fMacros.unitWidth = width;
    222     return move;
    223 }
    224 
    225 template<typename Derived>
    226 Derived NumberFormatterSettings<Derived>::sign(UNumberSignDisplay style) const& {
    227     Derived copy(*this);
    228     copy.fMacros.sign = style;
    229     return copy;
    230 }
    231 
    232 template<typename Derived>
    233 Derived NumberFormatterSettings<Derived>::sign(UNumberSignDisplay style)&& {
    234     Derived move(std::move(*this));
    235     move.fMacros.sign = style;
    236     return move;
    237 }
    238 
    239 template<typename Derived>
    240 Derived NumberFormatterSettings<Derived>::decimal(UNumberDecimalSeparatorDisplay style) const& {
    241     Derived copy(*this);
    242     copy.fMacros.decimal = style;
    243     return copy;
    244 }
    245 
    246 template<typename Derived>
    247 Derived NumberFormatterSettings<Derived>::decimal(UNumberDecimalSeparatorDisplay style)&& {
    248     Derived move(std::move(*this));
    249     move.fMacros.decimal = style;
    250     return move;
    251 }
    252 
    253 template<typename Derived>
    254 Derived NumberFormatterSettings<Derived>::scale(const Scale& scale) const& {
    255     Derived copy(*this);
    256     copy.fMacros.scale = scale;
    257     return copy;
    258 }
    259 
    260 template<typename Derived>
    261 Derived NumberFormatterSettings<Derived>::scale(const Scale& scale)&& {
    262     Derived move(std::move(*this));
    263     move.fMacros.scale = scale;
    264     return move;
    265 }
    266 
    267 template<typename Derived>
    268 Derived NumberFormatterSettings<Derived>::padding(const Padder& padder) const& {
    269     Derived copy(*this);
    270     copy.fMacros.padder = padder;
    271     return copy;
    272 }
    273 
    274 template<typename Derived>
    275 Derived NumberFormatterSettings<Derived>::padding(const Padder& padder)&& {
    276     Derived move(std::move(*this));
    277     move.fMacros.padder = padder;
    278     return move;
    279 }
    280 
    281 template<typename Derived>
    282 Derived NumberFormatterSettings<Derived>::threshold(int32_t threshold) const& {
    283     Derived copy(*this);
    284     copy.fMacros.threshold = threshold;
    285     return copy;
    286 }
    287 
    288 template<typename Derived>
    289 Derived NumberFormatterSettings<Derived>::threshold(int32_t threshold)&& {
    290     Derived move(std::move(*this));
    291     move.fMacros.threshold = threshold;
    292     return move;
    293 }
    294 
    295 template<typename Derived>
    296 Derived NumberFormatterSettings<Derived>::macros(const impl::MacroProps& macros) const& {
    297     Derived copy(*this);
    298     copy.fMacros = macros;
    299     return copy;
    300 }
    301 
    302 template<typename Derived>
    303 Derived NumberFormatterSettings<Derived>::macros(const impl::MacroProps& macros)&& {
    304     Derived move(std::move(*this));
    305     move.fMacros = macros;
    306     return move;
    307 }
    308 
    309 template<typename Derived>
    310 Derived NumberFormatterSettings<Derived>::macros(impl::MacroProps&& macros) const& {
    311     Derived copy(*this);
    312     copy.fMacros = std::move(macros);
    313     return copy;
    314 }
    315 
    316 template<typename Derived>
    317 Derived NumberFormatterSettings<Derived>::macros(impl::MacroProps&& macros)&& {
    318     Derived move(std::move(*this));
    319     move.fMacros = std::move(macros);
    320     return move;
    321 }
    322 
    323 template<typename Derived>
    324 UnicodeString NumberFormatterSettings<Derived>::toSkeleton(UErrorCode& status) const {
    325     if (fMacros.copyErrorTo(status)) {
    326         return ICU_Utility::makeBogusString();
    327     }
    328     return skeleton::generate(fMacros, status);
    329 }
    330 
    331 // Declare all classes that implement NumberFormatterSettings
    332 // See https://stackoverflow.com/a/495056/1407170
    333 template
    334 class icu::number::NumberFormatterSettings<icu::number::UnlocalizedNumberFormatter>;
    335 template
    336 class icu::number::NumberFormatterSettings<icu::number::LocalizedNumberFormatter>;
    337 
    338 
    339 UnlocalizedNumberFormatter NumberFormatter::with() {
    340     UnlocalizedNumberFormatter result;
    341     return result;
    342 }
    343 
    344 LocalizedNumberFormatter NumberFormatter::withLocale(const Locale& locale) {
    345     return with().locale(locale);
    346 }
    347 
    348 UnlocalizedNumberFormatter
    349 NumberFormatter::forSkeleton(const UnicodeString& skeleton, UErrorCode& status) {
    350     return skeleton::create(skeleton, status);
    351 }
    352 
    353 
    354 template<typename T> using NFS = NumberFormatterSettings<T>;
    355 using LNF = LocalizedNumberFormatter;
    356 using UNF = UnlocalizedNumberFormatter;
    357 
    358 UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const UNF& other)
    359         : UNF(static_cast<const NFS<UNF>&>(other)) {}
    360 
    361 UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const NFS<UNF>& other)
    362         : NFS<UNF>(other) {
    363     // No additional fields to assign
    364 }
    365 
    366 // Make default copy constructor call the NumberFormatterSettings copy constructor.
    367 UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(UNF&& src) U_NOEXCEPT
    368         : UNF(static_cast<NFS<UNF>&&>(src)) {}
    369 
    370 UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(NFS<UNF>&& src) U_NOEXCEPT
    371         : NFS<UNF>(std::move(src)) {
    372     // No additional fields to assign
    373 }
    374 
    375 UnlocalizedNumberFormatter& UnlocalizedNumberFormatter::operator=(const UNF& other) {
    376     NFS<UNF>::operator=(static_cast<const NFS<UNF>&>(other));
    377     // No additional fields to assign
    378     return *this;
    379 }
    380 
    381 UnlocalizedNumberFormatter& UnlocalizedNumberFormatter::operator=(UNF&& src) U_NOEXCEPT {
    382     NFS<UNF>::operator=(static_cast<NFS<UNF>&&>(src));
    383     // No additional fields to assign
    384     return *this;
    385 }
    386 
    387 // Make default copy constructor call the NumberFormatterSettings copy constructor.
    388 LocalizedNumberFormatter::LocalizedNumberFormatter(const LNF& other)
    389         : LNF(static_cast<const NFS<LNF>&>(other)) {}
    390 
    391 LocalizedNumberFormatter::LocalizedNumberFormatter(const NFS<LNF>& other)
    392         : NFS<LNF>(other) {
    393     // No additional fields to assign (let call count and compiled formatter reset to defaults)
    394 }
    395 
    396 LocalizedNumberFormatter::LocalizedNumberFormatter(LocalizedNumberFormatter&& src) U_NOEXCEPT
    397         : LNF(static_cast<NFS<LNF>&&>(src)) {}
    398 
    399 LocalizedNumberFormatter::LocalizedNumberFormatter(NFS<LNF>&& src) U_NOEXCEPT
    400         : NFS<LNF>(std::move(src)) {
    401     // For the move operators, copy over the compiled formatter.
    402     // Note: if the formatter is not compiled, call count information is lost.
    403     if (static_cast<LNF&&>(src).fCompiled != nullptr) {
    404         lnfMoveHelper(static_cast<LNF&&>(src));
    405     }
    406 }
    407 
    408 LocalizedNumberFormatter& LocalizedNumberFormatter::operator=(const LNF& other) {
    409     NFS<LNF>::operator=(static_cast<const NFS<LNF>&>(other));
    410     // Reset to default values.
    411     clear();
    412     return *this;
    413 }
    414 
    415 LocalizedNumberFormatter& LocalizedNumberFormatter::operator=(LNF&& src) U_NOEXCEPT {
    416     NFS<LNF>::operator=(static_cast<NFS<LNF>&&>(src));
    417     // For the move operators, copy over the compiled formatter.
    418     // Note: if the formatter is not compiled, call count information is lost.
    419     if (static_cast<LNF&&>(src).fCompiled != nullptr) {
    420         // Formatter is compiled
    421         lnfMoveHelper(static_cast<LNF&&>(src));
    422     } else {
    423         clear();
    424     }
    425     return *this;
    426 }
    427 
    428 void LocalizedNumberFormatter::clear() {
    429     // Reset to default values.
    430     auto* callCount = reinterpret_cast<u_atomic_int32_t*>(fUnsafeCallCount);
    431     umtx_storeRelease(*callCount, 0);
    432     delete fCompiled;
    433     fCompiled = nullptr;
    434 }
    435 
    436 void LocalizedNumberFormatter::lnfMoveHelper(LNF&& src) {
    437     // Copy over the compiled formatter and set call count to INT32_MIN as in computeCompiled().
    438     // Don't copy the call count directly because doing so requires a loadAcquire/storeRelease.
    439     // The bits themselves appear to be platform-dependent, so copying them might not be safe.
    440     auto* callCount = reinterpret_cast<u_atomic_int32_t*>(fUnsafeCallCount);
    441     umtx_storeRelease(*callCount, INT32_MIN);
    442     delete fCompiled;
    443     fCompiled = src.fCompiled;
    444     // Reset the source object to leave it in a safe state.
    445     auto* srcCallCount = reinterpret_cast<u_atomic_int32_t*>(src.fUnsafeCallCount);
    446     umtx_storeRelease(*srcCallCount, 0);
    447     src.fCompiled = nullptr;
    448 }
    449 
    450 
    451 LocalizedNumberFormatter::~LocalizedNumberFormatter() {
    452     delete fCompiled;
    453 }
    454 
    455 LocalizedNumberFormatter::LocalizedNumberFormatter(const MacroProps& macros, const Locale& locale) {
    456     fMacros = macros;
    457     fMacros.locale = locale;
    458 }
    459 
    460 LocalizedNumberFormatter::LocalizedNumberFormatter(MacroProps&& macros, const Locale& locale) {
    461     fMacros = std::move(macros);
    462     fMacros.locale = locale;
    463 }
    464 
    465 LocalizedNumberFormatter UnlocalizedNumberFormatter::locale(const Locale& locale) const& {
    466     return LocalizedNumberFormatter(fMacros, locale);
    467 }
    468 
    469 LocalizedNumberFormatter UnlocalizedNumberFormatter::locale(const Locale& locale)&& {
    470     return LocalizedNumberFormatter(std::move(fMacros), locale);
    471 }
    472 
    473 SymbolsWrapper::SymbolsWrapper(const SymbolsWrapper& other) {
    474     doCopyFrom(other);
    475 }
    476 
    477 SymbolsWrapper::SymbolsWrapper(SymbolsWrapper&& src) U_NOEXCEPT {
    478     doMoveFrom(std::move(src));
    479 }
    480 
    481 SymbolsWrapper& SymbolsWrapper::operator=(const SymbolsWrapper& other) {
    482     if (this == &other) {
    483         return *this;
    484     }
    485     doCleanup();
    486     doCopyFrom(other);
    487     return *this;
    488 }
    489 
    490 SymbolsWrapper& SymbolsWrapper::operator=(SymbolsWrapper&& src) U_NOEXCEPT {
    491     if (this == &src) {
    492         return *this;
    493     }
    494     doCleanup();
    495     doMoveFrom(std::move(src));
    496     return *this;
    497 }
    498 
    499 SymbolsWrapper::~SymbolsWrapper() {
    500     doCleanup();
    501 }
    502 
    503 void SymbolsWrapper::setTo(const DecimalFormatSymbols& dfs) {
    504     doCleanup();
    505     fType = SYMPTR_DFS;
    506     fPtr.dfs = new DecimalFormatSymbols(dfs);
    507 }
    508 
    509 void SymbolsWrapper::setTo(const NumberingSystem* ns) {
    510     doCleanup();
    511     fType = SYMPTR_NS;
    512     fPtr.ns = ns;
    513 }
    514 
    515 void SymbolsWrapper::doCopyFrom(const SymbolsWrapper& other) {
    516     fType = other.fType;
    517     switch (fType) {
    518         case SYMPTR_NONE:
    519             // No action necessary
    520             break;
    521         case SYMPTR_DFS:
    522             // Memory allocation failures are exposed in copyErrorTo()
    523             if (other.fPtr.dfs != nullptr) {
    524                 fPtr.dfs = new DecimalFormatSymbols(*other.fPtr.dfs);
    525             } else {
    526                 fPtr.dfs = nullptr;
    527             }
    528             break;
    529         case SYMPTR_NS:
    530             // Memory allocation failures are exposed in copyErrorTo()
    531             if (other.fPtr.ns != nullptr) {
    532                 fPtr.ns = new NumberingSystem(*other.fPtr.ns);
    533             } else {
    534                 fPtr.ns = nullptr;
    535             }
    536             break;
    537     }
    538 }
    539 
    540 void SymbolsWrapper::doMoveFrom(SymbolsWrapper&& src) {
    541     fType = src.fType;
    542     switch (fType) {
    543         case SYMPTR_NONE:
    544             // No action necessary
    545             break;
    546         case SYMPTR_DFS:
    547             fPtr.dfs = src.fPtr.dfs;
    548             src.fPtr.dfs = nullptr;
    549             break;
    550         case SYMPTR_NS:
    551             fPtr.ns = src.fPtr.ns;
    552             src.fPtr.ns = nullptr;
    553             break;
    554     }
    555 }
    556 
    557 void SymbolsWrapper::doCleanup() {
    558     switch (fType) {
    559         case SYMPTR_NONE:
    560             // No action necessary
    561             break;
    562         case SYMPTR_DFS:
    563             delete fPtr.dfs;
    564             break;
    565         case SYMPTR_NS:
    566             delete fPtr.ns;
    567             break;
    568     }
    569 }
    570 
    571 bool SymbolsWrapper::isDecimalFormatSymbols() const {
    572     return fType == SYMPTR_DFS;
    573 }
    574 
    575 bool SymbolsWrapper::isNumberingSystem() const {
    576     return fType == SYMPTR_NS;
    577 }
    578 
    579 const DecimalFormatSymbols* SymbolsWrapper::getDecimalFormatSymbols() const {
    580     U_ASSERT(fType == SYMPTR_DFS);
    581     return fPtr.dfs;
    582 }
    583 
    584 const NumberingSystem* SymbolsWrapper::getNumberingSystem() const {
    585     U_ASSERT(fType == SYMPTR_NS);
    586     return fPtr.ns;
    587 }
    588 
    589 
    590 FormattedNumber LocalizedNumberFormatter::formatInt(int64_t value, UErrorCode& status) const {
    591     if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); }
    592     auto results = new UFormattedNumberData();
    593     if (results == nullptr) {
    594         status = U_MEMORY_ALLOCATION_ERROR;
    595         return FormattedNumber(status);
    596     }
    597     results->quantity.setToLong(value);
    598     formatImpl(results, status);
    599 
    600     // Do not save the results object if we encountered a failure.
    601     if (U_SUCCESS(status)) {
    602         return FormattedNumber(results);
    603     } else {
    604         delete results;
    605         return FormattedNumber(status);
    606     }
    607 }
    608 
    609 FormattedNumber LocalizedNumberFormatter::formatDouble(double value, UErrorCode& status) const {
    610     if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); }
    611     auto results = new UFormattedNumberData();
    612     if (results == nullptr) {
    613         status = U_MEMORY_ALLOCATION_ERROR;
    614         return FormattedNumber(status);
    615     }
    616     results->quantity.setToDouble(value);
    617     formatImpl(results, status);
    618 
    619     // Do not save the results object if we encountered a failure.
    620     if (U_SUCCESS(status)) {
    621         return FormattedNumber(results);
    622     } else {
    623         delete results;
    624         return FormattedNumber(status);
    625     }
    626 }
    627 
    628 FormattedNumber LocalizedNumberFormatter::formatDecimal(StringPiece value, UErrorCode& status) const {
    629     if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); }
    630     auto results = new UFormattedNumberData();
    631     if (results == nullptr) {
    632         status = U_MEMORY_ALLOCATION_ERROR;
    633         return FormattedNumber(status);
    634     }
    635     results->quantity.setToDecNumber(value, status);
    636     formatImpl(results, status);
    637 
    638     // Do not save the results object if we encountered a failure.
    639     if (U_SUCCESS(status)) {
    640         return FormattedNumber(results);
    641     } else {
    642         delete results;
    643         return FormattedNumber(status);
    644     }
    645 }
    646 
    647 FormattedNumber
    648 LocalizedNumberFormatter::formatDecimalQuantity(const DecimalQuantity& dq, UErrorCode& status) const {
    649     if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); }
    650     auto results = new UFormattedNumberData();
    651     if (results == nullptr) {
    652         status = U_MEMORY_ALLOCATION_ERROR;
    653         return FormattedNumber(status);
    654     }
    655     results->quantity = dq;
    656     formatImpl(results, status);
    657 
    658     // Do not save the results object if we encountered a failure.
    659     if (U_SUCCESS(status)) {
    660         return FormattedNumber(results);
    661     } else {
    662         delete results;
    663         return FormattedNumber(status);
    664     }
    665 }
    666 
    667 void LocalizedNumberFormatter::formatImpl(impl::UFormattedNumberData* results, UErrorCode& status) const {
    668     if (computeCompiled(status)) {
    669         fCompiled->format(results->quantity, results->string, status);
    670     } else {
    671         NumberFormatterImpl::formatStatic(fMacros, results->quantity, results->string, status);
    672     }
    673 }
    674 
    675 void LocalizedNumberFormatter::getAffixImpl(bool isPrefix, bool isNegative, UnicodeString& result,
    676                                             UErrorCode& status) const {
    677     NumberStringBuilder string;
    678     auto signum = static_cast<int8_t>(isNegative ? -1 : 1);
    679     // Always return affixes for plural form OTHER.
    680     static const StandardPlural::Form plural = StandardPlural::OTHER;
    681     int32_t prefixLength;
    682     if (computeCompiled(status)) {
    683         prefixLength = fCompiled->getPrefixSuffix(signum, plural, string, status);
    684     } else {
    685         prefixLength = NumberFormatterImpl::getPrefixSuffixStatic(fMacros, signum, plural, string, status);
    686     }
    687     result.remove();
    688     if (isPrefix) {
    689         result.append(string.toTempUnicodeString().tempSubStringBetween(0, prefixLength));
    690     } else {
    691         result.append(string.toTempUnicodeString().tempSubStringBetween(prefixLength, string.length()));
    692     }
    693 }
    694 
    695 bool LocalizedNumberFormatter::computeCompiled(UErrorCode& status) const {
    696     // fUnsafeCallCount contains memory to be interpreted as an atomic int, most commonly
    697     // std::atomic<int32_t>.  Since the type of atomic int is platform-dependent, we cast the
    698     // bytes in fUnsafeCallCount to u_atomic_int32_t, a typedef for the platform-dependent
    699     // atomic int type defined in umutex.h.
    700     static_assert(
    701             sizeof(u_atomic_int32_t) <= sizeof(fUnsafeCallCount),
    702             "Atomic integer size on this platform exceeds the size allocated by fUnsafeCallCount");
    703     auto* callCount = reinterpret_cast<u_atomic_int32_t*>(
    704             const_cast<LocalizedNumberFormatter*>(this)->fUnsafeCallCount);
    705 
    706     // A positive value in the atomic int indicates that the data structure is not yet ready;
    707     // a negative value indicates that it is ready. If, after the increment, the atomic int
    708     // is exactly threshold, then it is the current thread's job to build the data structure.
    709     // Note: We set the callCount to INT32_MIN so that if another thread proceeds to increment
    710     // the atomic int, the value remains below zero.
    711     int32_t currentCount = umtx_loadAcquire(*callCount);
    712     if (0 <= currentCount && currentCount <= fMacros.threshold && fMacros.threshold > 0) {
    713         currentCount = umtx_atomic_inc(callCount);
    714     }
    715 
    716     if (currentCount == fMacros.threshold && fMacros.threshold > 0) {
    717         // Build the data structure and then use it (slow to fast path).
    718         const NumberFormatterImpl* compiled = new NumberFormatterImpl(fMacros, status);
    719         if (compiled == nullptr) {
    720             status = U_MEMORY_ALLOCATION_ERROR;
    721             return false;
    722         }
    723         U_ASSERT(fCompiled == nullptr);
    724         const_cast<LocalizedNumberFormatter*>(this)->fCompiled = compiled;
    725         umtx_storeRelease(*callCount, INT32_MIN);
    726         return true;
    727     } else if (currentCount < 0) {
    728         // The data structure is already built; use it (fast path).
    729         U_ASSERT(fCompiled != nullptr);
    730         return true;
    731     } else {
    732         // Format the number without building the data structure (slow path).
    733         return false;
    734     }
    735 }
    736 
    737 const impl::NumberFormatterImpl* LocalizedNumberFormatter::getCompiled() const {
    738     return fCompiled;
    739 }
    740 
    741 int32_t LocalizedNumberFormatter::getCallCount() const {
    742     auto* callCount = reinterpret_cast<u_atomic_int32_t*>(
    743             const_cast<LocalizedNumberFormatter*>(this)->fUnsafeCallCount);
    744     return umtx_loadAcquire(*callCount);
    745 }
    746 
    747 Format* LocalizedNumberFormatter::toFormat(UErrorCode& status) const {
    748     LocalPointer<LocalizedNumberFormatterAsFormat> retval(
    749             new LocalizedNumberFormatterAsFormat(*this, fMacros.locale), status);
    750     return retval.orphan();
    751 }
    752 
    753 
    754 FormattedNumber::FormattedNumber(FormattedNumber&& src) U_NOEXCEPT
    755         : fResults(src.fResults), fErrorCode(src.fErrorCode) {
    756     // Disown src.fResults to prevent double-deletion
    757     src.fResults = nullptr;
    758     src.fErrorCode = U_INVALID_STATE_ERROR;
    759 }
    760 
    761 FormattedNumber& FormattedNumber::operator=(FormattedNumber&& src) U_NOEXCEPT {
    762     delete fResults;
    763     fResults = src.fResults;
    764     fErrorCode = src.fErrorCode;
    765     // Disown src.fResults to prevent double-deletion
    766     src.fResults = nullptr;
    767     src.fErrorCode = U_INVALID_STATE_ERROR;
    768     return *this;
    769 }
    770 
    771 UnicodeString FormattedNumber::toString() const {
    772     UErrorCode localStatus = U_ZERO_ERROR;
    773     return toString(localStatus);
    774 }
    775 
    776 UnicodeString FormattedNumber::toString(UErrorCode& status) const {
    777     if (U_FAILURE(status)) {
    778         return ICU_Utility::makeBogusString();
    779     }
    780     if (fResults == nullptr) {
    781         status = fErrorCode;
    782         return ICU_Utility::makeBogusString();
    783     }
    784     return fResults->string.toUnicodeString();
    785 }
    786 
    787 Appendable& FormattedNumber::appendTo(Appendable& appendable) {
    788     UErrorCode localStatus = U_ZERO_ERROR;
    789     return appendTo(appendable, localStatus);
    790 }
    791 
    792 Appendable& FormattedNumber::appendTo(Appendable& appendable, UErrorCode& status) const {
    793     if (U_FAILURE(status)) {
    794         return appendable;
    795     }
    796     if (fResults == nullptr) {
    797         status = fErrorCode;
    798         return appendable;
    799     }
    800     appendable.appendString(fResults->string.chars(), fResults->string.length());
    801     return appendable;
    802 }
    803 
    804 void FormattedNumber::populateFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) {
    805     if (U_FAILURE(status)) {
    806         return;
    807     }
    808     if (fResults == nullptr) {
    809         status = fErrorCode;
    810         return;
    811     }
    812     // in case any users were depending on the old behavior:
    813     fieldPosition.setBeginIndex(0);
    814     fieldPosition.setEndIndex(0);
    815     fResults->string.nextFieldPosition(fieldPosition, status);
    816 }
    817 
    818 UBool FormattedNumber::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const {
    819     if (U_FAILURE(status)) {
    820         return FALSE;
    821     }
    822     if (fResults == nullptr) {
    823         status = fErrorCode;
    824         return FALSE;
    825     }
    826     // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
    827     return fResults->string.nextFieldPosition(fieldPosition, status) ? TRUE : FALSE;
    828 }
    829 
    830 void FormattedNumber::populateFieldPositionIterator(FieldPositionIterator& iterator, UErrorCode& status) {
    831     getAllFieldPositions(iterator, status);
    832 }
    833 
    834 void FormattedNumber::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const {
    835     FieldPositionIteratorHandler fpih(&iterator, status);
    836     getAllFieldPositionsImpl(fpih, status);
    837 }
    838 
    839 void FormattedNumber::getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih,
    840                                                UErrorCode& status) const {
    841     if (U_FAILURE(status)) {
    842         return;
    843     }
    844     if (fResults == nullptr) {
    845         status = fErrorCode;
    846         return;
    847     }
    848     fResults->string.getAllFieldPositions(fpih, status);
    849 }
    850 
    851 void FormattedNumber::getDecimalQuantity(DecimalQuantity& output, UErrorCode& status) const {
    852     if (U_FAILURE(status)) {
    853         return;
    854     }
    855     if (fResults == nullptr) {
    856         status = fErrorCode;
    857         return;
    858     }
    859     output = fResults->quantity;
    860 }
    861 
    862 FormattedNumber::~FormattedNumber() {
    863     delete fResults;
    864 }
    865 
    866 #endif /* #if !UCONFIG_NO_FORMATTING */
    867