mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-19 23:07:33 +09:00
Issue #1971 - Part 2: Update ICU source to 63.2.
This commit is contained in:
parent
8df84683be
commit
1e69214382
3160 changed files with 275815 additions and 234203 deletions
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2016 and later: Unicode, Inc. and others.
|
||||
// © 2016 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html
|
||||
/*
|
||||
*******************************************************************************
|
||||
|
|
@ -27,12 +27,14 @@
|
|||
#include "unicode/udata.h"
|
||||
#include "unicode/udisplaycontext.h"
|
||||
#include "unicode/brkiter.h"
|
||||
#include "nfrs.h"
|
||||
#include "unicode/ucasemap.h"
|
||||
|
||||
#include "cmemory.h"
|
||||
#include "cstring.h"
|
||||
#include "patternprops.h"
|
||||
#include "uresimp.h"
|
||||
#include "nfrs.h"
|
||||
#include "number_decimalquantity.h"
|
||||
|
||||
// debugging
|
||||
// #define RBNF_DEBUG
|
||||
|
|
@ -66,6 +68,8 @@ static const UChar gSemiPercent[] =
|
|||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
using number::impl::DecimalQuantity;
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedNumberFormat)
|
||||
|
||||
/*
|
||||
|
|
@ -314,13 +318,33 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void inc(void) { ++p; ch = 0xffff; }
|
||||
UBool checkInc(UChar c) { if (p < e && (ch == c || *p == c)) { inc(); return TRUE; } return FALSE; }
|
||||
UBool check(UChar c) { return p < e && (ch == c || *p == c); }
|
||||
void skipWhitespace(void) { while (p < e && PatternProps::isWhiteSpace(ch != 0xffff ? ch : *p)) inc();}
|
||||
UBool inList(UChar c, const UChar* list) const {
|
||||
if (*list == SPACE && PatternProps::isWhiteSpace(c)) return TRUE;
|
||||
while (*list && *list != c) ++list; return *list == c;
|
||||
inline void inc(void) {
|
||||
++p;
|
||||
ch = 0xffff;
|
||||
}
|
||||
inline UBool checkInc(UChar c) {
|
||||
if (p < e && (ch == c || *p == c)) {
|
||||
inc();
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
inline UBool check(UChar c) {
|
||||
return p < e && (ch == c || *p == c);
|
||||
}
|
||||
inline void skipWhitespace(void) {
|
||||
while (p < e && PatternProps::isWhiteSpace(ch != 0xffff ? ch : *p)) {
|
||||
inc();
|
||||
}
|
||||
}
|
||||
inline UBool inList(UChar c, const UChar* list) const {
|
||||
if (*list == SPACE && PatternProps::isWhiteSpace(c)) {
|
||||
return TRUE;
|
||||
}
|
||||
while (*list && *list != c) {
|
||||
++list;
|
||||
}
|
||||
return *list == c;
|
||||
}
|
||||
void parseError(const char* msg);
|
||||
|
||||
|
|
@ -656,7 +680,7 @@ StringLocalizationInfo::getDisplayName(int32_t localeIndex, int32_t ruleIndex) c
|
|||
RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
||||
const UnicodeString& locs,
|
||||
const Locale& alocale, UParseError& perror, UErrorCode& status)
|
||||
: ruleSets(NULL)
|
||||
: fRuleSets(NULL)
|
||||
, ruleSetDescriptions(NULL)
|
||||
, numRuleSets(0)
|
||||
, defaultRuleSet(NULL)
|
||||
|
|
@ -665,6 +689,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
|||
, decimalFormatSymbols(NULL)
|
||||
, defaultInfinityRule(NULL)
|
||||
, defaultNaNRule(NULL)
|
||||
, fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
|
||||
, lenient(FALSE)
|
||||
, lenientParseRules(NULL)
|
||||
, localizations(NULL)
|
||||
|
|
@ -680,7 +705,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
|||
RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
||||
const UnicodeString& locs,
|
||||
UParseError& perror, UErrorCode& status)
|
||||
: ruleSets(NULL)
|
||||
: fRuleSets(NULL)
|
||||
, ruleSetDescriptions(NULL)
|
||||
, numRuleSets(0)
|
||||
, defaultRuleSet(NULL)
|
||||
|
|
@ -689,6 +714,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
|||
, decimalFormatSymbols(NULL)
|
||||
, defaultInfinityRule(NULL)
|
||||
, defaultNaNRule(NULL)
|
||||
, fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
|
||||
, lenient(FALSE)
|
||||
, lenientParseRules(NULL)
|
||||
, localizations(NULL)
|
||||
|
|
@ -704,7 +730,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
|||
RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
||||
LocalizationInfo* info,
|
||||
const Locale& alocale, UParseError& perror, UErrorCode& status)
|
||||
: ruleSets(NULL)
|
||||
: fRuleSets(NULL)
|
||||
, ruleSetDescriptions(NULL)
|
||||
, numRuleSets(0)
|
||||
, defaultRuleSet(NULL)
|
||||
|
|
@ -713,6 +739,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
|||
, decimalFormatSymbols(NULL)
|
||||
, defaultInfinityRule(NULL)
|
||||
, defaultNaNRule(NULL)
|
||||
, fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
|
||||
, lenient(FALSE)
|
||||
, lenientParseRules(NULL)
|
||||
, localizations(NULL)
|
||||
|
|
@ -727,7 +754,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
|||
RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
||||
UParseError& perror,
|
||||
UErrorCode& status)
|
||||
: ruleSets(NULL)
|
||||
: fRuleSets(NULL)
|
||||
, ruleSetDescriptions(NULL)
|
||||
, numRuleSets(0)
|
||||
, defaultRuleSet(NULL)
|
||||
|
|
@ -736,6 +763,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
|||
, decimalFormatSymbols(NULL)
|
||||
, defaultInfinityRule(NULL)
|
||||
, defaultNaNRule(NULL)
|
||||
, fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
|
||||
, lenient(FALSE)
|
||||
, lenientParseRules(NULL)
|
||||
, localizations(NULL)
|
||||
|
|
@ -751,7 +779,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
|||
const Locale& aLocale,
|
||||
UParseError& perror,
|
||||
UErrorCode& status)
|
||||
: ruleSets(NULL)
|
||||
: fRuleSets(NULL)
|
||||
, ruleSetDescriptions(NULL)
|
||||
, numRuleSets(0)
|
||||
, defaultRuleSet(NULL)
|
||||
|
|
@ -760,6 +788,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
|||
, decimalFormatSymbols(NULL)
|
||||
, defaultInfinityRule(NULL)
|
||||
, defaultNaNRule(NULL)
|
||||
, fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
|
||||
, lenient(FALSE)
|
||||
, lenientParseRules(NULL)
|
||||
, localizations(NULL)
|
||||
|
|
@ -772,7 +801,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
|||
}
|
||||
|
||||
RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale& alocale, UErrorCode& status)
|
||||
: ruleSets(NULL)
|
||||
: fRuleSets(NULL)
|
||||
, ruleSetDescriptions(NULL)
|
||||
, numRuleSets(0)
|
||||
, defaultRuleSet(NULL)
|
||||
|
|
@ -781,6 +810,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale&
|
|||
, decimalFormatSymbols(NULL)
|
||||
, defaultInfinityRule(NULL)
|
||||
, defaultNaNRule(NULL)
|
||||
, fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
|
||||
, lenient(FALSE)
|
||||
, lenientParseRules(NULL)
|
||||
, localizations(NULL)
|
||||
|
|
@ -838,7 +868,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale&
|
|||
|
||||
RuleBasedNumberFormat::RuleBasedNumberFormat(const RuleBasedNumberFormat& rhs)
|
||||
: NumberFormat(rhs)
|
||||
, ruleSets(NULL)
|
||||
, fRuleSets(NULL)
|
||||
, ruleSetDescriptions(NULL)
|
||||
, numRuleSets(0)
|
||||
, defaultRuleSet(NULL)
|
||||
|
|
@ -847,6 +877,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const RuleBasedNumberFormat& rhs)
|
|||
, decimalFormatSymbols(NULL)
|
||||
, defaultInfinityRule(NULL)
|
||||
, defaultNaNRule(NULL)
|
||||
, fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
|
||||
, lenient(FALSE)
|
||||
, lenientParseRules(NULL)
|
||||
, localizations(NULL)
|
||||
|
|
@ -876,6 +907,7 @@ RuleBasedNumberFormat::operator=(const RuleBasedNumberFormat& rhs)
|
|||
setDecimalFormatSymbols(*rhs.getDecimalFormatSymbols());
|
||||
init(rhs.originalDescription, rhs.localizations ? rhs.localizations->ref() : NULL, perror, status);
|
||||
setDefaultRuleSet(rhs.getDefaultRuleSetName(), status);
|
||||
setRoundingMode(rhs.getRoundingMode());
|
||||
|
||||
capitalizationInfoSet = rhs.capitalizationInfoSet;
|
||||
capitalizationForUIListMenu = rhs.capitalizationForUIListMenu;
|
||||
|
|
@ -918,8 +950,8 @@ RuleBasedNumberFormat::operator==(const Format& other) const
|
|||
? FALSE
|
||||
: *localizations == rhs.localizations))) {
|
||||
|
||||
NFRuleSet** p = ruleSets;
|
||||
NFRuleSet** q = rhs.ruleSets;
|
||||
NFRuleSet** p = fRuleSets;
|
||||
NFRuleSet** q = rhs.fRuleSets;
|
||||
if (p == NULL) {
|
||||
return q == NULL;
|
||||
} else if (q == NULL) {
|
||||
|
|
@ -940,8 +972,8 @@ UnicodeString
|
|||
RuleBasedNumberFormat::getRules() const
|
||||
{
|
||||
UnicodeString result;
|
||||
if (ruleSets != NULL) {
|
||||
for (NFRuleSet** p = ruleSets; *p; ++p) {
|
||||
if (fRuleSets != NULL) {
|
||||
for (NFRuleSet** p = fRuleSets; *p; ++p) {
|
||||
(*p)->appendRules(result);
|
||||
}
|
||||
}
|
||||
|
|
@ -955,9 +987,9 @@ RuleBasedNumberFormat::getRuleSetName(int32_t index) const
|
|||
UnicodeString string(TRUE, localizations->getRuleSetName(index), (int32_t)-1);
|
||||
return string;
|
||||
}
|
||||
else if (ruleSets) {
|
||||
else if (fRuleSets) {
|
||||
UnicodeString result;
|
||||
for (NFRuleSet** p = ruleSets; *p; ++p) {
|
||||
for (NFRuleSet** p = fRuleSets; *p; ++p) {
|
||||
NFRuleSet* rs = *p;
|
||||
if (rs->isPublic()) {
|
||||
if (--index == -1) {
|
||||
|
|
@ -978,8 +1010,8 @@ RuleBasedNumberFormat::getNumberOfRuleSetNames() const
|
|||
if (localizations) {
|
||||
result = localizations->getNumberOfRuleSets();
|
||||
}
|
||||
else if (ruleSets) {
|
||||
for (NFRuleSet** p = ruleSets; *p; ++p) {
|
||||
else if (fRuleSets) {
|
||||
for (NFRuleSet** p = fRuleSets; *p; ++p) {
|
||||
if ((**p).isPublic()) {
|
||||
++result;
|
||||
}
|
||||
|
|
@ -1066,8 +1098,8 @@ RuleBasedNumberFormat::getRuleSetDisplayName(const UnicodeString& ruleSetName, c
|
|||
NFRuleSet*
|
||||
RuleBasedNumberFormat::findRuleSet(const UnicodeString& name, UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status) && ruleSets) {
|
||||
for (NFRuleSet** p = ruleSets; *p; ++p) {
|
||||
if (U_SUCCESS(status) && fRuleSets) {
|
||||
for (NFRuleSet** p = fRuleSets; *p; ++p) {
|
||||
NFRuleSet* rs = *p;
|
||||
if (rs->isNamed(name)) {
|
||||
return rs;
|
||||
|
|
@ -1078,18 +1110,89 @@ RuleBasedNumberFormat::findRuleSet(const UnicodeString& name, UErrorCode& status
|
|||
return NULL;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::format(const DecimalQuantity &number,
|
||||
UnicodeString &appendTo,
|
||||
FieldPositionIterator *posIter,
|
||||
UErrorCode &status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return appendTo;
|
||||
}
|
||||
DecimalQuantity copy(number);
|
||||
if (copy.fitsInLong()) {
|
||||
format(number.toLong(), appendTo, posIter, status);
|
||||
}
|
||||
else {
|
||||
copy.roundToMagnitude(0, number::impl::RoundingMode::UNUM_ROUND_HALFEVEN, status);
|
||||
if (copy.fitsInLong()) {
|
||||
format(number.toDouble(), appendTo, posIter, status);
|
||||
}
|
||||
else {
|
||||
// We're outside of our normal range that this framework can handle.
|
||||
// The DecimalFormat will provide more accurate results.
|
||||
|
||||
// TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J.
|
||||
LocalPointer<NumberFormat> decimalFormat(NumberFormat::createInstance(locale, UNUM_DECIMAL, status), status);
|
||||
if (decimalFormat.isNull()) {
|
||||
return appendTo;
|
||||
}
|
||||
Formattable f;
|
||||
LocalPointer<DecimalQuantity> decimalQuantity(new DecimalQuantity(number), status);
|
||||
if (decimalQuantity.isNull()) {
|
||||
return appendTo;
|
||||
}
|
||||
f.adoptDecimalQuantity(decimalQuantity.orphan()); // f now owns decimalQuantity.
|
||||
decimalFormat->format(f, appendTo, posIter, status);
|
||||
}
|
||||
}
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::format(const DecimalQuantity &number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPosition& pos,
|
||||
UErrorCode &status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return appendTo;
|
||||
}
|
||||
DecimalQuantity copy(number);
|
||||
if (copy.fitsInLong()) {
|
||||
format(number.toLong(), appendTo, pos, status);
|
||||
}
|
||||
else {
|
||||
copy.roundToMagnitude(0, number::impl::RoundingMode::UNUM_ROUND_HALFEVEN, status);
|
||||
if (copy.fitsInLong()) {
|
||||
format(number.toDouble(), appendTo, pos, status);
|
||||
}
|
||||
else {
|
||||
// We're outside of our normal range that this framework can handle.
|
||||
// The DecimalFormat will provide more accurate results.
|
||||
|
||||
// TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J.
|
||||
LocalPointer<NumberFormat> decimalFormat(NumberFormat::createInstance(locale, UNUM_DECIMAL, status), status);
|
||||
if (decimalFormat.isNull()) {
|
||||
return appendTo;
|
||||
}
|
||||
Formattable f;
|
||||
LocalPointer<DecimalQuantity> decimalQuantity(new DecimalQuantity(number), status);
|
||||
if (decimalQuantity.isNull()) {
|
||||
return appendTo;
|
||||
}
|
||||
f.adoptDecimalQuantity(decimalQuantity.orphan()); // f now owns decimalQuantity.
|
||||
decimalFormat->format(f, appendTo, pos, status);
|
||||
}
|
||||
}
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::format(int32_t number,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& /* pos */) const
|
||||
FieldPosition& pos) const
|
||||
{
|
||||
if (defaultRuleSet) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t startPos = toAppendTo.length();
|
||||
defaultRuleSet->format((int64_t)number, toAppendTo, toAppendTo.length(), 0, status);
|
||||
adjustForCapitalizationContext(startPos, toAppendTo);
|
||||
}
|
||||
return toAppendTo;
|
||||
return format((int64_t)number, toAppendTo, pos);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1100,9 +1203,7 @@ RuleBasedNumberFormat::format(int64_t number,
|
|||
{
|
||||
if (defaultRuleSet) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t startPos = toAppendTo.length();
|
||||
defaultRuleSet->format(number, toAppendTo, toAppendTo.length(), 0, status);
|
||||
adjustForCapitalizationContext(startPos, toAppendTo);
|
||||
format(number, defaultRuleSet, toAppendTo, status);
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
|
@ -1112,83 +1213,137 @@ UnicodeString&
|
|||
RuleBasedNumberFormat::format(double number,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& /* pos */) const
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
if (defaultRuleSet) {
|
||||
format(number, *defaultRuleSet, toAppendTo, status);
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::format(int32_t number,
|
||||
const UnicodeString& ruleSetName,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& pos,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
return format((int64_t)number, ruleSetName, toAppendTo, pos, status);
|
||||
}
|
||||
|
||||
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::format(int64_t number,
|
||||
const UnicodeString& ruleSetName,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& /* pos */,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
|
||||
// throw new IllegalArgumentException("Can't use internal rule set");
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
} else {
|
||||
NFRuleSet *rs = findRuleSet(ruleSetName, status);
|
||||
if (rs) {
|
||||
format(number, rs, toAppendTo, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::format(double number,
|
||||
const UnicodeString& ruleSetName,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& /* pos */,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
|
||||
// throw new IllegalArgumentException("Can't use internal rule set");
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
} else {
|
||||
NFRuleSet *rs = findRuleSet(ruleSetName, status);
|
||||
if (rs) {
|
||||
format(number, *rs, toAppendTo, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
void
|
||||
RuleBasedNumberFormat::format(double number,
|
||||
NFRuleSet& rs,
|
||||
UnicodeString& toAppendTo,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
int32_t startPos = toAppendTo.length();
|
||||
if (defaultRuleSet) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
defaultRuleSet->format(number, toAppendTo, toAppendTo.length(), 0, status);
|
||||
if (getRoundingMode() != DecimalFormat::ERoundingMode::kRoundUnnecessary && !uprv_isNaN(number) && !uprv_isInfinite(number)) {
|
||||
DecimalQuantity digitList;
|
||||
digitList.setToDouble(number);
|
||||
digitList.roundToMagnitude(
|
||||
-getMaximumFractionDigits(),
|
||||
static_cast<UNumberFormatRoundingMode>(getRoundingMode()),
|
||||
status);
|
||||
number = digitList.toDouble();
|
||||
}
|
||||
return adjustForCapitalizationContext(startPos, toAppendTo);
|
||||
rs.format(number, toAppendTo, toAppendTo.length(), 0, status);
|
||||
adjustForCapitalizationContext(startPos, toAppendTo, status);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bottleneck through which all the public format() methods
|
||||
* that take a long pass. By the time we get here, we know
|
||||
* which rule set we're using to do the formatting.
|
||||
* @param number The number to format
|
||||
* @param ruleSet The rule set to use to format the number
|
||||
* @return The text that resulted from formatting the number
|
||||
*/
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::format(int32_t number,
|
||||
const UnicodeString& ruleSetName,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& /* pos */,
|
||||
UErrorCode& status) const
|
||||
RuleBasedNumberFormat::format(int64_t number, NFRuleSet *ruleSet, UnicodeString& toAppendTo, UErrorCode& status) const
|
||||
{
|
||||
// return format((int64_t)number, ruleSetName, toAppendTo, pos, status);
|
||||
// all API format() routines that take a double vector through
|
||||
// here. We have these two identical functions-- one taking a
|
||||
// double and one taking a long-- the couple digits of precision
|
||||
// that long has but double doesn't (both types are 8 bytes long,
|
||||
// but double has to borrow some of the mantissa bits to hold
|
||||
// the exponent).
|
||||
// Create an empty string buffer where the result will
|
||||
// be built, and pass it to the rule set (along with an insertion
|
||||
// position of 0 and the number being formatted) to the rule set
|
||||
// for formatting
|
||||
|
||||
if (U_SUCCESS(status)) {
|
||||
if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
|
||||
// throw new IllegalArgumentException("Can't use internal rule set");
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
} else {
|
||||
NFRuleSet *rs = findRuleSet(ruleSetName, status);
|
||||
if (rs) {
|
||||
int32_t startPos = toAppendTo.length();
|
||||
rs->format((int64_t)number, toAppendTo, toAppendTo.length(), 0, status);
|
||||
adjustForCapitalizationContext(startPos, toAppendTo);
|
||||
if (number == U_INT64_MIN) {
|
||||
// We can't handle this value right now. Provide an accurate default value.
|
||||
|
||||
// TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J.
|
||||
NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status);
|
||||
if (decimalFormat == nullptr) {
|
||||
return toAppendTo;
|
||||
}
|
||||
Formattable f;
|
||||
FieldPosition pos(FieldPosition::DONT_CARE);
|
||||
DecimalQuantity *decimalQuantity = new DecimalQuantity();
|
||||
if (decimalQuantity == nullptr) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
delete decimalFormat;
|
||||
return toAppendTo;
|
||||
}
|
||||
decimalQuantity->setToLong(number);
|
||||
f.adoptDecimalQuantity(decimalQuantity); // f now owns decimalQuantity.
|
||||
decimalFormat->format(f, toAppendTo, pos, status);
|
||||
delete decimalFormat;
|
||||
}
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::format(int64_t number,
|
||||
const UnicodeString& ruleSetName,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& /* pos */,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
|
||||
// throw new IllegalArgumentException("Can't use internal rule set");
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
} else {
|
||||
NFRuleSet *rs = findRuleSet(ruleSetName, status);
|
||||
if (rs) {
|
||||
int32_t startPos = toAppendTo.length();
|
||||
rs->format(number, toAppendTo, toAppendTo.length(), 0, status);
|
||||
adjustForCapitalizationContext(startPos, toAppendTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::format(double number,
|
||||
const UnicodeString& ruleSetName,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& /* pos */,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
|
||||
// throw new IllegalArgumentException("Can't use internal rule set");
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
} else {
|
||||
NFRuleSet *rs = findRuleSet(ruleSetName, status);
|
||||
if (rs) {
|
||||
int32_t startPos = toAppendTo.length();
|
||||
rs->format(number, toAppendTo, toAppendTo.length(), 0, status);
|
||||
adjustForCapitalizationContext(startPos, toAppendTo);
|
||||
}
|
||||
else {
|
||||
int32_t startPos = toAppendTo.length();
|
||||
ruleSet->format(number, toAppendTo, toAppendTo.length(), 0, status);
|
||||
adjustForCapitalizationContext(startPos, toAppendTo, status);
|
||||
}
|
||||
}
|
||||
return toAppendTo;
|
||||
|
|
@ -1196,18 +1351,18 @@ RuleBasedNumberFormat::format(double number,
|
|||
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::adjustForCapitalizationContext(int32_t startPos,
|
||||
UnicodeString& currentResult) const
|
||||
UnicodeString& currentResult,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
#if !UCONFIG_NO_BREAK_ITERATION
|
||||
if (startPos==0 && currentResult.length() > 0) {
|
||||
UDisplayContext capitalizationContext = getContext(UDISPCTX_TYPE_CAPITALIZATION, status);
|
||||
if (capitalizationContext != UDISPCTX_CAPITALIZATION_NONE && startPos == 0 && currentResult.length() > 0) {
|
||||
// capitalize currentResult according to context
|
||||
UChar32 ch = currentResult.char32At(0);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UDisplayContext capitalizationContext = getContext(UDISPCTX_TYPE_CAPITALIZATION, status);
|
||||
if ( u_islower(ch) && U_SUCCESS(status) && capitalizationBrkIter!= NULL &&
|
||||
( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
|
||||
(capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationForUIListMenu) ||
|
||||
(capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && capitalizationForStandAlone)) ) {
|
||||
if (u_islower(ch) && U_SUCCESS(status) && capitalizationBrkIter != NULL &&
|
||||
( capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
|
||||
(capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationForUIListMenu) ||
|
||||
(capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_STANDALONE && capitalizationForStandAlone)) ) {
|
||||
// titlecase first word of currentResult, here use sentence iterator unlike current implementations
|
||||
// in LocaleDisplayNamesImpl::adjustForUsageAndContext and RelativeDateFormat::format
|
||||
currentResult.toTitle(capitalizationBrkIter, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
|
||||
|
|
@ -1223,7 +1378,7 @@ RuleBasedNumberFormat::parse(const UnicodeString& text,
|
|||
Formattable& result,
|
||||
ParsePosition& parsePosition) const
|
||||
{
|
||||
if (!ruleSets) {
|
||||
if (!fRuleSets) {
|
||||
parsePosition.setErrorIndex(0);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1234,13 +1389,13 @@ RuleBasedNumberFormat::parse(const UnicodeString& text,
|
|||
ParsePosition high_pp(0);
|
||||
Formattable high_result;
|
||||
|
||||
for (NFRuleSet** p = ruleSets; *p; ++p) {
|
||||
for (NFRuleSet** p = fRuleSets; *p; ++p) {
|
||||
NFRuleSet *rp = *p;
|
||||
if (rp->isPublic() && rp->isParseable()) {
|
||||
ParsePosition working_pp(0);
|
||||
Formattable working_result;
|
||||
|
||||
rp->parse(workingText, working_pp, kMaxDouble, working_result);
|
||||
rp->parse(workingText, working_pp, kMaxDouble, 0, working_result);
|
||||
if (working_pp.getIndex() > high_pp.getIndex()) {
|
||||
high_pp = working_pp;
|
||||
high_result = working_result;
|
||||
|
|
@ -1322,7 +1477,7 @@ void
|
|||
RuleBasedNumberFormat::initDefaultRuleSet()
|
||||
{
|
||||
defaultRuleSet = NULL;
|
||||
if (!ruleSets) {
|
||||
if (!fRuleSets) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1330,7 +1485,7 @@ RuleBasedNumberFormat::initDefaultRuleSet()
|
|||
const UnicodeString ordinal(UNICODE_STRING_SIMPLE("%digits-ordinal"));
|
||||
const UnicodeString duration(UNICODE_STRING_SIMPLE("%duration"));
|
||||
|
||||
NFRuleSet**p = &ruleSets[0];
|
||||
NFRuleSet**p = &fRuleSets[0];
|
||||
while (*p) {
|
||||
if ((*p)->isNamed(spellout) || (*p)->isNamed(ordinal) || (*p)->isNamed(duration)) {
|
||||
defaultRuleSet = *p;
|
||||
|
|
@ -1342,7 +1497,7 @@ RuleBasedNumberFormat::initDefaultRuleSet()
|
|||
|
||||
defaultRuleSet = *--p;
|
||||
if (!defaultRuleSet->isPublic()) {
|
||||
while (p != ruleSets) {
|
||||
while (p != fRuleSets) {
|
||||
if ((*--p)->isPublic()) {
|
||||
defaultRuleSet = *p;
|
||||
break;
|
||||
|
|
@ -1412,7 +1567,7 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
|
|||
// from the description
|
||||
lenientParseRules = new UnicodeString();
|
||||
/* test for NULL */
|
||||
if (lenientParseRules == 0) {
|
||||
if (lenientParseRules == nullptr) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1433,15 +1588,15 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
|
|||
++numRuleSets;
|
||||
|
||||
// our rule list is an array of the appropriate size
|
||||
ruleSets = (NFRuleSet **)uprv_malloc((numRuleSets + 1) * sizeof(NFRuleSet *));
|
||||
fRuleSets = (NFRuleSet **)uprv_malloc((numRuleSets + 1) * sizeof(NFRuleSet *));
|
||||
/* test for NULL */
|
||||
if (ruleSets == 0) {
|
||||
if (fRuleSets == 0) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= numRuleSets; ++i) {
|
||||
ruleSets[i] = NULL;
|
||||
fRuleSets[i] = NULL;
|
||||
}
|
||||
|
||||
// divide up the descriptions into individual rule-set descriptions
|
||||
|
|
@ -1457,7 +1612,7 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
|
|||
}
|
||||
|
||||
ruleSetDescriptions = new UnicodeString[numRuleSets];
|
||||
if (ruleSetDescriptions == 0) {
|
||||
if (ruleSetDescriptions == nullptr) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1467,8 +1622,8 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
|
|||
int32_t start = 0;
|
||||
for (int32_t p = description.indexOf(gSemiPercent, 2, 0); p != -1; p = description.indexOf(gSemiPercent, 2, start)) {
|
||||
ruleSetDescriptions[curRuleSet].setTo(description, start, p + 1 - start);
|
||||
ruleSets[curRuleSet] = new NFRuleSet(this, ruleSetDescriptions, curRuleSet, status);
|
||||
if (ruleSets[curRuleSet] == 0) {
|
||||
fRuleSets[curRuleSet] = new NFRuleSet(this, ruleSetDescriptions, curRuleSet, status);
|
||||
if (fRuleSets[curRuleSet] == nullptr) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1476,8 +1631,8 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
|
|||
start = p + 1;
|
||||
}
|
||||
ruleSetDescriptions[curRuleSet].setTo(description, start, description.length() - start);
|
||||
ruleSets[curRuleSet] = new NFRuleSet(this, ruleSetDescriptions, curRuleSet, status);
|
||||
if (ruleSets[curRuleSet] == 0) {
|
||||
fRuleSets[curRuleSet] = new NFRuleSet(this, ruleSetDescriptions, curRuleSet, status);
|
||||
if (fRuleSets[curRuleSet] == nullptr) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1495,11 +1650,11 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
|
|||
initDefaultRuleSet();
|
||||
|
||||
// finally, we can go back through the temporary descriptions
|
||||
// list and finish seting up the substructure (and we throw
|
||||
// list and finish setting up the substructure (and we throw
|
||||
// away the temporary descriptions as we go)
|
||||
{
|
||||
for (int i = 0; i < numRuleSets; i++) {
|
||||
ruleSets[i]->parseRules(ruleSetDescriptions[i], status);
|
||||
fRuleSets[i]->parseRules(ruleSetDescriptions[i], status);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1545,7 +1700,7 @@ RuleBasedNumberFormat::setContext(UDisplayContext value, UErrorCode& status)
|
|||
if ( capitalizationBrkIter == NULL && (value==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
|
||||
(value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationForUIListMenu) ||
|
||||
(value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && capitalizationForStandAlone)) ) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
status = U_ZERO_ERROR;
|
||||
capitalizationBrkIter = BreakIterator::createSentenceInstance(locale, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete capitalizationBrkIter;
|
||||
|
|
@ -1569,8 +1724,8 @@ RuleBasedNumberFormat::initCapitalizationContextInfo(const Locale& thelocale)
|
|||
int32_t len = 0;
|
||||
const int32_t * intVector = ures_getIntVector(rb, &len, &status);
|
||||
if (U_SUCCESS(status) && intVector != NULL && len >= 2) {
|
||||
capitalizationForUIListMenu = intVector[0];
|
||||
capitalizationForStandAlone = intVector[1];
|
||||
capitalizationForUIListMenu = static_cast<UBool>(intVector[0]);
|
||||
capitalizationForStandAlone = static_cast<UBool>(intVector[1]);
|
||||
}
|
||||
}
|
||||
ures_close(rb);
|
||||
|
|
@ -1605,7 +1760,7 @@ RuleBasedNumberFormat::stripWhitespace(UnicodeString& description)
|
|||
start = p + 1;
|
||||
}
|
||||
|
||||
// when we get here, we've seeked off the end of the sring, and
|
||||
// when we get here, we've seeked off the end of the string, and
|
||||
// we terminate the loop (we continue until *start* is -1 rather
|
||||
// than until *p* is -1, because otherwise we'd miss the last
|
||||
// rule in the description)
|
||||
|
|
@ -1621,12 +1776,12 @@ RuleBasedNumberFormat::stripWhitespace(UnicodeString& description)
|
|||
void
|
||||
RuleBasedNumberFormat::dispose()
|
||||
{
|
||||
if (ruleSets) {
|
||||
for (NFRuleSet** p = ruleSets; *p; ++p) {
|
||||
if (fRuleSets) {
|
||||
for (NFRuleSet** p = fRuleSets; *p; ++p) {
|
||||
delete *p;
|
||||
}
|
||||
uprv_free(ruleSets);
|
||||
ruleSets = NULL;
|
||||
uprv_free(fRuleSets);
|
||||
fRuleSets = NULL;
|
||||
}
|
||||
|
||||
if (ruleSetDescriptions) {
|
||||
|
|
@ -1676,7 +1831,7 @@ const RuleBasedCollator*
|
|||
RuleBasedNumberFormat::getCollator() const
|
||||
{
|
||||
#if !UCONFIG_NO_COLLATION
|
||||
if (!ruleSets) {
|
||||
if (!fRuleSets) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1685,7 +1840,7 @@ RuleBasedNumberFormat::getCollator() const
|
|||
// create a default collator based on the formatter's locale,
|
||||
// then pull out that collator's rules, append any additional
|
||||
// rules specified in the description, and create a _new_
|
||||
// collator based on the combinaiton of those rules
|
||||
// collator based on the combination of those rules
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
|
|
@ -1728,13 +1883,10 @@ RuleBasedNumberFormat::initializeDecimalFormatSymbols(UErrorCode &status)
|
|||
// lazy-evaluate the DecimalFormatSymbols object. This object
|
||||
// is shared by all DecimalFormat instances belonging to this
|
||||
// formatter
|
||||
if (decimalFormatSymbols == NULL) {
|
||||
DecimalFormatSymbols* temp = new DecimalFormatSymbols(locale, status);
|
||||
if (decimalFormatSymbols == nullptr) {
|
||||
LocalPointer<DecimalFormatSymbols> temp(new DecimalFormatSymbols(locale, status), status);
|
||||
if (U_SUCCESS(status)) {
|
||||
decimalFormatSymbols = temp;
|
||||
}
|
||||
else {
|
||||
delete temp;
|
||||
decimalFormatSymbols = temp.orphan();
|
||||
}
|
||||
}
|
||||
return decimalFormatSymbols;
|
||||
|
|
@ -1754,17 +1906,14 @@ NFRule*
|
|||
RuleBasedNumberFormat::initializeDefaultInfinityRule(UErrorCode &status)
|
||||
{
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
if (defaultInfinityRule == NULL) {
|
||||
UnicodeString rule(UNICODE_STRING_SIMPLE("Inf: "));
|
||||
rule.append(getDecimalFormatSymbols()->getSymbol(DecimalFormatSymbols::kInfinitySymbol));
|
||||
NFRule* temp = new NFRule(this, rule, status);
|
||||
LocalPointer<NFRule> temp(new NFRule(this, rule, status), status);
|
||||
if (U_SUCCESS(status)) {
|
||||
defaultInfinityRule = temp;
|
||||
}
|
||||
else {
|
||||
delete temp;
|
||||
defaultInfinityRule = temp.orphan();
|
||||
}
|
||||
}
|
||||
return defaultInfinityRule;
|
||||
|
|
@ -1780,17 +1929,14 @@ NFRule*
|
|||
RuleBasedNumberFormat::initializeDefaultNaNRule(UErrorCode &status)
|
||||
{
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
if (defaultNaNRule == NULL) {
|
||||
if (defaultNaNRule == nullptr) {
|
||||
UnicodeString rule(UNICODE_STRING_SIMPLE("NaN: "));
|
||||
rule.append(getDecimalFormatSymbols()->getSymbol(DecimalFormatSymbols::kNaNSymbol));
|
||||
NFRule* temp = new NFRule(this, rule, status);
|
||||
LocalPointer<NFRule> temp(new NFRule(this, rule, status), status);
|
||||
if (U_SUCCESS(status)) {
|
||||
defaultNaNRule = temp;
|
||||
}
|
||||
else {
|
||||
delete temp;
|
||||
defaultNaNRule = temp.orphan();
|
||||
}
|
||||
}
|
||||
return defaultNaNRule;
|
||||
|
|
@ -1828,15 +1974,15 @@ RuleBasedNumberFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsTo
|
|||
defaultNaNRule = NULL;
|
||||
initializeDefaultNaNRule(status); // Reset with the new DecimalFormatSymbols
|
||||
|
||||
if (ruleSets) {
|
||||
if (fRuleSets) {
|
||||
for (int32_t i = 0; i < numRuleSets; i++) {
|
||||
ruleSets[i]->setDecimalFormatSymbols(*symbolsToAdopt, status);
|
||||
fRuleSets[i]->setDecimalFormatSymbols(*symbolsToAdopt, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Setting the symbols is equlivalent to adopting a newly created localized symbols.
|
||||
// Setting the symbols is equivalent to adopting a newly created localized symbols.
|
||||
void
|
||||
RuleBasedNumberFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
|
||||
{
|
||||
|
|
@ -1848,7 +1994,28 @@ RuleBasedNumberFormat::createPluralFormat(UPluralType pluralType,
|
|||
const UnicodeString &pattern,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
return new PluralFormat(locale, pluralType, pattern, status);
|
||||
auto *pf = new PluralFormat(locale, pluralType, pattern, status);
|
||||
if (pf == nullptr) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
return pf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rounding mode.
|
||||
* @return A rounding mode
|
||||
*/
|
||||
DecimalFormat::ERoundingMode RuleBasedNumberFormat::getRoundingMode() const {
|
||||
return fRoundingMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rounding mode. This has no effect unless the rounding
|
||||
* increment is greater than zero.
|
||||
* @param roundingMode A rounding mode
|
||||
*/
|
||||
void RuleBasedNumberFormat::setRoundingMode(DecimalFormat::ERoundingMode roundingMode) {
|
||||
fRoundingMode = roundingMode;
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue