]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/number_fluent.cpp
ICU-64260.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / number_fluent.cpp
index 687adb6b5babd24e55c1446c79fdc0098453d6d3..4397c2c8e19130af498c5be0a174cde5b9a90a64 100644 (file)
@@ -151,7 +151,7 @@ Derived NumberFormatterSettings<Derived>::roundingMode(UNumberFormatRoundingMode
 }
 
 template<typename Derived>
-Derived NumberFormatterSettings<Derived>::grouping(UGroupingStrategy strategy) const& {
+Derived NumberFormatterSettings<Derived>::grouping(UNumberGroupingStrategy strategy) const& {
     Derived copy(*this);
     // NOTE: This is slightly different than how the setting is stored in Java
     // because we want to put it on the stack.
@@ -160,7 +160,7 @@ Derived NumberFormatterSettings<Derived>::grouping(UGroupingStrategy strategy) c
 }
 
 template<typename Derived>
-Derived NumberFormatterSettings<Derived>::grouping(UGroupingStrategy strategy)&& {
+Derived NumberFormatterSettings<Derived>::grouping(UNumberGroupingStrategy strategy)&& {
     Derived move(std::move(*this));
     move.fMacros.grouper = Grouper::forStrategy(strategy);
     return move;
@@ -322,12 +322,25 @@ Derived NumberFormatterSettings<Derived>::macros(impl::MacroProps&& macros)&& {
 
 template<typename Derived>
 UnicodeString NumberFormatterSettings<Derived>::toSkeleton(UErrorCode& status) const {
+    if (U_FAILURE(status)) {
+        return ICU_Utility::makeBogusString();
+    }
     if (fMacros.copyErrorTo(status)) {
         return ICU_Utility::makeBogusString();
     }
     return skeleton::generate(fMacros, status);
 }
 
+template<typename Derived>
+LocalPointer<Derived> NumberFormatterSettings<Derived>::clone() const & {
+    return LocalPointer<Derived>(new Derived(*this));
+}
+
+template<typename Derived>
+LocalPointer<Derived> NumberFormatterSettings<Derived>::clone() && {
+    return LocalPointer<Derived>(new Derived(std::move(*this)));
+}
+
 // Declare all classes that implement NumberFormatterSettings
 // See https://stackoverflow.com/a/495056/1407170
 template
@@ -347,7 +360,12 @@ LocalizedNumberFormatter NumberFormatter::withLocale(const Locale& locale) {
 
 UnlocalizedNumberFormatter
 NumberFormatter::forSkeleton(const UnicodeString& skeleton, UErrorCode& status) {
-    return skeleton::create(skeleton, status);
+    return skeleton::create(skeleton, nullptr, status);
+}
+
+UnlocalizedNumberFormatter
+NumberFormatter::forSkeleton(const UnicodeString& skeleton, UParseError& perror, UErrorCode& status) {
+    return skeleton::create(skeleton, &perror, status);
 }
 
 
@@ -363,6 +381,7 @@ UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const NFS<UNF>& other)
     // No additional fields to assign
 }
 
+// Make default copy constructor call the NumberFormatterSettings copy constructor.
 UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(UNF&& src) U_NOEXCEPT
         : UNF(static_cast<NFS<UNF>&&>(src)) {}
 
@@ -383,6 +402,7 @@ UnlocalizedNumberFormatter& UnlocalizedNumberFormatter::operator=(UNF&& src) U_N
     return *this;
 }
 
+// Make default copy constructor call the NumberFormatterSettings copy constructor.
 LocalizedNumberFormatter::LocalizedNumberFormatter(const LNF& other)
         : LNF(static_cast<const NFS<LNF>&>(other)) {}
 
@@ -405,7 +425,8 @@ LocalizedNumberFormatter::LocalizedNumberFormatter(NFS<LNF>&& src) U_NOEXCEPT
 
 LocalizedNumberFormatter& LocalizedNumberFormatter::operator=(const LNF& other) {
     NFS<LNF>::operator=(static_cast<const NFS<LNF>&>(other));
-    // No additional fields to assign (let call count and compiled formatter reset to defaults)
+    // Reset to default values.
+    clear();
     return *this;
 }
 
@@ -417,20 +438,26 @@ LocalizedNumberFormatter& LocalizedNumberFormatter::operator=(LNF&& src) U_NOEXC
         // Formatter is compiled
         lnfMoveHelper(static_cast<LNF&&>(src));
     } else {
-        // Reset to default values.
-        auto* callCount = reinterpret_cast<u_atomic_int32_t*>(fUnsafeCallCount);
-        umtx_storeRelease(*callCount, 0);
-        fCompiled = nullptr;
+        clear();
     }
     return *this;
 }
 
+void LocalizedNumberFormatter::clear() {
+    // Reset to default values.
+    auto* callCount = reinterpret_cast<u_atomic_int32_t*>(fUnsafeCallCount);
+    umtx_storeRelease(*callCount, 0);
+    delete fCompiled;
+    fCompiled = nullptr;
+}
+
 void LocalizedNumberFormatter::lnfMoveHelper(LNF&& src) {
     // Copy over the compiled formatter and set call count to INT32_MIN as in computeCompiled().
     // Don't copy the call count directly because doing so requires a loadAcquire/storeRelease.
     // The bits themselves appear to be platform-dependent, so copying them might not be safe.
     auto* callCount = reinterpret_cast<u_atomic_int32_t*>(fUnsafeCallCount);
     umtx_storeRelease(*callCount, INT32_MIN);
+    delete fCompiled;
     fCompiled = src.fCompiled;
     // Reset the source object to leave it in a safe state.
     auto* srcCallCount = reinterpret_cast<u_atomic_int32_t*>(src.fUnsafeCallCount);
@@ -491,6 +518,17 @@ SymbolsWrapper::~SymbolsWrapper() {
     doCleanup();
 }
 
+// Apple <rdar://problem/49955427>
+void SymbolsWrapper::setDFSShallowCopy(UBool shallow) {
+    if (shallow) {
+        if (fType == SYMPTR_DFS) {
+            fType = SYMPTR_DFS_SHALLOWCOPY;
+        }
+    } else if (fType == SYMPTR_DFS_SHALLOWCOPY) {
+        fType = SYMPTR_DFS;
+    }
+}
+
 void SymbolsWrapper::setTo(const DecimalFormatSymbols& dfs) {
     doCleanup();
     fType = SYMPTR_DFS;
@@ -517,6 +555,10 @@ void SymbolsWrapper::doCopyFrom(const SymbolsWrapper& other) {
                 fPtr.dfs = nullptr;
             }
             break;
+        case SYMPTR_DFS_SHALLOWCOPY: // Apple <rdar://problem/49955427>
+            // DecimalFormatSymbols pointer copy, do not clone
+            fPtr.dfs = other.fPtr.dfs;
+            break;
         case SYMPTR_NS:
             // Memory allocation failures are exposed in copyErrorTo()
             if (other.fPtr.ns != nullptr) {
@@ -535,6 +577,7 @@ void SymbolsWrapper::doMoveFrom(SymbolsWrapper&& src) {
             // No action necessary
             break;
         case SYMPTR_DFS:
+        case SYMPTR_DFS_SHALLOWCOPY:
             fPtr.dfs = src.fPtr.dfs;
             src.fPtr.dfs = nullptr;
             break;
@@ -553,6 +596,9 @@ void SymbolsWrapper::doCleanup() {
         case SYMPTR_DFS:
             delete fPtr.dfs;
             break;
+        case SYMPTR_DFS_SHALLOWCOPY: // Apple <rdar://problem/49955427>
+            // No action necessary
+            break;
         case SYMPTR_NS:
             delete fPtr.ns;
             break;
@@ -560,7 +606,7 @@ void SymbolsWrapper::doCleanup() {
 }
 
 bool SymbolsWrapper::isDecimalFormatSymbols() const {
-    return fType == SYMPTR_DFS;
+    return (fType == SYMPTR_DFS || fType == SYMPTR_DFS_SHALLOWCOPY);
 }
 
 bool SymbolsWrapper::isNumberingSystem() const {
@@ -568,7 +614,7 @@ bool SymbolsWrapper::isNumberingSystem() const {
 }
 
 const DecimalFormatSymbols* SymbolsWrapper::getDecimalFormatSymbols() const {
-    U_ASSERT(fType == SYMPTR_DFS);
+    U_ASSERT(fType == SYMPTR_DFS || fType == SYMPTR_DFS_SHALLOWCOPY);
     return fPtr.dfs;
 }
 
@@ -605,6 +651,11 @@ FormattedNumber LocalizedNumberFormatter::formatDouble(double value, UErrorCode&
         return FormattedNumber(status);
     }
     results->quantity.setToDouble(value);
+    if (fMacros.adjustDoublePrecision) { // Apple addition for <rdar://problem/39240173>
+        UErrorCode localStatus = U_ZERO_ERROR;
+        int32_t magnitude = results->quantity.getMagnitude();
+        results->quantity.roundToMagnitude(magnitude-14, kDefaultMode, localStatus);
+    }
     formatImpl(results, status);
 
     // Do not save the results object if we encountered a failure.
@@ -657,10 +708,14 @@ LocalizedNumberFormatter::formatDecimalQuantity(const DecimalQuantity& dq, UErro
 
 void LocalizedNumberFormatter::formatImpl(impl::UFormattedNumberData* results, UErrorCode& status) const {
     if (computeCompiled(status)) {
-        fCompiled->apply(results->quantity, results->string, status);
+        fCompiled->format(results->quantity, results->getStringRef(), status);
     } else {
-        NumberFormatterImpl::applyStatic(fMacros, results->quantity, results->string, status);
+        NumberFormatterImpl::formatStatic(fMacros, results->quantity, results->getStringRef(), status);
+    }
+    if (U_FAILURE(status)) {
+        return;
     }
+    results->getStringRef().writeTerminator(status);
 }
 
 void LocalizedNumberFormatter::getAffixImpl(bool isPrefix, bool isNegative, UnicodeString& result,
@@ -706,7 +761,11 @@ bool LocalizedNumberFormatter::computeCompiled(UErrorCode& status) const {
 
     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);
@@ -732,122 +791,17 @@ int32_t LocalizedNumberFormatter::getCallCount() const {
 }
 
 Format* LocalizedNumberFormatter::toFormat(UErrorCode& status) const {
+    if (U_FAILURE(status)) {
+        return nullptr;
+    }
     LocalPointer<LocalizedNumberFormatterAsFormat> retval(
             new LocalizedNumberFormatterAsFormat(*this, fMacros.locale), status);
     return retval.orphan();
 }
 
-
-FormattedNumber::FormattedNumber(FormattedNumber&& 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;
-}
-
-FormattedNumber& FormattedNumber::operator=(FormattedNumber&& 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 FormattedNumber::toString() const {
-    UErrorCode localStatus = U_ZERO_ERROR;
-    return toString(localStatus);
-}
-
-UnicodeString FormattedNumber::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();
-}
-
-Appendable& FormattedNumber::appendTo(Appendable& appendable) {
-    UErrorCode localStatus = U_ZERO_ERROR;
-    return appendTo(appendable, localStatus);
-}
-
-Appendable& FormattedNumber::appendTo(Appendable& appendable, UErrorCode& status) {
-    if (U_FAILURE(status)) {
-        return appendable;
-    }
-    if (fResults == nullptr) {
-        status = fErrorCode;
-        return appendable;
-    }
-    appendable.appendString(fResults->string.chars(), fResults->string.length());
-    return appendable;
-}
-
-void FormattedNumber::populateFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) {
-    if (U_FAILURE(status)) {
-        return;
-    }
-    if (fResults == nullptr) {
-        status = fErrorCode;
-        return;
-    }
-    // in case any users were depending on the old behavior:
-    fieldPosition.setBeginIndex(0);
-    fieldPosition.setEndIndex(0);
-    fResults->string.nextFieldPosition(fieldPosition, status);
-}
-
-UBool FormattedNumber::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 FormattedNumber::populateFieldPositionIterator(FieldPositionIterator& iterator, UErrorCode& status) {
-    getAllFieldPositions(iterator, status);
-}
-
-void FormattedNumber::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const {
-    FieldPositionIteratorHandler fpih(&iterator, status);
-    getAllFieldPositionsImpl(fpih, status);
-}
-
-void FormattedNumber::getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih,
-                                               UErrorCode& status) const {
-    if (U_FAILURE(status)) {
-        return;
-    }
-    if (fResults == nullptr) {
-        status = fErrorCode;
-        return;
-    }
-    fResults->string.getAllFieldPositions(fpih, status);
-}
-
-void FormattedNumber::getDecimalQuantity(DecimalQuantity& output, UErrorCode& status) const {
-    if (U_FAILURE(status)) {
-        return;
-    }
-    if (fResults == nullptr) {
-        status = fErrorCode;
-        return;
-    }
-    output = fResults->quantity;
-}
-
-FormattedNumber::~FormattedNumber() {
-    delete fResults;
+// Apple <rdar://problem/49955427>
+void LocalizedNumberFormatter::setDFSShallowCopy(UBool shallow) {
+    fMacros.symbols.setDFSShallowCopy(shallow);
 }
 
 #endif /* #if !UCONFIG_NO_FORMATTING */