- Migrates Number[Range] formatter to helper macros.
- Adds additional macros.
- Syncs docstrings between subclasses.
return fString;
}
+ inline const number::impl::NumberStringBuilder& getStringRef() const {
+ return fString;
+ }
+
private:
number::impl::NumberStringBuilder fString;
number::impl::Field fNumericField;
};
+/** Boilerplate to check for valid status before dereferencing the fData pointer. */
+#define UPRV_FORMATTED_VALUE_METHOD_GUARD(returnExpression) \
+ if (U_FAILURE(status)) { \
+ return returnExpression; \
+ } \
+ if (fData == nullptr) { \
+ status = fErrorCode; \
+ return returnExpression; \
+ } \
+
+
/** Implementation of the methods from U_FORMATTED_VALUE_SUBCLASS_AUTO. */
#define UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(Name) \
- Name::Name(Name&& src) U_NOEXCEPT { \
- fData = src.fData; \
+ Name::Name(Name&& src) U_NOEXCEPT \
+ : fData(src.fData), fErrorCode(src.fErrorCode) { \
src.fData = nullptr; \
- fErrorCode = src.fErrorCode; \
src.fErrorCode = U_INVALID_STATE_ERROR; \
} \
Name::~Name() { \
return *this; \
} \
UnicodeString Name::toString(UErrorCode& status) const { \
- if (U_FAILURE(status)) { \
- return ICU_Utility::makeBogusString(); \
- } \
- if (fData == nullptr) { \
- status = fErrorCode; \
- return ICU_Utility::makeBogusString(); \
- } \
+ UPRV_FORMATTED_VALUE_METHOD_GUARD(ICU_Utility::makeBogusString()) \
return fData->toString(status); \
} \
UnicodeString Name::toTempString(UErrorCode& status) const { \
- if (U_FAILURE(status)) { \
- return ICU_Utility::makeBogusString(); \
- } \
- if (fData == nullptr) { \
- status = fErrorCode; \
- return ICU_Utility::makeBogusString(); \
- } \
+ UPRV_FORMATTED_VALUE_METHOD_GUARD(ICU_Utility::makeBogusString()) \
return fData->toTempString(status); \
} \
Appendable& Name::appendTo(Appendable& appendable, UErrorCode& status) const { \
- if (U_FAILURE(status)) { \
- return appendable; \
- } \
- if (fData == nullptr) { \
- status = fErrorCode; \
- return appendable; \
- } \
+ UPRV_FORMATTED_VALUE_METHOD_GUARD(appendable) \
return fData->appendTo(appendable, status); \
} \
UBool Name::nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const { \
- if (U_FAILURE(status)) { \
- return FALSE; \
+ UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE) \
+ return fData->nextPosition(cfpos, status); \
+ }
+
+
+/** Like UPRV_FORMATTED_VALUE_CAPI_AUTO_IMPL but without impl type declarations. */
+#define UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(CType, ImplType, HelperType, Prefix) \
+ U_CAPI CType* U_EXPORT2 \
+ Prefix ## _openResult (UErrorCode* ec) { \
+ if (U_FAILURE(*ec)) { \
+ return nullptr; \
} \
- if (fData == nullptr) { \
- status = fErrorCode; \
- return FALSE; \
+ ImplType* impl = new ImplType(); \
+ if (impl == nullptr) { \
+ *ec = U_MEMORY_ALLOCATION_ERROR; \
+ return nullptr; \
} \
- return fData->nextPosition(cfpos, status); \
+ return static_cast<HelperType*>(impl)->exportForC(); \
+ } \
+ U_DRAFT const UFormattedValue* U_EXPORT2 \
+ Prefix ## _resultAsValue (const CType* uresult, UErrorCode* ec) { \
+ const ImplType* result = HelperType::validate(uresult, *ec); \
+ if (U_FAILURE(*ec)) { return nullptr; } \
+ return static_cast<const UFormattedValueApiHelper*>(result)->exportConstForC(); \
+ } \
+ U_CAPI void U_EXPORT2 \
+ Prefix ## _closeResult (CType* uresult) { \
+ UErrorCode localStatus = U_ZERO_ERROR; \
+ const ImplType* impl = HelperType::validate(uresult, localStatus); \
+ delete impl; \
}
} \
ImplType::~ImplType() {} \
U_NAMESPACE_END \
- U_CAPI CType* U_EXPORT2 \
- Prefix ## _openResult (UErrorCode* ec) { \
- if (U_FAILURE(*ec)) { \
- return nullptr; \
- } \
- ImplType* impl = new ImplType(); \
- if (impl == nullptr) { \
- *ec = U_MEMORY_ALLOCATION_ERROR; \
- return nullptr; \
- } \
- return static_cast<HelperType*>(impl)->exportForC(); \
- } \
- U_DRAFT const UFormattedValue* U_EXPORT2 \
- Prefix ## _resultAsValue (const CType* uresult, UErrorCode* ec) { \
- const ImplType* result = HelperType::validate(uresult, *ec); \
- if (U_FAILURE(*ec)) { return nullptr; } \
- return static_cast<const UFormattedValueApiHelper*>(result)->exportConstForC(); \
- } \
- U_CAPI void U_EXPORT2 \
- Prefix ## _closeResult (CType* uresult) { \
- UErrorCode localStatus = U_ZERO_ERROR; \
- const ImplType* impl = HelperType::validate(uresult, localStatus); \
- delete impl; \
- }
+ UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(CType, ImplType, HelperType, Prefix)
U_NAMESPACE_END
// always return first occurrence:
pos.setBeginIndex(0);
pos.setEndIndex(0);
- bool found = data.string.nextFieldPosition(pos, status);
+ bool found = data.getStringRef().nextFieldPosition(pos, status);
if (found && appendTo.length() != 0) {
pos.setBeginIndex(pos.getBeginIndex() + appendTo.length());
pos.setEndIndex(pos.getEndIndex() + appendTo.length());
}
- appendTo.append(data.string.toTempUnicodeString());
+ appendTo.append(data.getStringRef().toTempUnicodeString());
return appendTo;
}
if (U_FAILURE(status)) {
return appendTo;
}
- appendTo.append(data.string.toTempUnicodeString());
+ appendTo.append(data.getStringRef().toTempUnicodeString());
if (posIter != nullptr) {
FieldPositionIteratorHandler fpih(posIter, status);
- data.string.getAllFieldPositions(fpih, status);
+ data.getStringRef().getAllFieldPositions(fpih, status);
}
return appendTo;
}
UFormattedNumberImpl::~UFormattedNumberImpl() {
// Disown the data from fImpl so it doesn't get deleted twice
- fImpl.fResults = nullptr;
+ fImpl.fData = nullptr;
}
}
U_NAMESPACE_END
+UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(
+ UFormattedNumber,
+ UFormattedNumberImpl,
+ UFormattedNumberApiHelper,
+ unumf)
+
+
const DecimalQuantity* icu::number::impl::validateUFormattedNumberToDecimalQuantity(
const UFormattedNumber* uresult, UErrorCode& status) {
auto* result = UFormattedNumberApiHelper::validate(uresult, status);
return impl->exportForC();
}
-U_CAPI UFormattedNumber* U_EXPORT2
-unumf_openResult(UErrorCode* ec) {
- auto* impl = new UFormattedNumberImpl();
- if (impl == nullptr) {
- *ec = U_MEMORY_ALLOCATION_ERROR;
- return nullptr;
- }
- return static_cast<UFormattedNumberApiHelper*>(impl)->exportForC();
-}
-
U_CAPI void U_EXPORT2
unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNumber* uresult,
UErrorCode* ec) {
auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
if (U_FAILURE(*ec)) { return; }
- result->fData.string.clear();
+ result->fData.getStringRef().clear();
result->fData.quantity.setToLong(value);
formatter->fFormatter.formatImpl(&result->fData, *ec);
}
auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
if (U_FAILURE(*ec)) { return; }
- result->fData.string.clear();
+ result->fData.getStringRef().clear();
result->fData.quantity.setToDouble(value);
formatter->fFormatter.formatImpl(&result->fData, *ec);
}
auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
if (U_FAILURE(*ec)) { return; }
- result->fData.string.clear();
+ result->fData.getStringRef().clear();
result->fData.quantity.setToDecNumber({value, valueLen}, *ec);
if (U_FAILURE(*ec)) { return; }
formatter->fFormatter.formatImpl(&result->fData, *ec);
}
-U_DRAFT const UFormattedValue* U_EXPORT2
-unumf_resultAsFormattedValue(const UFormattedNumber* uresult, UErrorCode* ec) {
- const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
- if (U_FAILURE(*ec)) { return nullptr; }
-
- return static_cast<const UFormattedValueApiHelper*>(result)->exportConstForC();
-}
-
U_CAPI int32_t U_EXPORT2
unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t bufferCapacity,
UErrorCode* ec) {
result->fImpl.getAllFieldPositions(*fpi, *ec);
}
-U_CAPI void U_EXPORT2
-unumf_closeResult(UFormattedNumber* uresult) {
- UErrorCode localStatus = U_ZERO_ERROR;
- const UFormattedNumberImpl* impl = UFormattedNumberApiHelper::validate(uresult, localStatus);
- delete impl;
-}
-
U_CAPI void U_EXPORT2
unumf_close(UNumberFormatter* f) {
UErrorCode localStatus = U_ZERO_ERROR;
void LocalizedNumberFormatter::formatImpl(impl::UFormattedNumberData* results, UErrorCode& status) const {
if (computeCompiled(status)) {
- fCompiled->format(results->quantity, results->string, status);
+ fCompiled->format(results->quantity, results->getStringRef(), status);
} else {
- NumberFormatterImpl::formatStatic(fMacros, results->quantity, results->string, status);
+ NumberFormatterImpl::formatStatic(fMacros, results->quantity, results->getStringRef(), status);
}
if (U_FAILURE(status)) {
return;
}
- results->string.writeTerminator(status);
+ results->getStringRef().writeTerminator(status);
}
void LocalizedNumberFormatter::getAffixImpl(bool isPrefix, bool isNegative, UnicodeString& result,
namespace number {
-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;
-}
+UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedNumber)
-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();
-}
-
-UnicodeString FormattedNumber::toTempString(UErrorCode& status) const {
- if (U_FAILURE(status)) {
- return ICU_Utility::makeBogusString();
- }
- if (fResults == nullptr) {
- status = fErrorCode;
- return ICU_Utility::makeBogusString();
- }
- return fResults->string.toTempUnicodeString();
-}
-
-Appendable& FormattedNumber::appendTo(Appendable& appendable, UErrorCode& status) const {
- if (U_FAILURE(status)) {
- return appendable;
- }
- if (fResults == nullptr) {
- status = fErrorCode;
- return appendable;
- }
- appendable.appendString(fResults->string.chars(), fResults->string.length());
- return appendable;
-}
-
-UBool FormattedNumber::nextPosition(ConstrainedFieldPosition& cfpos, 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.nextPosition(cfpos, 0, status) ? TRUE : FALSE;
-}
UBool FormattedNumber::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const {
- if (U_FAILURE(status)) {
- return FALSE;
- }
- if (fResults == nullptr) {
- status = fErrorCode;
- return FALSE;
- }
+ UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE)
// NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
- return fResults->string.nextFieldPosition(fieldPosition, status) ? TRUE : FALSE;
+ return fData->getStringRef().nextFieldPosition(fieldPosition, status) ? TRUE : FALSE;
}
void FormattedNumber::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const {
void FormattedNumber::getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih,
UErrorCode& status) const {
- if (U_FAILURE(status)) {
- return;
- }
- if (fResults == nullptr) {
- status = fErrorCode;
- return;
- }
- fResults->string.getAllFieldPositions(fpih, status);
+ UPRV_FORMATTED_VALUE_METHOD_GUARD()
+ fData->getStringRef().getAllFieldPositions(fpih, status);
}
void FormattedNumber::getDecimalQuantity(impl::DecimalQuantity& output, UErrorCode& status) const {
- if (U_FAILURE(status)) {
- return;
- }
- if (fResults == nullptr) {
- status = fErrorCode;
- return;
- }
- output = fResults->quantity;
+ UPRV_FORMATTED_VALUE_METHOD_GUARD()
+ output = fData->quantity;
}
-FormattedNumber::~FormattedNumber() {
- delete fResults;
-}
+
+impl::UFormattedNumberData::~UFormattedNumberData() = default;
} // namespace number
#include "number_types.h"
#include "number_decimalquantity.h"
#include "number_stringbuilder.h"
+#include "formattedval_impl.h"
U_NAMESPACE_BEGIN namespace number {
namespace impl {
* The DecimalQuantity is not currently being used by FormattedNumber, but at some point it could be used
* to add a toDecNumber() or similar method.
*/
-struct UFormattedNumberData : public UMemory {
+class UFormattedNumberData : public FormattedValueNumberStringBuilderImpl {
+public:
+ UFormattedNumberData() : FormattedValueNumberStringBuilderImpl(0) {}
+ virtual ~UFormattedNumberData();
+
DecimalQuantity quantity;
- NumberStringBuilder string;
};
if (U_FAILURE(status)) {
return;
}
- results.string.writeTerminator(status);
+ results.getStringRef().writeTerminator(status);
}
const impl::NumberRangeFormatterImpl*
}
-FormattedNumberRange::FormattedNumberRange(FormattedNumberRange&& 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;
-}
-
-FormattedNumberRange& FormattedNumberRange::operator=(FormattedNumberRange&& 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 FormattedNumberRange::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();
-}
-
-UnicodeString FormattedNumberRange::toTempString(UErrorCode& status) const {
- if (U_FAILURE(status)) {
- return ICU_Utility::makeBogusString();
- }
- if (fResults == nullptr) {
- status = fErrorCode;
- return ICU_Utility::makeBogusString();
- }
- return fResults->string.toTempUnicodeString();
-}
+UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedNumberRange)
-Appendable& FormattedNumberRange::appendTo(Appendable& appendable, UErrorCode& status) const {
- if (U_FAILURE(status)) {
- return appendable;
- }
- if (fResults == nullptr) {
- status = fErrorCode;
- return appendable;
- }
- appendable.appendString(fResults->string.chars(), fResults->string.length());
- return appendable;
-}
-
-UBool FormattedNumberRange::nextPosition(ConstrainedFieldPosition& cfpos, 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.nextPosition(cfpos, 0, status) ? TRUE : FALSE;
-}
UBool FormattedNumberRange::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const {
- if (U_FAILURE(status)) {
- return FALSE;
- }
- if (fResults == nullptr) {
- status = fErrorCode;
- return FALSE;
- }
+ UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE)
// NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
- return fResults->string.nextFieldPosition(fieldPosition, status) ? TRUE : FALSE;
+ return fData->getStringRef().nextFieldPosition(fieldPosition, status) ? TRUE : FALSE;
}
void FormattedNumberRange::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const {
void FormattedNumberRange::getAllFieldPositionsImpl(
FieldPositionIteratorHandler& fpih, UErrorCode& status) const {
- if (U_FAILURE(status)) {
- return;
- }
- if (fResults == nullptr) {
- status = fErrorCode;
- return;
- }
- fResults->string.getAllFieldPositions(fpih, status);
+ UPRV_FORMATTED_VALUE_METHOD_GUARD()
+ fData->getStringRef().getAllFieldPositions(fpih, status);
}
UnicodeString FormattedNumberRange::getFirstDecimal(UErrorCode& status) const {
- if (U_FAILURE(status)) {
- return ICU_Utility::makeBogusString();
- }
- if (fResults == nullptr) {
- status = fErrorCode;
- return ICU_Utility::makeBogusString();
- }
- return fResults->quantity1.toScientificString();
+ UPRV_FORMATTED_VALUE_METHOD_GUARD(ICU_Utility::makeBogusString())
+ return fData->quantity1.toScientificString();
}
UnicodeString FormattedNumberRange::getSecondDecimal(UErrorCode& status) const {
- if (U_FAILURE(status)) {
- return ICU_Utility::makeBogusString();
- }
- if (fResults == nullptr) {
- status = fErrorCode;
- return ICU_Utility::makeBogusString();
- }
- return fResults->quantity2.toScientificString();
+ UPRV_FORMATTED_VALUE_METHOD_GUARD(ICU_Utility::makeBogusString())
+ return fData->quantity2.toScientificString();
}
UNumberRangeIdentityResult FormattedNumberRange::getIdentityResult(UErrorCode& status) const {
- if (U_FAILURE(status)) {
- return UNUM_IDENTITY_RESULT_NOT_EQUAL;
- }
- if (fResults == nullptr) {
- status = fErrorCode;
- return UNUM_IDENTITY_RESULT_NOT_EQUAL;
- }
- return fResults->identityResult;
+ UPRV_FORMATTED_VALUE_METHOD_GUARD(UNUM_IDENTITY_RESULT_NOT_EQUAL)
+ return fData->identityResult;
}
-FormattedNumberRange::~FormattedNumberRange() {
- delete fResults;
-}
+
+UFormattedNumberRangeData::~UFormattedNumberRangeData() = default;
UErrorCode& status) const {
if (U_FAILURE(status)) { return; }
if (fSameFormatters) {
- int32_t length = NumberFormatterImpl::writeNumber(micros1, data.quantity1, data.string, 0, status);
- NumberFormatterImpl::writeAffixes(micros1, data.string, 0, length, status);
+ int32_t length = NumberFormatterImpl::writeNumber(micros1, data.quantity1, data.getStringRef(), 0, status);
+ NumberFormatterImpl::writeAffixes(micros1, data.getStringRef(), 0, length, status);
} else {
formatRange(data, micros1, micros2, status);
}
UErrorCode& status) const {
if (U_FAILURE(status)) { return; }
if (fSameFormatters) {
- int32_t length = NumberFormatterImpl::writeNumber(micros1, data.quantity1, data.string, 0, status);
+ int32_t length = NumberFormatterImpl::writeNumber(micros1, data.quantity1, data.getStringRef(), 0, status);
// HEURISTIC: Desired modifier order: inner, middle, approximately, outer.
- length += micros1.modInner->apply(data.string, 0, length, status);
- length += micros1.modMiddle->apply(data.string, 0, length, status);
- length += fApproximatelyModifier.apply(data.string, 0, length, status);
- micros1.modOuter->apply(data.string, 0, length, status);
+ length += micros1.modInner->apply(data.getStringRef(), 0, length, status);
+ length += micros1.modMiddle->apply(data.getStringRef(), 0, length, status);
+ length += fApproximatelyModifier.apply(data.getStringRef(), 0, length, status);
+ micros1.modOuter->apply(data.getStringRef(), 0, length, status);
} else {
formatRange(data, micros1, micros2, status);
}
break;
}
- NumberStringBuilder& string = data.string;
+ NumberStringBuilder& string = data.getStringRef();
int32_t lengthPrefix = 0;
int32_t length1 = 0;
int32_t lengthInfix = 0;
#include "number_decimalquantity.h"
#include "number_formatimpl.h"
#include "number_stringbuilder.h"
+#include "formattedval_impl.h"
U_NAMESPACE_BEGIN namespace number {
namespace impl {
*
* Has incomplete magic number logic that will need to be finished
* if this is to be exposed as C API in the future.
+ *
+ * Possible magic number: 0x46445200
+ * Reads in ASCII as "FDR" (FormatteDnumberRange with room at the end)
*/
-struct UFormattedNumberRangeData : public UMemory {
- // The magic number to identify incoming objects.
- // Reads in ASCII as "FDR" (FormatteDnumberRange with room at the end)
- static constexpr int32_t kMagic = 0x46445200;
+class UFormattedNumberRangeData : public FormattedValueNumberStringBuilderImpl {
+public:
+ UFormattedNumberRangeData() : FormattedValueNumberStringBuilderImpl(0) {}
+ virtual ~UFormattedNumberRangeData();
- // Data members:
- int32_t fMagic = kMagic;
DecimalQuantity quantity1;
DecimalQuantity quantity2;
- NumberStringBuilder string;
UNumberRangeIdentityResult identityResult = UNUM_IDENTITY_RESULT_COUNT;
-
- // No C conversion methods (no C API yet)
};
auto *decFmt = dynamic_cast<DecimalFormat *>(numberFormat);
if(decFmt != nullptr) {
decFmt->toNumberFormatter().formatImpl(&data, status); // mutates &data
- numberString = data.string.toUnicodeString();
+ numberString = data.getStringRef().toUnicodeString();
} else {
if (offset == 0) {
numberFormat->format(numberObject, numberString, status);
if (U_FAILURE(status)) {
return;
}
- output = std::move(fn.string);
+ output = std::move(fn.getStringRef());
pluralKeyword = rules.select(fn.quantity);
} else {
UnicodeString result;
if (U_FAILURE(localStatus)) {
return;
}
- appendTo.append(result.string.toTempUnicodeString());
+ appendTo.append(result.getStringRef().toTempUnicodeString());
return;
}
/**
* An immutable class containing the result of a date interval formatting operation.
*
- * Not intended for public subclassing.
+ * Instances of this class are immutable and thread-safe.
*
* When calling nextPosition():
* The fields are returned from left to right. The special field category
* corresponding fields in UFIELD_CATEGORY_DATE
* in the nextPosition() iterator.
*
+ * Not intended for public subclassing.
+ *
* @draft ICU 64
*/
class U_I18N_API FormattedDateInterval : public UMemory, public FormattedValue {
/**
* An immutable class containing the result of a list formatting operation.
*
+ * Instances of this class are immutable and thread-safe.
+ *
* When calling nextPosition():
* The fields are returned from start to end. The special field category
* UFIELD_CATEGORY_LIST_SPAN is used to indicate which argument
struct MacroProps;
struct MicroProps;
class DecimalQuantity;
-struct UFormattedNumberData;
+class UFormattedNumberData;
class NumberFormatterImpl;
struct ParsedPatternInfo;
class ScientificModifier;
/**
* Default constructor; makes an empty FormattedNumber.
+ * @draft ICU 60
*/
FormattedNumber()
- : fResults(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {};
-
- /**
- * Copying not supported; use move constructor instead.
- */
- FormattedNumber(const FormattedNumber&) = delete;
+ : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {};
/**
- * Move constructor:
- * Leaves the source FormattedNumber in an undefined state.
+ * Move constructor: Leaves the source FormattedNumber in an undefined state.
* @draft ICU 62
*/
FormattedNumber(FormattedNumber&& src) U_NOEXCEPT;
/**
- * Destruct an instance of FormattedNumber, cleaning up any memory it might own.
+ * Destruct an instance of FormattedNumber.
* @draft ICU 60
*/
virtual ~FormattedNumber() U_OVERRIDE;
- /**
- * Copying not supported; use move assignment instead.
- */
+ /** Copying not supported; use move constructor instead. */
+ FormattedNumber(const FormattedNumber&) = delete;
+
+ /** Copying not supported; use move assignment instead. */
FormattedNumber& operator=(const FormattedNumber&) = delete;
/**
- * Move assignment:
- * Leaves the source FormattedNumber in an undefined state.
+ * Move assignment: Leaves the source FormattedNumber in an undefined state.
* @draft ICU 62
*/
FormattedNumber& operator=(FormattedNumber&& src) U_NOEXCEPT;
- /**
- * @copydoc FormattedValue::toString()
- */
+ /** @copydoc FormattedValue::toString() */
UnicodeString toString(UErrorCode& status) const U_OVERRIDE;
- /**
- * @copydoc FormattedValue::toTempString()
- */
+ /** @copydoc FormattedValue::toTempString() */
UnicodeString toTempString(UErrorCode& status) const U_OVERRIDE;
- /**
- * @copydoc FormattedValue::appendTo()
- */
+ /** @copydoc FormattedValue::appendTo() */
Appendable &appendTo(Appendable& appendable, UErrorCode& status) const U_OVERRIDE;
- /**
- * @copydoc FormattedValue::nextPosition()
- */
+ /** @copydoc FormattedValue::nextPosition() */
UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE;
/**
private:
// Can't use LocalPointer because UFormattedNumberData is forward-declared
- impl::UFormattedNumberData *fResults;
+ const impl::UFormattedNumberData *fData;
// Error code for the terminal methods
UErrorCode fErrorCode;
* @internal
*/
explicit FormattedNumber(impl::UFormattedNumberData *results)
- : fResults(results), fErrorCode(U_ZERO_ERROR) {};
+ : fData(results), fErrorCode(U_ZERO_ERROR) {};
explicit FormattedNumber(UErrorCode errorCode)
- : fResults(nullptr), fErrorCode(errorCode) {};
+ : fData(nullptr), fErrorCode(errorCode) {};
// To give LocalizedNumberFormatter format methods access to this class's constructor:
friend class LocalizedNumberFormatter;
// Forward declarations:
struct RangeMacroProps;
class DecimalQuantity;
-struct UFormattedNumberRangeData;
+class UFormattedNumberRangeData;
class NumberRangeFormatterImpl;
} // namespace impl
private:
// Can't use LocalPointer because UFormattedNumberRangeData is forward-declared
- const impl::UFormattedNumberRangeData *fResults;
+ const impl::UFormattedNumberRangeData *fData;
// Error code for the terminal methods
UErrorCode fErrorCode;
* @internal
*/
explicit FormattedNumberRange(impl::UFormattedNumberRangeData *results)
- : fResults(results), fErrorCode(U_ZERO_ERROR) {};
+ : fData(results), fErrorCode(U_ZERO_ERROR) {};
explicit FormattedNumberRange(UErrorCode errorCode)
- : fResults(nullptr), fErrorCode(errorCode) {};
+ : fData(nullptr), fErrorCode(errorCode) {};
void getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const;
/**
* An immutable class containing the result of a relative datetime formatting operation.
*
+ * Instances of this class are immutable and thread-safe.
+ *
* Not intended for public subclassing.
*
* @draft ICU 64
/**
- * Creates a new UFormattedNumber for holding the result of a number formatting operation.
- *
- * Objects of type UFormattedNumber are not guaranteed to be threadsafe.
- *
- * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead.
+ * Creates an object to hold the result of a UNumberFormatter
+ * operation. The object can be used repeatedly; it is cleared whenever
+ * passed to a format function.
*
* @param ec Set if an error occurs.
* @draft ICU 62
* @draft ICU 64
*/
U_DRAFT const UFormattedValue* U_EXPORT2
-unumf_resultAsFormattedValue(const UFormattedNumber* uresult, UErrorCode* ec);
+unumf_resultAsValue(const UFormattedNumber* uresult, UErrorCode* ec);
/**
* Also see ufmtval_getString, which returns a NUL-terminated string:
*
* int32_t len;
- * const UChar* str = ufmtval_getString(unumf_resultAsFormattedValue(uresult, &ec), &len, &ec);
+ * const UChar* str = ufmtval_getString(unumf_resultAsValue(uresult, &ec), &len, &ec);
*
* NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead.
*
/**
* Releases the UNumberFormatter created by unumf_openForSkeletonAndLocale().
*
- * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead.
- *
* @param uformatter An object created by unumf_openForSkeletonAndLocale().
* @draft ICU 62
*/
/**
* Releases the UFormattedNumber created by unumf_openResult().
*
- * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead.
- *
* @param uresult An object created by unumf_openResult().
* @draft ICU 62
*/
unumf_formatInt(uformatter, 55000, uresult, &ec); // "55.00 K"
if (assertSuccessCheck("Should format without error", &ec, TRUE)) {
- const UFormattedValue* fv = unumf_resultAsFormattedValue(uresult, &ec);
+ const UFormattedValue* fv = unumf_resultAsValue(uresult, &ec);
assertSuccess("Should convert without error", &ec);
static const UFieldPosition expectedFieldPositions[] = {
// field, begin index, end index
standardplural.o plurrule.o
deps
# FormattedNumber internals:
- number_representation format
+ number_representation format formatted_value_sbimpl
# PluralRules internals:
unifiedcache
import com.ibm.icu.text.Replaceable;
import com.ibm.icu.text.UTF16;
import com.ibm.icu.text.UnicodeMatcher;
+import com.ibm.icu.util.ICUUncheckedIOException;
public final class Utility {
}
return hash;
}
+
+ /**
+ * Appends a CharSequence to an Appendable, converting IOException to ICUUncheckedIOException.
+ */
+ public static <A extends Appendable> A appendTo(CharSequence string, A appendable) {
+ try {
+ appendable.append(string);
+ return appendable;
+ } catch (IOException e) {
+ throw new ICUUncheckedIOException(e);
+ }
+ }
}
// License & terms of use: http://www.unicode.org/copyright.html#License
package com.ibm.icu.number;
-import java.io.IOException;
import java.math.BigDecimal;
import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.util.Arrays;
+import com.ibm.icu.impl.Utility;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.NumberStringBuilder;
import com.ibm.icu.text.ConstrainedFieldPosition;
import com.ibm.icu.text.FormattedValue;
import com.ibm.icu.text.PluralRules.IFixedDecimal;
-import com.ibm.icu.util.ICUUncheckedIOException;
/**
* The result of a number formatting operation. This class allows the result to be exported in several
* @see NumberFormatter
*/
public class FormattedNumber implements FormattedValue {
- final NumberStringBuilder nsb;
+ final NumberStringBuilder string;
final DecimalQuantity fq;
FormattedNumber(NumberStringBuilder nsb, DecimalQuantity fq) {
- this.nsb = nsb;
+ this.string = nsb;
this.fq = fq;
}
*/
@Override
public String toString() {
- return nsb.toString();
+ return string.toString();
}
/**
* {@inheritDoc}
*
- * @return The same Appendable, for chaining.
- * @draft ICU 60
+ * @draft ICU 64
+ * @provisional This API might change or be removed in a future release.
*/
@Override
- public <A extends Appendable> A appendTo(A appendable) {
- try {
- appendable.append(nsb);
- } catch (IOException e) {
- // Throw as an unchecked exception to avoid users needing try/catch
- throw new ICUUncheckedIOException(e);
- }
- return appendable;
+ public int length() {
+ return string.length();
}
/**
*/
@Override
public char charAt(int index) {
- return nsb.charAt(index);
+ return string.charAt(index);
}
/**
* @provisional This API might change or be removed in a future release.
*/
@Override
- public int length() {
- return nsb.length();
+ public CharSequence subSequence(int start, int end) {
+ return string.subString(start, end);
}
/**
* {@inheritDoc}
*
- * @draft ICU 64
+ * @draft ICU 60
* @provisional This API might change or be removed in a future release.
*/
@Override
- public CharSequence subSequence(int start, int end) {
- return nsb.subString(start, end);
+ public <A extends Appendable> A appendTo(A appendable) {
+ return Utility.appendTo(string, appendable);
}
/**
*/
@Override
public boolean nextPosition(ConstrainedFieldPosition cfpos) {
- return nsb.nextPosition(cfpos, null);
+ return string.nextPosition(cfpos, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @draft ICU 62
+ * @provisional This API might change or be removed in a future release.
+ */
+ @Override
+ public AttributedCharacterIterator toCharacterIterator() {
+ return string.toCharacterIterator(null);
}
/**
*/
public boolean nextFieldPosition(FieldPosition fieldPosition) {
fq.populateUFieldPosition(fieldPosition);
- return nsb.nextFieldPosition(fieldPosition);
- }
-
- /**
- * {@inheritDoc}
- *
- * @draft ICU 62
- * @provisional This API might change or be removed in a future release.
- */
- @Override
- public AttributedCharacterIterator toCharacterIterator() {
- return nsb.toCharacterIterator(null);
+ return string.nextFieldPosition(fieldPosition);
}
/**
public int hashCode() {
// NumberStringBuilder and BigDecimal are mutable, so we can't call
// #equals() or #hashCode() on them directly.
- return Arrays.hashCode(nsb.toCharArray())
- ^ Arrays.hashCode(nsb.toFieldArray())
+ return Arrays.hashCode(string.toCharArray())
+ ^ Arrays.hashCode(string.toFieldArray())
^ fq.toBigDecimal().hashCode();
}
// NumberStringBuilder and BigDecimal are mutable, so we can't call
// #equals() or #hashCode() on them directly.
FormattedNumber _other = (FormattedNumber) other;
- return Arrays.equals(nsb.toCharArray(), _other.nsb.toCharArray())
- && Arrays.equals(nsb.toFieldArray(), _other.nsb.toFieldArray())
+ return Arrays.equals(string.toCharArray(), _other.string.toCharArray())
+ && Arrays.equals(string.toFieldArray(), _other.string.toFieldArray())
&& fq.toBigDecimal().equals(_other.fq.toBigDecimal());
}
}
\ No newline at end of file
* Represents the result of a formatting operation of a relative datetime.
* Access the string value or field information.
*
+ * Instances of this class are immutable and thread-safe.
+ *
+ * Not intended for public subclassing.
+ *
* @author sffc
* @draft ICU 64
* @provisional This API might change or be removed in a future release.