}
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.
}
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;
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
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);
}
// 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)) {}
return *this;
}
+// Make default copy constructor call the NumberFormatterSettings copy constructor.
LocalizedNumberFormatter::LocalizedNumberFormatter(const LNF& other)
: LNF(static_cast<const NFS<LNF>&>(other)) {}
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;
}
// 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);
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;
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) {
// No action necessary
break;
case SYMPTR_DFS:
+ case SYMPTR_DFS_SHALLOWCOPY:
fPtr.dfs = src.fPtr.dfs;
src.fPtr.dfs = nullptr;
break;
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;
}
bool SymbolsWrapper::isDecimalFormatSymbols() const {
- return fType == SYMPTR_DFS;
+ return (fType == SYMPTR_DFS || fType == SYMPTR_DFS_SHALLOWCOPY);
}
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;
}
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.
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,
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);
}
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 */