#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER) // Ignore MSVC warning 4661. This is generated for NumberFormatterSettings<>::toSkeleton() as this method // is defined elsewhere (in number_skeletons.cpp). The compiler is warning that the explicit template instantiation // inside this single translation unit (CPP file) is incomplete, and thus it isn't sure if the template class is // fully defined. However, since each translation unit explicitly instantiates all the necessary template classes, // they will all be passed to the linker, and the linker will still find and export all the class members. #pragma warning(push) #pragma warning(disable: 4661) #endif
template<typename Derived>
Derived NumberFormatterSettings<Derived>::notation(const Notation& notation) const& {
Derived copy(*this); // NOTE: Slicing is OK.
copy.fMacros.notation = notation; return copy;
}
template<typename Derived>
Derived NumberFormatterSettings<Derived>::notation(const Notation& notation)&& {
Derived move(std::move(*this)); // NOTE: Slicing is OK.
move.fMacros.notation = notation; return move;
}
template<typename Derived>
Derived NumberFormatterSettings<Derived>::unit(const icu::MeasureUnit& unit) const& {
Derived copy(*this); // NOTE: Slicing occurs here. However, CurrencyUnit can be restored from MeasureUnit. // TimeUnit may be affected, but TimeUnit is not as relevant to number formatting.
copy.fMacros.unit = unit; return copy;
}
template<typename Derived>
Derived NumberFormatterSettings<Derived>::adoptUnit(icu::MeasureUnit* unit) const& {
Derived copy(*this); // Just move the unit into the MacroProps by value, and delete it since we have ownership. // NOTE: Slicing occurs here. However, CurrencyUnit can be restored from MeasureUnit. // TimeUnit may be affected, but TimeUnit is not as relevant to number formatting. if (unit != nullptr) { // TODO: On nullptr, reset to default value?
copy.fMacros.unit = std::move(*unit); delete unit;
} return copy;
}
template<typename Derived>
Derived NumberFormatterSettings<Derived>::adoptUnit(icu::MeasureUnit* unit)&& {
Derived move(std::move(*this)); // See comments above about slicing and ownership. if (unit != nullptr) { // TODO: On nullptr, reset to default value?
move.fMacros.unit = std::move(*unit); delete unit;
} return move;
}
template<typename Derived>
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.
copy.fMacros.grouper = Grouper::forStrategy(strategy); return copy;
}
// Declare all classes that implement NumberFormatterSettings // See https://stackoverflow.com/a/495056/1407170 template class icu::number::NumberFormatterSettings<icu::number::UnlocalizedNumberFormatter>; template class icu::number::NumberFormatterSettings<icu::number::LocalizedNumberFormatter>;
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. delete fCompiled; if (src.fCompiled != nullptr) { auto* callCount = reinterpret_cast<u_atomic_int32_t*>(fUnsafeCallCount);
umtx_storeRelease(*callCount, INT32_MIN);
fCompiled = src.fCompiled; // Reset the source object to leave it in a safe state.
src.resetCompiled();
} else {
resetCompiled();
}
void LocalizedNumberFormatter::lnfCopyHelper(const LNF&, UErrorCode& status) { // When copying, always reset the compiled formatter. delete fCompiled;
resetCompiled();
// If MacroProps has a reference to AffixPatternProvider, we need to copy it. // If MacroProps has a reference to PluralRules, copy that one, too. delete fWarehouse; if (fMacros.affixProvider || fMacros.rules) {
LocalPointer<DecimalFormatWarehouse> warehouse(new DecimalFormatWarehouse(), status); if (U_FAILURE(status)) {
fWarehouse = nullptr; return;
} if (fMacros.affixProvider) {
warehouse->affixProvider.setTo(fMacros.affixProvider, status);
fMacros.affixProvider = &warehouse->affixProvider.get();
} if (fMacros.rules) {
warehouse->rules.adoptInsteadAndCheckErrorCode( new PluralRules(*fMacros.rules), status);
fMacros.rules = warehouse->rules.getAlias();
}
fWarehouse = warehouse.orphan();
} else {
fWarehouse = nullptr;
}
}
FormattedNumber LocalizedNumberFormatter::formatInt(int64_t value, UErrorCode& status) const { if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); } auto* results = new UFormattedNumberData(); if (results == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return FormattedNumber(status);
}
results->quantity.setToLong(value);
formatImpl(results, status);
// Do not save the results object if we encountered a failure. if (U_SUCCESS(status)) { return FormattedNumber(results);
} else { delete results; return FormattedNumber(status);
}
}
FormattedNumber LocalizedNumberFormatter::formatDouble(double value, UErrorCode& status) const { if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); } auto* results = new UFormattedNumberData(); if (results == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return FormattedNumber(status);
}
results->quantity.setToDouble(value);
formatImpl(results, status);
// Do not save the results object if we encountered a failure. if (U_SUCCESS(status)) { return FormattedNumber(results);
} else { delete results; return FormattedNumber(status);
}
}
FormattedNumber LocalizedNumberFormatter::formatDecimal(StringPiece value, UErrorCode& status) const { if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); } auto* results = new UFormattedNumberData(); if (results == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return FormattedNumber(status);
}
results->quantity.setToDecNumber(value, status);
formatImpl(results, status);
// Do not save the results object if we encountered a failure. if (U_SUCCESS(status)) { return FormattedNumber(results);
} else { delete results; return FormattedNumber(status);
}
}
FormattedNumber
LocalizedNumberFormatter::formatDecimalQuantity(const DecimalQuantity& dq, UErrorCode& status) const { if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); } auto* results = new UFormattedNumberData(); if (results == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return FormattedNumber(status);
}
results->quantity = dq;
formatImpl(results, status);
// Do not save the results object if we encountered a failure. if (U_SUCCESS(status)) { return FormattedNumber(results);
} else { delete results; return FormattedNumber(status);
}
}
bool LocalizedNumberFormatter::computeCompiled(UErrorCode& status) const { // fUnsafeCallCount contains memory to be interpreted as an atomic int, most commonly // std::atomic<int32_t>. Since the type of atomic int is platform-dependent, we cast the // bytes in fUnsafeCallCount to u_atomic_int32_t, a typedef for the platform-dependent // atomic int type defined in umutex.h.
static_assert( sizeof(u_atomic_int32_t) <= sizeof(fUnsafeCallCount), "Atomic integer size on this platform exceeds the size allocated by fUnsafeCallCount"); auto* callCount = reinterpret_cast<u_atomic_int32_t*>( const_cast<LocalizedNumberFormatter*>(this)->fUnsafeCallCount);
// A positive value in the atomic int indicates that the data structure is not yet ready; // a negative value indicates that it is ready. If, after the increment, the atomic int // is exactly threshold, then it is the current thread's job to build the data structure. // Note: We set the callCount to INT32_MIN so that if another thread proceeds to increment // the atomic int, the value remains below zero.
int32_t currentCount = umtx_loadAcquire(*callCount); if (0 <= currentCount && currentCount <= fMacros.threshold && fMacros.threshold > 0) {
currentCount = umtx_atomic_inc(callCount);
}
if (currentCount == fMacros.threshold && fMacros.threshold > 0) { // Build the data structure and then use it (slow to fast path). const NumberFormatterImpl* compiled = new NumberFormatterImpl(fMacros, status); if (compiled == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; returnfalse;
}
U_ASSERT(fCompiled == nullptr); const_cast<LocalizedNumberFormatter*>(this)->fCompiled = compiled;
umtx_storeRelease(*callCount, INT32_MIN); returntrue;
} elseif (currentCount < 0) { // The data structure is already built; use it (fast path).
U_ASSERT(fCompiled != nullptr); returntrue;
} else { // Format the number without building the data structure (slow path). returnfalse;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.