ICU-20562 Adding toDecimalNumber method to C++ FormattedNumber.
This commit is contained in:
parent
4e07b85279
commit
4785f55622
@ -55,6 +55,8 @@ class U_I18N_API DecNum : public UMemory {
|
||||
|
||||
bool isZero() const;
|
||||
|
||||
void toString(ByteSink& output, UErrorCode& status) const;
|
||||
|
||||
inline const decNumber* getRawDecNumber() const {
|
||||
return fData.getAlias();
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "number_utypes.h"
|
||||
#include "util.h"
|
||||
#include "number_decimalquantity.h"
|
||||
#include "number_decnum.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
namespace number {
|
||||
@ -28,6 +29,13 @@ void FormattedNumber::getAllFieldPositions(FieldPositionIterator& iterator, UErr
|
||||
getAllFieldPositionsImpl(fpih, status);
|
||||
}
|
||||
|
||||
void FormattedNumber::toDecimalNumber(ByteSink& sink, UErrorCode& status) const {
|
||||
UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG)
|
||||
impl::DecNum decnum;
|
||||
fData->quantity.toDecNum(decnum, status);
|
||||
decnum.toString(sink, status);
|
||||
}
|
||||
|
||||
void FormattedNumber::getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih,
|
||||
UErrorCode& status) const {
|
||||
UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG)
|
||||
|
@ -252,4 +252,15 @@ bool DecNum::isZero() const {
|
||||
return decNumberIsZero(fData.getAlias());
|
||||
}
|
||||
|
||||
void DecNum::toString(ByteSink& output, UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
// "string must be at least dn->digits+14 characters long"
|
||||
int32_t minCapacity = fData.getAlias()->digits + 14;
|
||||
MaybeStackArray<char, 30> buffer(minCapacity);
|
||||
uprv_decNumberToString(fData, buffer.getAlias());
|
||||
output.Append(buffer.getAlias(), static_cast<int32_t>(uprv_strlen(buffer.getAlias())));
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
@ -11,8 +11,9 @@
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/appendable.h"
|
||||
#include "unicode/dcfmtsym.h"
|
||||
#include "unicode/bytestream.h"
|
||||
#include "unicode/currunit.h"
|
||||
#include "unicode/dcfmtsym.h"
|
||||
#include "unicode/fieldpos.h"
|
||||
#include "unicode/formattedvalue.h"
|
||||
#include "unicode/fpositer.h"
|
||||
@ -2520,6 +2521,27 @@ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue {
|
||||
*/
|
||||
void getAllFieldPositions(FieldPositionIterator &iterator, UErrorCode &status) const;
|
||||
|
||||
/**
|
||||
* Export the formatted number as a "numeric string" conforming to the
|
||||
* syntax defined in the Decimal Arithmetic Specification, available at
|
||||
* http://speleotrove.com/decimal
|
||||
*
|
||||
* This endpoint is useful for obtaining the exact number being printed
|
||||
* after scaling and rounding have been applied by the number formatter.
|
||||
*
|
||||
* Example call site:
|
||||
*
|
||||
* auto decimalNumber = fn.toDecimalNumber<std::string>(status);
|
||||
*
|
||||
* @tparam StringClass A string class compatible with StringByteSink;
|
||||
* for example, std::string.
|
||||
* @param status Set if an error occurs.
|
||||
* @return A StringClass containing the numeric string.
|
||||
* @draft ICU 65
|
||||
*/
|
||||
template<typename StringClass>
|
||||
inline StringClass toDecimalNumber(UErrorCode& status) const;
|
||||
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
|
||||
/**
|
||||
@ -2553,6 +2575,9 @@ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue {
|
||||
explicit FormattedNumber(UErrorCode errorCode)
|
||||
: fData(nullptr), fErrorCode(errorCode) {}
|
||||
|
||||
// TODO(ICU-20775): Propose this as API.
|
||||
void toDecimalNumber(ByteSink& sink, UErrorCode& status) const;
|
||||
|
||||
// To give LocalizedNumberFormatter format methods access to this class's constructor:
|
||||
friend class LocalizedNumberFormatter;
|
||||
|
||||
@ -2560,6 +2585,16 @@ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue {
|
||||
friend struct impl::UFormattedNumberImpl;
|
||||
};
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
template<typename StringClass>
|
||||
StringClass FormattedNumber::toDecimalNumber(UErrorCode& status) const {
|
||||
StringClass result;
|
||||
StringByteSink<StringClass> sink(&result);
|
||||
toDecimalNumber(sink, status);
|
||||
return result;
|
||||
};
|
||||
#endif // U_HIDE_DRAFT_API
|
||||
|
||||
/**
|
||||
* See the main description in numberformatter.h for documentation and examples.
|
||||
*
|
||||
|
@ -650,6 +650,13 @@ unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPosition
|
||||
UErrorCode* ec);
|
||||
|
||||
|
||||
// TODO(ICU-20775): Propose this as API.
|
||||
// NOTE: This is not currently implemented.
|
||||
// U_DRAFT int32_t U_EXPORT2
|
||||
// unumf_resultToDecimalNumber(const UFormattedNumber* uresult, char* buffer, int32_t bufferCapacity,
|
||||
// UErrorCode* ec);
|
||||
|
||||
|
||||
/**
|
||||
* Releases the UNumberFormatter created by unumf_openForSkeletonAndLocale().
|
||||
*
|
||||
|
@ -82,6 +82,7 @@ class NumberFormatterApiTest : public IntlTestWithFieldPosition {
|
||||
void copyMove();
|
||||
void localPointerCAPI();
|
||||
void toObject();
|
||||
void toDecimalNumber();
|
||||
|
||||
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
|
||||
|
||||
|
@ -104,6 +104,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
|
||||
TESTCASE_AUTO(copyMove);
|
||||
TESTCASE_AUTO(localPointerCAPI);
|
||||
TESTCASE_AUTO(toObject);
|
||||
TESTCASE_AUTO(toDecimalNumber);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
||||
@ -3033,6 +3034,18 @@ void NumberFormatterApiTest::toObject() {
|
||||
}
|
||||
}
|
||||
|
||||
void NumberFormatterApiTest::toDecimalNumber() {
|
||||
IcuTestErrorCode status(*this, "toDecimalNumber");
|
||||
FormattedNumber fn = NumberFormatter::withLocale("bn-BD")
|
||||
.scale(Scale::powerOfTen(2))
|
||||
.precision(Precision::maxSignificantDigits(5))
|
||||
.formatDouble(9.87654321e12, status);
|
||||
assertEquals("Should have expected localized string result",
|
||||
u"৯৮,৭৬,৫০,০০,০০,০০,০০০", fn.toString(status));
|
||||
assertEquals(u"Should have expected toDecimalNumber string result",
|
||||
"9.8765E+14", fn.toDecimalNumber<std::string>(status).c_str());
|
||||
}
|
||||
|
||||
|
||||
void NumberFormatterApiTest::assertFormatDescending(const char16_t* umessage, const char16_t* uskeleton,
|
||||
const UnlocalizedNumberFormatter& f, Locale locale,
|
||||
|
Loading…
Reference in New Issue
Block a user