mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-07 06:25:30 +00:00
ICU-20409 Additional refactoring of FormattedValue implementations.
- Migrates Number[Range] formatter to helper macros. - Adds additional macros. - Syncs docstrings between subclasses.
This commit is contained in:
parent
8c2de1401e
commit
35b182767f
23 changed files with 213 additions and 406 deletions
|
@ -130,6 +130,10 @@ public:
|
|||
return fString;
|
||||
}
|
||||
|
||||
inline const number::impl::NumberStringBuilder& getStringRef() const {
|
||||
return fString;
|
||||
}
|
||||
|
||||
private:
|
||||
number::impl::NumberStringBuilder fString;
|
||||
number::impl::Field fNumericField;
|
||||
|
@ -146,12 +150,22 @@ struct UFormattedValueImpl : public UMemory, public UFormattedValueApiHelper {
|
|||
};
|
||||
|
||||
|
||||
/** 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() { \
|
||||
|
@ -167,47 +181,51 @@ struct UFormattedValueImpl : public UMemory, public UFormattedValueApiHelper {
|
|||
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; \
|
||||
} \
|
||||
if (fData == nullptr) { \
|
||||
status = fErrorCode; \
|
||||
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; \
|
||||
} \
|
||||
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; \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of the standard methods for a UFormattedValue "subclass" C API.
|
||||
* @param CPPType The public C++ type, like FormattedList
|
||||
|
@ -232,30 +250,7 @@ struct UFormattedValueImpl : public UMemory, public UFormattedValueApiHelper {
|
|||
} \
|
||||
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
|
||||
|
|
|
@ -62,12 +62,12 @@ UnicodeString& LocalizedNumberFormatterAsFormat::format(const Formattable& obj,
|
|||
// 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;
|
||||
}
|
||||
|
||||
|
@ -84,10 +84,10 @@ UnicodeString& LocalizedNumberFormatterAsFormat::format(const Formattable& obj,
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ UFormattedNumberImpl::UFormattedNumberImpl()
|
|||
|
||||
UFormattedNumberImpl::~UFormattedNumberImpl() {
|
||||
// Disown the data from fImpl so it doesn't get deleted twice
|
||||
fImpl.fResults = nullptr;
|
||||
fImpl.fData = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -62,6 +62,13 @@ UFormattedNumberImpl::~UFormattedNumberImpl() {
|
|||
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);
|
||||
|
@ -101,16 +108,6 @@ unumf_openForSkeletonAndLocaleWithError(const UChar* skeleton, int32_t skeletonL
|
|||
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) {
|
||||
|
@ -118,7 +115,7 @@ unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNum
|
|||
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);
|
||||
}
|
||||
|
@ -130,7 +127,7 @@ unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedN
|
|||
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);
|
||||
}
|
||||
|
@ -142,20 +139,12 @@ unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32
|
|||
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) {
|
||||
|
@ -206,13 +195,6 @@ unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPosition
|
|||
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;
|
||||
|
|
|
@ -684,14 +684,14 @@ LocalizedNumberFormatter::formatDecimalQuantity(const DecimalQuantity& dq, UErro
|
|||
|
||||
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,
|
||||
|
|
|
@ -14,79 +14,13 @@ U_NAMESPACE_BEGIN
|
|||
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;
|
||||
}
|
||||
UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedNumber)
|
||||
|
||||
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(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 {
|
||||
|
@ -96,30 +30,17 @@ void FormattedNumber::getAllFieldPositions(FieldPositionIterator& iterator, UErr
|
|||
|
||||
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
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "number_types.h"
|
||||
#include "number_decimalquantity.h"
|
||||
#include "number_stringbuilder.h"
|
||||
#include "formattedval_impl.h"
|
||||
|
||||
U_NAMESPACE_BEGIN namespace number {
|
||||
namespace impl {
|
||||
|
@ -30,9 +31,12 @@ const DecimalQuantity* validateUFormattedNumberToDecimalQuantity(
|
|||
* 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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -331,7 +331,7 @@ void LocalizedNumberRangeFormatter::formatImpl(
|
|||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
results.string.writeTerminator(status);
|
||||
results.getStringRef().writeTerminator(status);
|
||||
}
|
||||
|
||||
const impl::NumberRangeFormatterImpl*
|
||||
|
@ -375,79 +375,13 @@ LocalizedNumberRangeFormatter::getFormatter(UErrorCode& status) const {
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedNumberRange)
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -457,52 +391,27 @@ void FormattedNumberRange::getAllFieldPositions(FieldPositionIterator& iterator,
|
|||
|
||||
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;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -279,8 +279,8 @@ void NumberRangeFormatterImpl::formatSingleValue(UFormattedNumberRangeData& data
|
|||
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);
|
||||
}
|
||||
|
@ -292,12 +292,12 @@ void NumberRangeFormatterImpl::formatApproximately (UFormattedNumberRangeData& d
|
|||
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);
|
||||
}
|
||||
|
@ -375,7 +375,7 @@ void NumberRangeFormatterImpl::formatRange(UFormattedNumberRangeData& data,
|
|||
break;
|
||||
}
|
||||
|
||||
NumberStringBuilder& string = data.string;
|
||||
NumberStringBuilder& string = data.getStringRef();
|
||||
int32_t lengthPrefix = 0;
|
||||
int32_t length1 = 0;
|
||||
int32_t lengthInfix = 0;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "number_decimalquantity.h"
|
||||
#include "number_formatimpl.h"
|
||||
#include "number_stringbuilder.h"
|
||||
#include "formattedval_impl.h"
|
||||
|
||||
U_NAMESPACE_BEGIN namespace number {
|
||||
namespace impl {
|
||||
|
@ -24,20 +25,18 @@ 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)
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -278,7 +278,7 @@ PluralFormat::format(const Formattable& numberObject, double number,
|
|||
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);
|
||||
|
|
|
@ -192,7 +192,7 @@ void QuantityFormatter::formatAndSelect(
|
|||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
output = std::move(fn.string);
|
||||
output = std::move(fn.getStringRef());
|
||||
pluralKeyword = rules.select(fn.quantity);
|
||||
} else {
|
||||
UnicodeString result;
|
||||
|
|
|
@ -2079,7 +2079,7 @@ SimpleDateFormat::zeroPaddingNumber(
|
|||
if (U_FAILURE(localStatus)) {
|
||||
return;
|
||||
}
|
||||
appendTo.append(result.string.toTempUnicodeString());
|
||||
appendTo.append(result.getStringRef().toTempUnicodeString());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ class DateIntervalFormat;
|
|||
/**
|
||||
* 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
|
||||
|
@ -50,6 +50,8 @@ class DateIntervalFormat;
|
|||
* 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 {
|
||||
|
|
|
@ -66,6 +66,8 @@ struct ListFormatData : public UMemory {
|
|||
/**
|
||||
* 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
|
||||
|
|
|
@ -131,7 +131,7 @@ class Padder;
|
|||
struct MacroProps;
|
||||
struct MicroProps;
|
||||
class DecimalQuantity;
|
||||
struct UFormattedNumberData;
|
||||
class UFormattedNumberData;
|
||||
class NumberFormatterImpl;
|
||||
struct ParsedPatternInfo;
|
||||
class ScientificModifier;
|
||||
|
@ -2399,58 +2399,45 @@ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue {
|
|||
|
||||
/**
|
||||
* Default constructor; makes an empty FormattedNumber.
|
||||
* @draft ICU 60
|
||||
*/
|
||||
FormattedNumber()
|
||||
: fResults(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {};
|
||||
: fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {};
|
||||
|
||||
/**
|
||||
* Copying not supported; use move constructor instead.
|
||||
*/
|
||||
FormattedNumber(const FormattedNumber&) = delete;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
|
@ -2523,7 +2510,7 @@ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue {
|
|||
|
||||
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;
|
||||
|
@ -2533,10 +2520,10 @@ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue {
|
|||
* @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;
|
||||
|
|
|
@ -176,7 +176,7 @@ namespace impl {
|
|||
// Forward declarations:
|
||||
struct RangeMacroProps;
|
||||
class DecimalQuantity;
|
||||
struct UFormattedNumberRangeData;
|
||||
class UFormattedNumberRangeData;
|
||||
class NumberRangeFormatterImpl;
|
||||
|
||||
} // namespace impl
|
||||
|
@ -828,7 +828,7 @@ class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue {
|
|||
|
||||
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;
|
||||
|
@ -838,10 +838,10 @@ class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue {
|
|||
* @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;
|
||||
|
||||
|
|
|
@ -252,6 +252,8 @@ class FormattedRelativeDateTimeData;
|
|||
/**
|
||||
* 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
|
||||
|
|
|
@ -473,11 +473,9 @@ unumf_openForSkeletonAndLocaleWithError(
|
|||
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -565,7 +563,7 @@ unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32
|
|||
* @draft ICU 64
|
||||
*/
|
||||
U_DRAFT const UFormattedValue* U_EXPORT2
|
||||
unumf_resultAsFormattedValue(const UFormattedNumber* uresult, UErrorCode* ec);
|
||||
unumf_resultAsValue(const UFormattedNumber* uresult, UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -576,7 +574,7 @@ unumf_resultAsFormattedValue(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.
|
||||
*
|
||||
|
@ -658,8 +656,6 @@ unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPosition
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@ -670,8 +666,6 @@ unumf_close(UNumberFormatter* uformatter);
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
|
|
@ -207,7 +207,7 @@ static void TestFormattedValue() {
|
|||
|
||||
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
|
||||
|
|
|
@ -949,7 +949,7 @@ group: number_output
|
|||
standardplural.o plurrule.o
|
||||
deps
|
||||
# FormattedNumber internals:
|
||||
number_representation format
|
||||
number_representation format formatted_value_sbimpl
|
||||
# PluralRules internals:
|
||||
unifiedcache
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import com.ibm.icu.lang.UCharacter;
|
|||
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 {
|
||||
|
||||
|
@ -1845,4 +1846,16 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,18 +2,17 @@
|
|||
// 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
|
||||
|
@ -24,11 +23,11 @@ import com.ibm.icu.util.ICUUncheckedIOException;
|
|||
* @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;
|
||||
}
|
||||
|
||||
|
@ -40,35 +39,7 @@ public class FormattedNumber implements FormattedValue {
|
|||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return nsb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return The same Appendable, for chaining.
|
||||
* @draft ICU 60
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @draft ICU 64
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
return nsb.charAt(index);
|
||||
return string.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,7 +50,18 @@ public class FormattedNumber implements FormattedValue {
|
|||
*/
|
||||
@Override
|
||||
public int length() {
|
||||
return nsb.length();
|
||||
return string.length();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @draft ICU 64
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
return string.charAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,7 +72,18 @@ public class FormattedNumber implements FormattedValue {
|
|||
*/
|
||||
@Override
|
||||
public CharSequence subSequence(int start, int end) {
|
||||
return nsb.subString(start, end);
|
||||
return string.subString(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @draft ICU 60
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
@Override
|
||||
public <A extends Appendable> A appendTo(A appendable) {
|
||||
return Utility.appendTo(string, appendable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,7 +94,18 @@ public class FormattedNumber implements FormattedValue {
|
|||
*/
|
||||
@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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,18 +143,7 @@ public class FormattedNumber implements FormattedValue {
|
|||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -186,8 +179,8 @@ public class FormattedNumber implements FormattedValue {
|
|||
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();
|
||||
}
|
||||
|
||||
|
@ -208,8 +201,8 @@ public class FormattedNumber implements FormattedValue {
|
|||
// 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());
|
||||
}
|
||||
}
|
|
@ -448,6 +448,10 @@ public final class RelativeDateTimeFormatter {
|
|||
* 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.
|
||||
|
|
Loading…
Add table
Reference in a new issue