ICU-20806 Removing obsolete number formatting methods.

See #1034
This commit is contained in:
Shane F. Carr 2020-03-24 07:03:31 +00:00 committed by Shane F. Carr
parent fc6612cc56
commit 6edd38f35f
21 changed files with 288 additions and 439 deletions

View File

@ -519,7 +519,9 @@ UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, Fie
return appendTo;
}
UErrorCode localStatus = U_ZERO_ERROR;
FormattedNumber output = fields->formatter.formatDouble(number, localStatus);
UFormattedNumberData output;
output.quantity.setToDouble(number);
fields->formatter.formatImpl(&output, localStatus);
fieldPositionHelper(output, pos, appendTo.length(), localStatus);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, localStatus);
@ -540,7 +542,9 @@ UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, Fie
if (pos.getField() == FieldPosition::DONT_CARE && fastFormatDouble(number, appendTo)) {
return appendTo;
}
FormattedNumber output = fields->formatter.formatDouble(number, status);
UFormattedNumberData output;
output.quantity.setToDouble(number);
fields->formatter.formatImpl(&output, status);
fieldPositionHelper(output, pos, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@ -562,7 +566,9 @@ DecimalFormat::format(double number, UnicodeString& appendTo, FieldPositionItera
if (posIter == nullptr && fastFormatDouble(number, appendTo)) {
return appendTo;
}
FormattedNumber output = fields->formatter.formatDouble(number, status);
UFormattedNumberData output;
output.quantity.setToDouble(number);
fields->formatter.formatImpl(&output, status);
fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@ -593,7 +599,9 @@ UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, Fi
return appendTo;
}
UErrorCode localStatus = U_ZERO_ERROR;
FormattedNumber output = fields->formatter.formatInt(number, localStatus);
UFormattedNumberData output;
output.quantity.setToLong(number);
fields->formatter.formatImpl(&output, localStatus);
fieldPositionHelper(output, pos, appendTo.length(), localStatus);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, localStatus);
@ -614,7 +622,9 @@ UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, Fi
if (pos.getField() == FieldPosition::DONT_CARE && fastFormatInt64(number, appendTo)) {
return appendTo;
}
FormattedNumber output = fields->formatter.formatInt(number, status);
UFormattedNumberData output;
output.quantity.setToLong(number);
fields->formatter.formatImpl(&output, status);
fieldPositionHelper(output, pos, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@ -636,7 +646,9 @@ DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPositionIter
if (posIter == nullptr && fastFormatInt64(number, appendTo)) {
return appendTo;
}
FormattedNumber output = fields->formatter.formatInt(number, status);
UFormattedNumberData output;
output.quantity.setToLong(number);
fields->formatter.formatImpl(&output, status);
fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@ -655,7 +667,9 @@ DecimalFormat::format(StringPiece number, UnicodeString& appendTo, FieldPosition
appendTo.setToBogus();
return appendTo;
}
FormattedNumber output = fields->formatter.formatDecimal(number, status);
UFormattedNumberData output;
output.quantity.setToDecNumber(number, status);
fields->formatter.formatImpl(&output, status);
fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@ -673,7 +687,9 @@ UnicodeString& DecimalFormat::format(const DecimalQuantity& number, UnicodeStrin
appendTo.setToBogus();
return appendTo;
}
FormattedNumber output = fields->formatter.formatDecimalQuantity(number, status);
UFormattedNumberData output;
output.quantity = number;
fields->formatter.formatImpl(&output, status);
fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@ -692,7 +708,9 @@ DecimalFormat::format(const DecimalQuantity& number, UnicodeString& appendTo, Fi
appendTo.setToBogus();
return appendTo;
}
FormattedNumber output = fields->formatter.formatDecimalQuantity(number, status);
UFormattedNumberData output;
output.quantity = number;
fields->formatter.formatImpl(&output, status);
fieldPositionHelper(output, pos, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@ -1703,8 +1721,11 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getCurrencyParser(UErrorC
}
void
DecimalFormat::fieldPositionHelper(const number::FormattedNumber& formatted, FieldPosition& fieldPosition,
int32_t offset, UErrorCode& status) {
DecimalFormat::fieldPositionHelper(
const UFormattedNumberData& formatted,
FieldPosition& fieldPosition,
int32_t offset,
UErrorCode& status) {
if (U_FAILURE(status)) { return; }
// always return first occurrence:
fieldPosition.setBeginIndex(0);
@ -1717,12 +1738,15 @@ DecimalFormat::fieldPositionHelper(const number::FormattedNumber& formatted, Fie
}
void
DecimalFormat::fieldPositionIteratorHelper(const number::FormattedNumber& formatted, FieldPositionIterator* fpi,
int32_t offset, UErrorCode& status) {
DecimalFormat::fieldPositionIteratorHelper(
const UFormattedNumberData& formatted,
FieldPositionIterator* fpi,
int32_t offset,
UErrorCode& status) {
if (U_SUCCESS(status) && (fpi != nullptr)) {
FieldPositionIteratorHandler fpih(fpi, status);
fpih.setShift(offset);
formatted.getAllFieldPositionsImpl(fpih, status);
formatted.getAllFieldPositions(fpih, status);
}
}

View File

@ -62,8 +62,9 @@ class FieldPositionOnlyHandler : public FieldPositionHandler {
// utility subclass FieldPositionIteratorHandler
// exported as U_I18N_API for tests
class FieldPositionIteratorHandler : public FieldPositionHandler {
class U_I18N_API FieldPositionIteratorHandler : public FieldPositionHandler {
FieldPositionIterator* iter; // can be NULL
UVector32* vec;
UErrorCode status;

View File

@ -38,6 +38,7 @@
#include "uassert.h"
#include "unicode/numberformatter.h"
#include "number_longnames.h"
#include "number_utypes.h"
#include "sharednumberformat.h"
#include "sharedpluralrules.h"
@ -47,6 +48,8 @@
U_NAMESPACE_BEGIN
using number::impl::UFormattedNumberData;
static constexpr int32_t WIDTH_INDEX_COUNT = UMEASFMT_WIDTH_NARROW + 1;
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MeasureFormat)
@ -504,12 +507,13 @@ UnicodeString &MeasureFormat::formatMeasurePerUnit(
status = U_UNSUPPORTED_ERROR;
return appendTo;
}
number::FormattedNumber result;
UFormattedNumberData result;
if (auto* lnf = df->toNumberFormatter(status)) {
result = lnf->unit(measure.getUnit())
result.quantity.setToDouble(measure.getNumber().getDouble(status));
lnf->unit(measure.getUnit())
.perUnit(perUnit)
.unitWidth(getUnitWidth(fWidth))
.formatDouble(measure.getNumber().getDouble(status), status);
.formatImpl(&result, status);
}
DecimalFormat::fieldPositionHelper(result, pos, appendTo.length(), status);
appendTo.append(result.toTempString(status));
@ -699,11 +703,12 @@ UnicodeString &MeasureFormat::formatMeasure(
SimpleFormatter formatter(pattern, 0, 1, status);
return QuantityFormatter::format(formatter, formattedNumber, appendTo, pos, status);
}
number::FormattedNumber result;
UFormattedNumberData result;
if (auto* lnf = df->toNumberFormatter(status)) {
result = lnf->unit(amtUnit)
result.quantity.setToDouble(amtNumber.getDouble(status));
lnf->unit(amtUnit)
.unitWidth(getUnitWidth(fWidth))
.formatDouble(amtNumber.getDouble(status), status);
.formatImpl(&result, status);
}
DecimalFormat::fieldPositionHelper(result, pos, appendTo.length(), status);
appendTo.append(result.toTempString(status));

View File

@ -156,7 +156,7 @@ unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t buf
return 0;
}
return result->fImpl.toTempString(*ec).extract(buffer, bufferCapacity, *ec);
return result->fData.toTempString(*ec).extract(buffer, bufferCapacity, *ec);
}
U_CAPI UBool U_EXPORT2
@ -173,7 +173,7 @@ unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* u
fp.setField(ufpos->field);
fp.setBeginIndex(ufpos->beginIndex);
fp.setEndIndex(ufpos->endIndex);
bool retval = result->fImpl.nextFieldPosition(fp, *ec);
bool retval = result->fData.nextFieldPosition(fp, *ec);
ufpos->beginIndex = fp.getBeginIndex();
ufpos->endIndex = fp.getEndIndex();
// NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
@ -192,7 +192,8 @@ unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPosition
}
auto* fpi = reinterpret_cast<FieldPositionIterator*>(ufpositer);
result->fImpl.getAllFieldPositions(*fpi, *ec);
FieldPositionIteratorHandler fpih(fpi, *ec);
result->fData.getAllFieldPositions(fpih, *ec);
}
U_CAPI void U_EXPORT2

View File

@ -19,16 +19,6 @@ UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedNumber)
#define UPRV_NOARG
UBool FormattedNumber::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const {
UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE)
return fData->nextFieldPosition(fieldPosition, status);
}
void FormattedNumber::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const {
FieldPositionIteratorHandler fpih(&iterator, status);
getAllFieldPositionsImpl(fpih, status);
}
void FormattedNumber::toDecimalNumber(ByteSink& sink, UErrorCode& status) const {
UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG)
impl::DecNum decnum;

View File

@ -30,8 +30,10 @@ 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.
*
* Exported as U_I18N_API for tests
*/
class UFormattedNumberData : public FormattedValueStringBuilderImpl {
class U_I18N_API UFormattedNumberData : public FormattedValueStringBuilderImpl {
public:
UFormattedNumberData() : FormattedValueStringBuilderImpl(kUndefinedField) {}
virtual ~UFormattedNumberData();

View File

@ -379,23 +379,6 @@ UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedNumberRange)
#define UPRV_NOARG
UBool FormattedNumberRange::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const {
UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE)
// NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
return fData->nextFieldPosition(fieldPosition, status);
}
void FormattedNumberRange::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const {
FieldPositionIteratorHandler fpih(&iterator, status);
getAllFieldPositionsImpl(fpih, status);
}
void FormattedNumberRange::getAllFieldPositionsImpl(
FieldPositionIteratorHandler& fpih, UErrorCode& status) const {
UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG)
fData->getAllFieldPositions(fpih, status);
}
UnicodeString FormattedNumberRange::getFirstDecimal(UErrorCode& status) const {
UPRV_FORMATTED_VALUE_METHOD_GUARD(ICU_Utility::makeBogusString())
return fData->quantity1.toScientificString();

View File

@ -53,10 +53,10 @@ class CompactDecimalFormat;
namespace number {
class LocalizedNumberFormatter;
class FormattedNumber;
namespace impl {
class DecimalQuantity;
struct DecimalFormatFields;
class UFormattedNumberData;
}
}
@ -2168,11 +2168,17 @@ class U_I18N_API DecimalFormat : public NumberFormat {
const numparse::impl::NumberParserImpl* getCurrencyParser(UErrorCode& status) const;
static void fieldPositionHelper(const number::FormattedNumber& formatted, FieldPosition& fieldPosition,
int32_t offset, UErrorCode& status);
static void fieldPositionHelper(
const number::impl::UFormattedNumberData& formatted,
FieldPosition& fieldPosition,
int32_t offset,
UErrorCode& status);
static void fieldPositionIteratorHelper(const number::FormattedNumber& formatted,
FieldPositionIterator* fpi, int32_t offset, UErrorCode& status);
static void fieldPositionIteratorHelper(
const number::impl::UFormattedNumberData& formatted,
FieldPositionIterator* fpi,
int32_t offset,
UErrorCode& status);
void setupFastFormat();

View File

@ -2490,60 +2490,6 @@ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue {
/** @copydoc FormattedValue::nextPosition() */
UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE;
#ifndef U_HIDE_DRAFT_API
/**
* Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given
* <em>field</em> in the output string. This allows you to determine the locations of, for example,
* the integer part, fraction part, or symbols.
*
* This is a simpler but less powerful alternative to {@link #nextPosition}.
*
* If a field occurs just once, calling this method will find that occurrence and return it. If a
* field occurs multiple times, this method may be called repeatedly with the following pattern:
*
* <pre>
* FieldPosition fpos(UNUM_GROUPING_SEPARATOR_FIELD);
* while (formattedNumber.nextFieldPosition(fpos, status)) {
* // do something with fpos.
* }
* </pre>
*
* This method is useful if you know which field to query. If you want all available field position
* information, use {@link #nextPosition} or {@link #getAllFieldPositions}.
*
* @param fieldPosition
* Input+output variable. On input, the "field" property determines which field to look
* up, and the "beginIndex" and "endIndex" properties determine where to begin the search.
* On output, the "beginIndex" is set to the beginning of the first occurrence of the
* field with either begin or end indices after the input indices; "endIndex" is set to
* the end of that occurrence of the field (exclusive index). If a field position is not
* found, the method returns FALSE and the FieldPosition may or may not be changed.
* @param status
* Set if an error occurs while populating the FieldPosition.
* @return TRUE if a new occurrence of the field was found; FALSE otherwise.
* @draft ICU 62
* @see UNumberFormatFields
*/
UBool nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const;
/**
* Export the formatted number to a FieldPositionIterator. This allows you to determine which characters in
* the output string correspond to which <em>fields</em>, such as the integer part, fraction part, and sign.
*
* This is an alternative to the more powerful #nextPosition() API.
*
* If information on only one field is needed, use #nextPosition() or #nextFieldPosition() instead.
*
* @param iterator
* The FieldPositionIterator to populate with all of the fields present in the formatted number.
* @param status
* Set if an error occurs while populating the FieldPositionIterator.
* @draft ICU 62
* @see UNumberFormatFields
*/
void getAllFieldPositions(FieldPositionIterator &iterator, UErrorCode &status) const;
#endif /* U_HIDE_DRAFT_API */
#ifndef U_HIDE_DRAFT_API
/**
* Export the formatted number as a "numeric string" conforming to the

View File

@ -728,52 +728,6 @@ class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue {
UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE;
#ifndef U_HIDE_DRAFT_API
/**
* Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given
* <em>field</em> in the output string. This allows you to determine the locations of, for example,
* the integer part, fraction part, or symbols.
*
* If both sides of the range have the same field, the field will occur twice, once before the
* range separator and once after the range separator, if applicable.
*
* If a field occurs just once, calling this method will find that occurrence and return it. If a
* field occurs multiple times, this method may be called repeatedly with the following pattern:
*
* <pre>
* FieldPosition fpos(UNUM_INTEGER_FIELD);
* while (formattedNumberRange.nextFieldPosition(fpos, status)) {
* // do something with fpos.
* }
* </pre>
*
* This method is useful if you know which field to query. If you want all available field position
* information, use #getAllFieldPositions().
*
* @param fieldPosition
* Input+output variable. See {@link FormattedNumber#nextFieldPosition}.
* @param status
* Set if an error occurs while populating the FieldPosition.
* @return TRUE if a new occurrence of the field was found; FALSE otherwise.
* @draft ICU 63
* @see UNumberFormatFields
*/
UBool nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const;
/**
* Export the formatted number range to a FieldPositionIterator. This allows you to determine which characters in
* the output string correspond to which <em>fields</em>, such as the integer part, fraction part, and sign.
*
* If information on only one field is needed, use #nextFieldPosition() instead.
*
* @param iterator
* The FieldPositionIterator to populate with all of the fields present in the formatted number.
* @param status
* Set if an error occurs while populating the FieldPositionIterator.
* @draft ICU 63
* @see UNumberFormatFields
*/
void getAllFieldPositions(FieldPositionIterator &iterator, UErrorCode &status) const;
/**
* Export the first formatted number as a decimal number. This endpoint
* is useful for obtaining the exact number being printed after scaling

View File

@ -427,7 +427,7 @@ typedef struct UFormattedNumber UFormattedNumber;
* NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead.
*
* @param skeleton The skeleton string, like u"percent precision-integer"
* @param skeletonLen The number of UChars in the skeleton string, or -1 it it is NUL-terminated.
* @param skeletonLen The number of UChars in the skeleton string, or -1 if it is NUL-terminated.
* @param locale The NUL-terminated locale ID.
* @param ec Set if an error occurs.
* @stable ICU 62
@ -443,7 +443,7 @@ unumf_openForSkeletonAndLocale(const UChar* skeleton, int32_t skeletonLen, const
* location of a skeleton syntax error if such a syntax error exists.
*
* @param skeleton The skeleton string, like u"percent precision-integer"
* @param skeletonLen The number of UChars in the skeleton string, or -1 it it is NUL-terminated.
* @param skeletonLen The number of UChars in the skeleton string, or -1 if it is NUL-terminated.
* @param locale The NUL-terminated locale ID.
* @param perror A parse error struct populated if an error occurs when parsing. Can be NULL.
* If no error occurs, perror->offset will be set to -1.

View File

@ -16,6 +16,9 @@
#include "number_utils.h"
#include "numbertest.h"
#include "unicode/utypes.h"
#include "number_utypes.h"
using number::impl::UFormattedNumberData;
// Horrible workaround for the lack of a status code in the constructor...
// (Also affects numbertest_range.cpp)
@ -2730,9 +2733,10 @@ void NumberFormatterApiTest::fieldPositionLogic() {
UPRV_LENGTHOF(expectedFieldPositions));
// Test the iteration functionality of nextFieldPosition
FieldPosition actual = {UNUM_GROUPING_SEPARATOR_FIELD};
ConstrainedFieldPosition actual;
actual.constrainField(UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD);
int32_t i = 1;
while (fmtd.nextFieldPosition(actual, status)) {
while (fmtd.nextPosition(actual, status)) {
UFieldPosition expected = expectedFieldPositions[i++];
assertEquals(
UnicodeString(u"Next for grouping, field, case #") + Int64ToUnicodeString(i),
@ -2741,18 +2745,19 @@ void NumberFormatterApiTest::fieldPositionLogic() {
assertEquals(
UnicodeString(u"Next for grouping, begin index, case #") + Int64ToUnicodeString(i),
expected.beginIndex,
actual.getBeginIndex());
actual.getStart());
assertEquals(
UnicodeString(u"Next for grouping, end index, case #") + Int64ToUnicodeString(i),
expected.endIndex,
actual.getEndIndex());
actual.getLimit());
}
assertEquals(u"Should have seen all grouping separators", 4, i);
// Make sure strings without fraction do not contain fraction field
actual = {UNUM_FRACTION_FIELD};
actual.reset();
actual.constrainField(UFIELD_CATEGORY_NUMBER, UNUM_FRACTION_FIELD);
fmtd = NumberFormatter::withLocale("en").formatInt(5, status);
assertFalse(u"No fraction part in an integer", fmtd.nextFieldPosition(actual, status));
assertFalse(u"No fraction part in an integer", fmtd.nextPosition(actual, status));
}
void NumberFormatterApiTest::fieldPositionCoverage() {
@ -3064,10 +3069,18 @@ void NumberFormatterApiTest::toFormat() {
dynamic_cast<LocalizedNumberFormatterAsFormat*>(format.getAlias())->getNumberFormatter()
.toSkeleton(status));
UFormattedNumberData result;
result.quantity.setToDouble(514.23);
lnf.formatImpl(&result, status);
FieldPositionIterator fpi1;
lnf.formatDouble(514.23, status).getAllFieldPositions(fpi1, status);
{
FieldPositionIteratorHandler fpih(&fpi1, status);
result.getAllFieldPositions(fpih, status);
}
FieldPositionIterator fpi2;
format->format(514.23, sb.remove(), &fpi2, status);
assertTrue("Should produce same field position iterator", fpi1 == fpi2);
}
@ -3119,19 +3132,20 @@ void NumberFormatterApiTest::errors() {
"Terminal toSkeleton on error object should be bogus",
output.isBogus());
// FieldPosition
// FieldPosition (constrained category)
status = U_ZERO_ERROR;
FieldPosition fp;
fn.nextFieldPosition(fp, status);
ConstrainedFieldPosition fp;
fp.constrainCategory(UFIELD_CATEGORY_NUMBER);
fn.nextPosition(fp, status);
assertEquals(
"Should fail on FieldPosition terminal method with correct error code",
U_NUMBER_ARG_OUTOFBOUNDS_ERROR,
status);
// FieldPositionIterator
// FieldPositionIterator (no constraints)
status = U_ZERO_ERROR;
FieldPositionIterator fpi;
fn.getAllFieldPositions(fpi, status);
fp.reset();
fn.nextPosition(fp, status);
assertEquals(
"Should fail on FieldPositoinIterator terminal method with correct error code",
U_NUMBER_ARG_OUTOFBOUNDS_ERROR,
@ -3592,64 +3606,6 @@ void NumberFormatterApiTest::assertNumberFieldPositions(
UFIELD_CATEGORY_NUMBER,
expectedFieldPositions,
length);
// Check FormattedNumber-specific functions
UnicodeString baseMessage = UnicodeString(message) + u": " + formattedNumber.toString(status) + u": ";
FieldPositionIterator fpi;
formattedNumber.getAllFieldPositions(fpi, status);
int32_t i = 0;
FieldPosition actual;
while (fpi.next(actual)) {
UFieldPosition expected = expectedFieldPositions[i++];
assertEquals(
baseMessage + UnicodeString(u"Field, case #") + Int64ToUnicodeString(i),
expected.field,
actual.getField());
assertEquals(
baseMessage + UnicodeString(u"Iterator, begin, case #") + Int64ToUnicodeString(i),
expected.beginIndex,
actual.getBeginIndex());
assertEquals(
baseMessage + UnicodeString(u"Iterator, end, case #") + Int64ToUnicodeString(i),
expected.endIndex,
actual.getEndIndex());
// Check for the first location of the field
FieldPosition actual2(expected.field);
// Fast-forward the field to skip previous occurrences of the field:
actual2.setBeginIndex(expected.beginIndex);
actual2.setEndIndex(expected.beginIndex);
UBool found = formattedNumber.nextFieldPosition(actual2, status);
assertEquals(
baseMessage + UnicodeString(u"Next, found first, case #") + Int64ToUnicodeString(i),
(UBool) TRUE,
found);
assertEquals(
baseMessage + UnicodeString(u"Next, begin, case #") + Int64ToUnicodeString(i),
expected.beginIndex,
actual2.getBeginIndex());
assertEquals(
baseMessage + UnicodeString(u"Next, end, case #") + Int64ToUnicodeString(i),
expected.endIndex,
actual2.getEndIndex());
// The next position should be empty unless the field occurs again
UBool occursAgain = false;
for (int32_t j=i; j<length; j++) {
if (expectedFieldPositions[j].field == expected.field) {
occursAgain = true;
break;
}
}
if (!occursAgain) {
found = formattedNumber.nextFieldPosition(actual2, status);
assertEquals(
baseMessage + UnicodeString(u"Next, found second, case #") + Int64ToUnicodeString(i),
(UBool) FALSE,
found);
}
}
assertEquals(baseMessage + u"Should have seen every field position", length, i);
}

View File

@ -12,7 +12,9 @@ import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import com.ibm.icu.number.FormattedNumber;
import com.ibm.icu.impl.FormattedStringBuilder;
import com.ibm.icu.impl.FormattedValueStringBuilderImpl;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.number.LocalizedNumberFormatter;
import com.ibm.icu.number.NumberFormatter;
import com.ibm.icu.util.ULocale;
@ -46,16 +48,18 @@ public class LocalizedNumberFormatterAsFormat extends Format {
if (!(obj instanceof Number)) {
throw new IllegalArgumentException();
}
FormattedNumber result = formatter.format((Number) obj);
DecimalQuantity dq = new DecimalQuantity_DualStorageBCD((Number) obj);
FormattedStringBuilder string = new FormattedStringBuilder();
formatter.formatImpl(dq, string);
// always return first occurrence:
pos.setBeginIndex(0);
pos.setEndIndex(0);
boolean found = result.nextFieldPosition(pos);
boolean found = FormattedValueStringBuilderImpl.nextFieldPosition(string, pos);
if (found && toAppendTo.length() != 0) {
pos.setBeginIndex(pos.getBeginIndex() + toAppendTo.length());
pos.setEndIndex(pos.getEndIndex() + toAppendTo.length());
}
result.appendTo(toAppendTo);
Utility.appendTo(string, toAppendTo);
return toAppendTo;
}

View File

@ -4,8 +4,6 @@ package com.ibm.icu.number;
import java.math.BigDecimal;
import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.util.Arrays;
import com.ibm.icu.impl.FormattedStringBuilder;
import com.ibm.icu.impl.FormattedValueStringBuilderImpl;
@ -107,44 +105,6 @@ public class FormattedNumber implements FormattedValue {
return FormattedValueStringBuilderImpl.toCharacterIterator(string, null);
}
/**
* Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the
* given <em>field</em> in the output string. This allows you to determine the locations of,
* for example, the integer part, fraction part, or symbols.
* <p>
* This is a simpler but less powerful alternative to {@link #nextPosition}.
* <p>
* If a field occurs just once, calling this method will find that occurrence and return it. If a
* field occurs multiple times, this method may be called repeatedly with the following pattern:
*
* <pre>
* FieldPosition fpos = new FieldPosition(NumberFormat.Field.GROUPING_SEPARATOR);
* while (formattedNumber.nextFieldPosition(fpos, status)) {
* // do something with fpos.
* }
* </pre>
* <p>
* This method is useful if you know which field to query. If you want all available field position
* information, use {@link #nextPosition} or {@link #toCharacterIterator()}.
*
* @param fieldPosition
* Input+output variable. On input, the "field" property determines which field to look
* up, and the "beginIndex" and "endIndex" properties determine where to begin the search.
* On output, the "beginIndex" is set to the beginning of the first occurrence of the
* field with either begin or end indices after the input indices, "endIndex" is set to
* the end of that occurrence of the field (exclusive index). If a field position is not
* found, the method returns FALSE and the FieldPosition may or may not be changed.
* @return true if a new occurrence of the field was found; false otherwise.
* @draft ICU 62
* @provisional This API might change or be removed in a future release.
* @see com.ibm.icu.text.NumberFormat.Field
* @see NumberFormatter
*/
public boolean nextFieldPosition(FieldPosition fieldPosition) {
fq.populateUFieldPosition(fieldPosition);
return FormattedValueStringBuilderImpl.nextFieldPosition(string, fieldPosition);
}
/**
* Export the formatted number as a BigDecimal. This endpoint is useful for obtaining the exact
* number being printed after scaling and rounding have been applied by the number formatting
@ -166,41 +126,4 @@ public class FormattedNumber implements FormattedValue {
public IFixedDecimal getFixedDecimal() {
return fq;
}
/**
* {@inheritDoc}
*
* @draft ICU 60
* @provisional This API might change or be removed in a future release.
*/
@Override
public int hashCode() {
// FormattedStringBuilder and BigDecimal are mutable, so we can't call
// #equals() or #hashCode() on them directly.
return Arrays.hashCode(string.toCharArray())
^ Arrays.hashCode(string.toFieldArray())
^ fq.toBigDecimal().hashCode();
}
/**
* {@inheritDoc}
*
* @draft ICU 60
* @provisional This API might change or be removed in a future release.
*/
@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (other == null)
return false;
if (!(other instanceof FormattedNumber))
return false;
// FormattedStringBuilder and BigDecimal are mutable, so we can't call
// #equals() or #hashCode() on them directly.
FormattedNumber _other = (FormattedNumber) other;
return Arrays.equals(string.toCharArray(), _other.string.toCharArray())
&& Arrays.equals(string.toFieldArray(), _other.string.toFieldArray())
&& fq.toBigDecimal().equals(_other.fq.toBigDecimal());
}
}

View File

@ -5,7 +5,6 @@ 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.FormattedStringBuilder;
@ -110,39 +109,6 @@ public class FormattedNumberRange implements FormattedValue {
return FormattedValueStringBuilderImpl.nextPosition(string, cfpos, null);
}
/**
* Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given
* <em>field</em> in the output string. This allows you to determine the locations of, for example,
* the integer part, fraction part, or symbols.
* <p>
* If both sides of the range have the same field, the field will occur twice, once before the range separator and
* once after the range separator, if applicable.
* <p>
* If a field occurs just once, calling this method will find that occurrence and return it. If a field occurs
* multiple times, this method may be called repeatedly with the following pattern:
*
* <pre>
* FieldPosition fpos = new FieldPosition(NumberFormat.Field.INTEGER);
* while (formattedNumberRange.nextFieldPosition(fpos, status)) {
* // do something with fpos.
* }
* </pre>
* <p>
* This method is useful if you know which field to query. If you want all available field position information, use
* {@link #toCharacterIterator()}.
*
* @param fieldPosition
* Input+output variable. See {@link FormattedNumber#nextFieldPosition(FieldPosition)}.
* @return true if a new occurrence of the field was found; false otherwise.
* @draft ICU 63
* @provisional This API might change or be removed in a future release.
* @see com.ibm.icu.text.NumberFormat.Field
* @see NumberRangeFormatter
*/
public boolean nextFieldPosition(FieldPosition fieldPosition) {
return FormattedValueStringBuilderImpl.nextFieldPosition(string, fieldPosition);
}
/**
* {@inheritDoc}
*

View File

@ -97,20 +97,11 @@ public class LocalizedNumberFormatter extends NumberFormatterSettings<LocalizedN
* @see NumberFormatter
*/
public FormattedNumber format(Measure input) {
DecimalQuantity fq = new DecimalQuantity_DualStorageBCD(input.getNumber());
MeasureUnit unit = input.getUnit();
Number number = input.getNumber();
// Use this formatter if possible
if (Objects.equals(resolve().unit, unit)) {
return format(number);
}
// This mechanism saves the previously used unit, so if the user calls this method with the
// same unit multiple times in a row, they get a more efficient code path.
LocalizedNumberFormatter withUnit = savedWithUnit;
if (withUnit == null || !Objects.equals(withUnit.resolve().unit, unit)) {
withUnit = new LocalizedNumberFormatter(this, KEY_UNIT, unit);
savedWithUnit = withUnit;
}
return withUnit.format(number);
FormattedStringBuilder string = new FormattedStringBuilder();
formatImpl(fq, unit, string);
return new FormattedNumber(string, fq);
}
/**
@ -161,6 +152,29 @@ public class LocalizedNumberFormatter extends NumberFormatterSettings<LocalizedN
}
}
/**
* Version of above for unit override.
*
* @internal
* @deprecated ICU 67 This API is ICU internal only.
*/
@Deprecated
public void formatImpl(DecimalQuantity fq, MeasureUnit unit, FormattedStringBuilder string) {
// Use this formatter if possible
if (Objects.equals(resolve().unit, unit)) {
formatImpl(fq, string);
return;
}
// This mechanism saves the previously used unit, so if the user calls this method with the
// same unit multiple times in a row, they get a more efficient code path.
LocalizedNumberFormatter withUnit = savedWithUnit;
if (withUnit == null || !Objects.equals(withUnit.resolve().unit, unit)) {
withUnit = new LocalizedNumberFormatter(this, KEY_UNIT, unit);
savedWithUnit = withUnit;
}
withUnit.formatImpl(fq, string);
}
/**
* @internal
* @deprecated This API is ICU internal only. Use {@link FormattedNumber#nextPosition}

View File

@ -346,25 +346,13 @@ public abstract class Precision implements Cloneable {
if (this.mathContext.equals(mathContext)) {
return this;
}
Precision other = (Precision) this.clone();
Precision other = createCopy();
other.mathContext = mathContext;
return other;
}
/**
* {@inheritDoc}
* @draft ICU 62
* @provisional This API might change or be removed in a future release.
*/
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// Should not happen since parent is Object
throw new AssertionError(e);
}
}
/** Package-private clone method */
abstract Precision createCopy();
/**
* @internal
@ -566,6 +554,13 @@ public abstract class Precision implements Cloneable {
value.roundToInfinity();
value.setMinFraction(0);
}
@Override
InfiniteRounderImpl createCopy() {
InfiniteRounderImpl copy = new InfiniteRounderImpl();
copy.mathContext = mathContext;
return copy;
}
}
static class FractionRounderImpl extends FractionPrecision {
@ -582,6 +577,13 @@ public abstract class Precision implements Cloneable {
value.roundToMagnitude(getRoundingMagnitudeFraction(maxFrac), mathContext);
value.setMinFraction(Math.max(0, -getDisplayMagnitudeFraction(minFrac)));
}
@Override
FractionRounderImpl createCopy() {
FractionRounderImpl copy = new FractionRounderImpl(minFrac, maxFrac);
copy.mathContext = mathContext;
return copy;
}
}
static class SignificantRounderImpl extends Precision {
@ -611,6 +613,13 @@ public abstract class Precision implements Cloneable {
assert quantity.isZeroish();
quantity.setMinFraction(minSig - minInt);
}
@Override
SignificantRounderImpl createCopy() {
SignificantRounderImpl copy = new SignificantRounderImpl(minSig, maxSig);
copy.mathContext = mathContext;
return copy;
}
}
static class FracSigRounderImpl extends Precision {
@ -642,6 +651,13 @@ public abstract class Precision implements Cloneable {
value.roundToMagnitude(roundingMag, mathContext);
value.setMinFraction(Math.max(0, -displayMag));
}
@Override
FracSigRounderImpl createCopy() {
FracSigRounderImpl copy = new FracSigRounderImpl(minFrac, maxFrac, minSig, maxSig);
copy.mathContext = mathContext;
return copy;
}
}
/**
@ -659,6 +675,13 @@ public abstract class Precision implements Cloneable {
value.roundToIncrement(increment, mathContext);
value.setMinFraction(increment.scale());
}
@Override
IncrementRounderImpl createCopy() {
IncrementRounderImpl copy = new IncrementRounderImpl(increment);
copy.mathContext = mathContext;
return copy;
}
}
/**
@ -681,6 +704,13 @@ public abstract class Precision implements Cloneable {
value.roundToMagnitude(-maxFrac, mathContext);
value.setMinFraction(minFrac);
}
@Override
IncrementOneRounderImpl createCopy() {
IncrementOneRounderImpl copy = new IncrementOneRounderImpl(increment, minFrac, maxFrac);
copy.mathContext = mathContext;
return copy;
}
}
/**
@ -701,6 +731,13 @@ public abstract class Precision implements Cloneable {
value.roundToNickel(-maxFrac, mathContext);
value.setMinFraction(minFrac);
}
@Override
IncrementFiveRounderImpl createCopy() {
IncrementFiveRounderImpl copy = new IncrementFiveRounderImpl(increment, minFrac, maxFrac);
copy.mathContext = mathContext;
return copy;
}
}
static class CurrencyRounderImpl extends CurrencyPrecision {
@ -715,6 +752,13 @@ public abstract class Precision implements Cloneable {
// Call .withCurrency() before .apply()!
throw new AssertionError();
}
@Override
CurrencyRounderImpl createCopy() {
CurrencyRounderImpl copy = new CurrencyRounderImpl(usage);
copy.mathContext = mathContext;
return copy;
}
}
private static int getRoundingMagnitudeFraction(int maxFrac) {

View File

@ -27,7 +27,7 @@ import com.ibm.icu.text.NumberFormat;
* @stable ICU 60
* @see NumberFormatter
*/
public class ScientificNotation extends Notation implements Cloneable {
public class ScientificNotation extends Notation {
int engineeringInterval;
boolean requireMinInt;
@ -62,7 +62,7 @@ public class ScientificNotation extends Notation implements Cloneable {
*/
public ScientificNotation withMinExponentDigits(int minExponentDigits) {
if (minExponentDigits >= 1 && minExponentDigits <= RoundingUtils.MAX_INT_FRAC_SIG) {
ScientificNotation other = (ScientificNotation) this.clone();
ScientificNotation other = createCopy();
other.minExponentDigits = minExponentDigits;
return other;
} else {
@ -87,23 +87,19 @@ public class ScientificNotation extends Notation implements Cloneable {
* @see NumberFormatter
*/
public ScientificNotation withExponentSignDisplay(SignDisplay exponentSignDisplay) {
ScientificNotation other = (ScientificNotation) this.clone();
ScientificNotation other = createCopy();
other.exponentSignDisplay = exponentSignDisplay;
return other;
}
/**
* @draft ICU 60
* @provisional This API might change or be removed in a future release.
*/
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// Should not happen since parent is Object
throw new AssertionError(e);
}
/** Package-private clone method */
ScientificNotation createCopy() {
return new ScientificNotation(
engineeringInterval,
requireMinInt,
minExponentDigits,
exponentSignDisplay
);
}
/* package-private */ MicroPropsGenerator withLocaleData(

View File

@ -12,9 +12,14 @@ import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.text.ParsePosition;
import com.ibm.icu.impl.FormattedStringBuilder;
import com.ibm.icu.impl.FormattedValueStringBuilderImpl;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.impl.number.AffixUtils;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.impl.number.DecimalFormatProperties.ParseMode;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
import com.ibm.icu.impl.number.Padder;
import com.ibm.icu.impl.number.Padder.PadPosition;
import com.ibm.icu.impl.number.PatternStringParser;
@ -708,9 +713,11 @@ public class DecimalFormat extends NumberFormat {
*/
@Override
public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
FormattedNumber output = formatter.format(number);
fieldPositionHelper(output, fieldPosition, result.length());
output.appendTo(result);
DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(number);
FormattedStringBuilder string = new FormattedStringBuilder();
formatter.formatImpl(dq, string);
fieldPositionHelper(dq, string, fieldPosition, result.length());
Utility.appendTo(string, result);
return result;
}
@ -721,9 +728,11 @@ public class DecimalFormat extends NumberFormat {
*/
@Override
public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
FormattedNumber output = formatter.format(number);
fieldPositionHelper(output, fieldPosition, result.length());
output.appendTo(result);
DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(number);
FormattedStringBuilder string = new FormattedStringBuilder();
formatter.formatImpl(dq, string);
fieldPositionHelper(dq, string, fieldPosition, result.length());
Utility.appendTo(string, result);
return result;
}
@ -734,9 +743,11 @@ public class DecimalFormat extends NumberFormat {
*/
@Override
public StringBuffer format(BigInteger number, StringBuffer result, FieldPosition fieldPosition) {
FormattedNumber output = formatter.format(number);
fieldPositionHelper(output, fieldPosition, result.length());
output.appendTo(result);
DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(number);
FormattedStringBuilder string = new FormattedStringBuilder();
formatter.formatImpl(dq, string);
fieldPositionHelper(dq, string, fieldPosition, result.length());
Utility.appendTo(string, result);
return result;
}
@ -748,9 +759,11 @@ public class DecimalFormat extends NumberFormat {
@Override
public StringBuffer format(
java.math.BigDecimal number, StringBuffer result, FieldPosition fieldPosition) {
FormattedNumber output = formatter.format(number);
fieldPositionHelper(output, fieldPosition, result.length());
output.appendTo(result);
DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(number);
FormattedStringBuilder string = new FormattedStringBuilder();
formatter.formatImpl(dq, string);
fieldPositionHelper(dq, string, fieldPosition, result.length());
Utility.appendTo(string, result);
return result;
}
@ -761,9 +774,11 @@ public class DecimalFormat extends NumberFormat {
*/
@Override
public StringBuffer format(BigDecimal number, StringBuffer result, FieldPosition fieldPosition) {
FormattedNumber output = formatter.format(number);
fieldPositionHelper(output, fieldPosition, result.length());
output.appendTo(result);
DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(number);
FormattedStringBuilder string = new FormattedStringBuilder();
formatter.formatImpl(dq, string);
fieldPositionHelper(dq, string, fieldPosition, result.length());
Utility.appendTo(string, result);
return result;
}
@ -792,12 +807,14 @@ public class DecimalFormat extends NumberFormat {
// because its caching mechanism will not provide any benefit here.
DecimalFormatSymbols localSymbols = (DecimalFormatSymbols) symbols.clone();
localSymbols.setCurrency(currAmt.getCurrency());
FormattedNumber output = formatter
.symbols(localSymbols)
DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(currAmt.getNumber());
FormattedStringBuilder string = new FormattedStringBuilder();
formatter.symbols(localSymbols)
.unit(currAmt.getCurrency())
.format(currAmt.getNumber());
fieldPositionHelper(output, fieldPosition, result.length());
output.appendTo(result);
.formatImpl(dq, string);
fieldPositionHelper(dq, string, fieldPosition, result.length());
Utility.appendTo(string, result);
return result;
}
@ -2585,11 +2602,13 @@ public synchronized void setParseStrictMode(ParseMode parseMode) {
PatternStringParser.parseToExistingProperties(pattern, properties, ignoreRounding);
}
static void fieldPositionHelper(FormattedNumber formatted, FieldPosition fieldPosition, int offset) {
static void fieldPositionHelper(
DecimalQuantity dq, FormattedStringBuilder string, FieldPosition fieldPosition, int offset) {
// always return first occurrence:
fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
boolean found = formatted.nextFieldPosition(fieldPosition);
dq.populateUFieldPosition(fieldPosition);
boolean found = FormattedValueStringBuilderImpl.nextFieldPosition(string, fieldPosition);;
if (found && offset != 0) {
fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + offset);
fieldPosition.setEndIndex(fieldPosition.getEndIndex() + offset);

View File

@ -31,13 +31,16 @@ import java.util.concurrent.ConcurrentHashMap;
import com.ibm.icu.impl.DontCareFieldPosition;
import com.ibm.icu.impl.FormattedStringBuilder;
import com.ibm.icu.impl.FormattedValueStringBuilderImpl;
import com.ibm.icu.impl.ICUData;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.SimpleFormatterImpl;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
import com.ibm.icu.impl.number.LongNameHandler;
import com.ibm.icu.impl.number.RoundingUtils;
import com.ibm.icu.number.FormattedNumber;
import com.ibm.icu.number.IntegerWidth;
import com.ibm.icu.number.LocalizedNumberFormatter;
import com.ibm.icu.number.NumberFormatter;
@ -320,9 +323,10 @@ public class MeasureFormat extends UFormat {
} else if (obj instanceof Measure[]) {
formatMeasuresInternal(toAppendTo, fpos, (Measure[]) obj);
} else if (obj instanceof Measure) {
FormattedNumber result = formatMeasure((Measure) obj);
result.nextFieldPosition(fpos); // No offset: toAppendTo.length() is considered below
result.appendTo(toAppendTo);
FormattedStringBuilder result = formatMeasure((Measure) obj);
// No offset: toAppendTo.length() is considered below
FormattedValueStringBuilderImpl.nextFieldPosition(result, fpos);
Utility.appendTo(result, toAppendTo);
} else {
throw new IllegalArgumentException(obj.toString());
}
@ -386,11 +390,13 @@ public class MeasureFormat extends UFormat {
MeasureUnit perUnit,
StringBuilder appendTo,
FieldPosition pos) {
FormattedNumber result = getUnitFormatterFromCache(NUMBER_FORMATTER_STANDARD,
measure.getUnit(),
perUnit).format(measure.getNumber());
DecimalFormat.fieldPositionHelper(result, pos, appendTo.length());
result.appendTo(appendTo);
DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(measure.getNumber());
FormattedStringBuilder string = new FormattedStringBuilder();
getUnitFormatterFromCache(
NUMBER_FORMATTER_STANDARD, measure.getUnit(), perUnit
).formatImpl(dq, string);
DecimalFormat.fieldPositionHelper(dq, string, pos, appendTo.length());
Utility.appendTo(string, appendTo);
return appendTo;
}
@ -433,9 +439,9 @@ public class MeasureFormat extends UFormat {
return;
}
if (measures.length == 1) {
FormattedNumber result = formatMeasure(measures[0]);
result.nextFieldPosition(fieldPosition);
result.appendTo(appendTo);
FormattedStringBuilder result = formatMeasure(measures[0]);
FormattedValueStringBuilderImpl.nextFieldPosition(result, fieldPosition);
Utility.appendTo(result, appendTo);
return;
}
@ -768,20 +774,26 @@ public class MeasureFormat extends UFormat {
/// END NUMBER FORMATTER CACHING MACHINERY ///
private FormattedNumber formatMeasure(Measure measure) {
private FormattedStringBuilder formatMeasure(Measure measure) {
MeasureUnit unit = measure.getUnit();
DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(measure.getNumber());
FormattedStringBuilder string = new FormattedStringBuilder();
if (unit instanceof Currency) {
return getUnitFormatterFromCache(NUMBER_FORMATTER_CURRENCY, unit, null)
.format(measure.getNumber());
getUnitFormatterFromCache(NUMBER_FORMATTER_CURRENCY, unit, null)
.formatImpl(dq, string);
} else {
return getUnitFormatterFromCache(NUMBER_FORMATTER_STANDARD, unit, null)
.format(measure.getNumber());
getUnitFormatterFromCache(NUMBER_FORMATTER_STANDARD, unit, null)
.formatImpl(dq, string);
}
return string;
}
private FormattedNumber formatMeasureInteger(Measure measure) {
return getUnitFormatterFromCache(NUMBER_FORMATTER_INTEGER, measure.getUnit(), null)
.format(measure.getNumber());
private FormattedStringBuilder formatMeasureInteger(Measure measure) {
DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(measure.getNumber());
FormattedStringBuilder string = new FormattedStringBuilder();
getUnitFormatterFromCache(NUMBER_FORMATTER_INTEGER, measure.getUnit(), null)
.formatImpl(dq, string);
return string;
}
private void formatMeasuresSlowTrack(
@ -797,14 +809,14 @@ public class MeasureFormat extends UFormat {
int fieldPositionFoundIndex = -1;
for (int i = 0; i < measures.length; ++i) {
FormattedNumber result;
FormattedStringBuilder result;
if (i == measures.length - 1) {
result = formatMeasure(measures[i]);
} else {
result = formatMeasureInteger(measures[i]);
}
if (fieldPositionFoundIndex == -1) {
result.nextFieldPosition(fpos);
FormattedValueStringBuilderImpl.nextFieldPosition(result, fpos);
if (fpos.getEndIndex() != 0) {
fieldPositionFoundIndex = i;
}

View File

@ -46,6 +46,7 @@ import com.ibm.icu.number.Precision;
import com.ibm.icu.number.Scale;
import com.ibm.icu.number.ScientificNotation;
import com.ibm.icu.number.UnlocalizedNumberFormatter;
import com.ibm.icu.text.ConstrainedFieldPosition;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.text.NumberingSystem;
@ -2585,9 +2586,10 @@ public class NumberFormatterApiTest {
assertNumberFieldPositions(message, fmtd, expectedFieldPositions);
// Test the iteration functionality of nextFieldPosition
FieldPosition actual = new FieldPosition(NumberFormat.Field.GROUPING_SEPARATOR);
ConstrainedFieldPosition actual = new ConstrainedFieldPosition();
actual.constrainField(NumberFormat.Field.GROUPING_SEPARATOR);
int i = 1;
while (fmtd.nextFieldPosition(actual)) {
while (fmtd.nextPosition(actual)) {
Object[] cas = expectedFieldPositions[i++];
NumberFormat.Field expectedField = (NumberFormat.Field) cas[0];
int expectedBeginIndex = (Integer) cas[1];
@ -2596,22 +2598,23 @@ public class NumberFormatterApiTest {
assertEquals(
"Next for grouping, field, case #" + i,
expectedField,
actual.getFieldAttribute());
actual.getField());
assertEquals(
"Next for grouping, begin index, case #" + i,
expectedBeginIndex,
actual.getBeginIndex());
actual.getStart());
assertEquals(
"Next for grouping, end index, case #" + i,
expectedEndIndex,
actual.getEndIndex());
actual.getLimit());
}
assertEquals("Should have seen all grouping separators", 4, i);
// Make sure strings without fraction do not contain fraction field
actual = new FieldPosition(NumberFormat.Field.FRACTION);
actual.reset();
actual.constrainField(NumberFormat.Field.FRACTION);
fmtd = NumberFormatter.withLocale(ULocale.ENGLISH).format(5);
assertFalse("No fraction part in an integer", fmtd.nextFieldPosition(actual));
assertFalse("No fraction part in an integer", fmtd.nextPosition(actual));
}
@Test