return scale;
}
+/**
+ * Helper method for the overrides of getSamples() for double and FixedDecimal
+ * return value types. Provide only one of an allocated array of doubles or
+ * FixedDecimals, and a nullptr for the other.
+ */
static int32_t
-getSamplesFromString(const UnicodeString &samples, double *dest,
- int32_t destCapacity, UErrorCode& status) {
+getSamplesFromString(const UnicodeString &samples, double *destDbl,
+ FixedDecimal* destFd, int32_t destCapacity,
+ UErrorCode& status) {
+
+ if ((destDbl == nullptr && destFd == nullptr)
+ || (destDbl != nullptr && destFd != nullptr)) {
+ status = U_INTERNAL_PROGRAM_ERROR;
+ return 0;
+ }
+
+ bool isDouble = destDbl != nullptr;
int32_t sampleCount = 0;
int32_t sampleStartIdx = 0;
int32_t sampleEndIdx = 0;
int32_t tildeIndex = sampleRange.indexOf(TILDE);
if (tildeIndex < 0) {
FixedDecimal fixed(sampleRange, status);
- double sampleValue = fixed.source;
- if (fixed.visibleDecimalDigitCount == 0 || sampleValue != floor(sampleValue)) {
- dest[sampleCount++] = sampleValue;
+ if (isDouble) {
+ double sampleValue = fixed.source;
+ if (fixed.visibleDecimalDigitCount == 0 || sampleValue != floor(sampleValue)) {
+ destDbl[sampleCount++] = sampleValue;
+ }
+ } else {
+ destFd[sampleCount++] = fixed;
}
} else {
rangeLo *= scale;
rangeHi *= scale;
for (double n=rangeLo; n<=rangeHi; n+=1) {
- // Hack Alert: don't return any decimal samples with integer values that
- // originated from a format with trailing decimals.
- // This API is returning doubles, which can't distinguish having displayed
- // zeros to the right of the decimal.
- // This results in test failures with values mapping back to a different keyword.
double sampleValue = n/scale;
- if (!(sampleValue == floor(sampleValue) && fixedLo.visibleDecimalDigitCount > 0)) {
- dest[sampleCount++] = sampleValue;
+ if (isDouble) {
+ // Hack Alert: don't return any decimal samples with integer values that
+ // originated from a format with trailing decimals.
+ // This API is returning doubles, which can't distinguish having displayed
+ // zeros to the right of the decimal.
+ // This results in test failures with values mapping back to a different keyword.
+ if (!(sampleValue == floor(sampleValue) && fixedLo.visibleDecimalDigitCount > 0)) {
+ destDbl[sampleCount++] = sampleValue;
+ }
+ } else {
+ int32_t v = (int32_t) fixedLo.getPluralOperand(PluralOperand::PLURAL_OPERAND_V);
+ int32_t e = (int32_t) fixedLo.getPluralOperand(PluralOperand::PLURAL_OPERAND_E);
+ FixedDecimal newSample = FixedDecimal::createWithExponent(sampleValue, v, e);
+ destFd[sampleCount++] = newSample;
}
if (sampleCount >= destCapacity) {
break;
return sampleCount;
}
-
int32_t
PluralRules::getSamples(const UnicodeString &keyword, double *dest,
int32_t destCapacity, UErrorCode& status) {
- if (destCapacity == 0 || U_FAILURE(status)) {
+ if (U_FAILURE(status)) {
return 0;
}
if (U_FAILURE(mInternalStatus)) {
status = mInternalStatus;
return 0;
}
+ if (dest != nullptr ? destCapacity < 0 : destCapacity != 0) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
RuleChain *rc = rulesForKeyword(keyword);
if (rc == nullptr) {
return 0;
}
- int32_t numSamples = getSamplesFromString(rc->fIntegerSamples, dest, destCapacity, status);
+ int32_t numSamples = getSamplesFromString(rc->fIntegerSamples, dest, nullptr, destCapacity, status);
if (numSamples == 0) {
- numSamples = getSamplesFromString(rc->fDecimalSamples, dest, destCapacity, status);
+ numSamples = getSamplesFromString(rc->fDecimalSamples, dest, nullptr, destCapacity, status);
+ }
+ return numSamples;
+}
+
+int32_t
+PluralRules::getSamples(const UnicodeString &keyword, FixedDecimal *dest,
+ int32_t destCapacity, UErrorCode& status) {
+ if (U_FAILURE(status)) {
+ return 0;
+ }
+ if (U_FAILURE(mInternalStatus)) {
+ status = mInternalStatus;
+ return 0;
+ }
+ if (dest != nullptr ? destCapacity < 0 : destCapacity != 0) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+ RuleChain *rc = rulesForKeyword(keyword);
+ if (rc == nullptr) {
+ return 0;
+ }
+ int32_t numSamples = getSamplesFromString(rc->fIntegerSamples, nullptr, dest, destCapacity, status);
+ if (numSamples == 0) {
+ numSamples = getSamplesFromString(rc->fDecimalSamples, nullptr, dest, destCapacity, status);
}
return numSamples;
}
}
}
-FixedDecimal::FixedDecimal(double n, int32_t v, int64_t f) {
- init(n, v, f);
+FixedDecimal::FixedDecimal(double n, int32_t v, int64_t f, int32_t e) {
+ init(n, v, f, e);
// check values. TODO make into unit test.
//
// long visiblePower = (int) Math.pow(10, v);
// }
}
+FixedDecimal::FixedDecimal(double n, int32_t v, int64_t f) {
+ init(n, v, f);
+}
+
FixedDecimal::FixedDecimal(double n, int32_t v) {
// Ugly, but for samples we don't care.
init(n, v, getFractionalDigits(n, v));
FixedDecimal::FixedDecimal(const UnicodeString &num, UErrorCode &status) {
CharString cs;
- cs.appendInvariantChars(num, status);
+ int32_t parsedExponent = 0;
+
+ int32_t exponentIdx = num.indexOf(u'e');
+ if (exponentIdx < 0) {
+ exponentIdx = num.indexOf(u'E');
+ }
+ if (exponentIdx >= 0) {
+ cs.appendInvariantChars(num.tempSubString(0, exponentIdx), status);
+ int32_t expSubstrStart = exponentIdx + 1;
+ parsedExponent = ICU_Utility::parseAsciiInteger(num, expSubstrStart);
+ }
+ else {
+ cs.appendInvariantChars(num, status);
+ }
+
DecimalQuantity dl;
dl.setToDecNumber(cs.toStringPiece(), status);
if (U_FAILURE(status)) {
init(0, 0, 0);
return;
}
+
int32_t decimalPoint = num.indexOf(DOT);
double n = dl.toDouble();
if (decimalPoint == -1) {
- init(n, 0, 0);
+ init(n, 0, 0, parsedExponent);
} else {
- int32_t v = num.length() - decimalPoint - 1;
- init(n, v, getFractionalDigits(n, v));
+ int32_t fractionNumLength = exponentIdx < 0 ? num.length() : cs.length();
+ int32_t v = fractionNumLength - decimalPoint - 1;
+ init(n, v, getFractionalDigits(n, v), parsedExponent);
}
}
decimalDigits = other.decimalDigits;
decimalDigitsWithoutTrailingZeros = other.decimalDigitsWithoutTrailingZeros;
intValue = other.intValue;
+ exponent = other.exponent;
_hasIntegerValue = other._hasIntegerValue;
isNegative = other.isNegative;
_isNaN = other._isNaN;
FixedDecimal::~FixedDecimal() = default;
+FixedDecimal FixedDecimal::createWithExponent(double n, int32_t v, int32_t e) {
+ return FixedDecimal(n, v, getFractionalDigits(n, v), e);
+}
+
void FixedDecimal::init(double n) {
int32_t numFractionDigits = decimals(n);
void FixedDecimal::init(double n, int32_t v, int64_t f) {
+ int32_t exponent = 0;
+ init(n, v, f, exponent);
+}
+
+
+void FixedDecimal::init(double n, int32_t v, int64_t f, int32_t e) {
isNegative = n < 0.0;
source = fabs(n);
_isNaN = uprv_isNaN(source);
_isInfinite = uprv_isInfinite(source);
+ exponent = e;
if (_isNaN || _isInfinite) {
v = 0;
f = 0;
case PLURAL_OPERAND_F: return static_cast<double>(decimalDigits);
case PLURAL_OPERAND_T: return static_cast<double>(decimalDigitsWithoutTrailingZeros);
case PLURAL_OPERAND_V: return visibleDecimalDigitCount;
- case PLURAL_OPERAND_E: return 0;
+ case PLURAL_OPERAND_E: return exponent;
default:
UPRV_UNREACHABLE; // unexpected.
}
return visibleDecimalDigitCount;
}
+bool FixedDecimal::operator==(const FixedDecimal &other) const {
+ return source == other.source && visibleDecimalDigitCount == other.visibleDecimalDigitCount
+ && decimalDigits == other.decimalDigits && exponent == other.exponent;
+}
+
+UnicodeString FixedDecimal::toString() const {
+ char pattern[15];
+ char buffer[20];
+ if (exponent == 0) {
+ snprintf(pattern, sizeof(pattern), "%%.%df", visibleDecimalDigitCount);
+ snprintf(buffer, sizeof(buffer), pattern, source);
+ } else {
+ snprintf(pattern, sizeof(pattern), "%%.%dfe%%d", visibleDecimalDigitCount);
+ snprintf(buffer, sizeof(buffer), pattern, source, exponent);
+ }
+ return UnicodeString(buffer, -1, US_INV);
+}
PluralAvailableLocalesEnumeration::PluralAvailableLocalesEnumeration(UErrorCode &status) {
#include "unicode/numberrangeformatter.h"
#include "cmemory.h"
+#include "cstr.h"
#include "plurrule_impl.h"
#include "plurults.h"
#include "uhash.h"
TESTCASE_AUTO(testAPI);
// TESTCASE_AUTO(testGetUniqueKeywordValue);
TESTCASE_AUTO(testGetSamples);
+ TESTCASE_AUTO(testGetFixedDecimalSamples);
+ TESTCASE_AUTO(testSamplesWithExponent);
TESTCASE_AUTO(testWithin);
TESTCASE_AUTO(testGetAllKeywordValues);
TESTCASE_AUTO(testCompactDecimalPluralKeyword);
void
PluralRulesTest::assertRuleValue(const UnicodeString& rule, double expected) {
- assertRuleKeyValue("a:" + rule, "a", expected);
+ assertRuleKeyValue("a:" + rule, "a", expected);
}
void
PluralRulesTest::assertRuleKeyValue(const UnicodeString& rule,
const UnicodeString& key, double expected) {
- UErrorCode status = U_ZERO_ERROR;
- PluralRules *pr = PluralRules::createRules(rule, status);
- double result = pr->getUniqueKeywordValue(key);
- delete pr;
- if (expected != result) {
- errln("expected %g but got %g", expected, result);
- }
+ UErrorCode status = U_ZERO_ERROR;
+ PluralRules *pr = PluralRules::createRules(rule, status);
+ double result = pr->getUniqueKeywordValue(key);
+ delete pr;
+ if (expected != result) {
+ errln("expected %g but got %g", expected, result);
+ }
}
// TODO: UniqueKeywordValue() is not currently supported.
// If it never will be, this test code should be removed.
void PluralRulesTest::testGetUniqueKeywordValue() {
- assertRuleValue("n is 1", 1);
- assertRuleValue("n in 2..2", 2);
- assertRuleValue("n within 2..2", 2);
- assertRuleValue("n in 3..4", UPLRULES_NO_UNIQUE_VALUE);
- assertRuleValue("n within 3..4", UPLRULES_NO_UNIQUE_VALUE);
- assertRuleValue("n is 2 or n is 2", 2);
- assertRuleValue("n is 2 and n is 2", 2);
- assertRuleValue("n is 2 or n is 3", UPLRULES_NO_UNIQUE_VALUE);
- assertRuleValue("n is 2 and n is 3", UPLRULES_NO_UNIQUE_VALUE);
- assertRuleValue("n is 2 or n in 2..3", UPLRULES_NO_UNIQUE_VALUE);
- assertRuleValue("n is 2 and n in 2..3", 2);
- assertRuleKeyValue("a: n is 1", "not_defined", UPLRULES_NO_UNIQUE_VALUE); // key not defined
- assertRuleKeyValue("a: n is 1", "other", UPLRULES_NO_UNIQUE_VALUE); // key matches default rule
+ assertRuleValue("n is 1", 1);
+ assertRuleValue("n in 2..2", 2);
+ assertRuleValue("n within 2..2", 2);
+ assertRuleValue("n in 3..4", UPLRULES_NO_UNIQUE_VALUE);
+ assertRuleValue("n within 3..4", UPLRULES_NO_UNIQUE_VALUE);
+ assertRuleValue("n is 2 or n is 2", 2);
+ assertRuleValue("n is 2 and n is 2", 2);
+ assertRuleValue("n is 2 or n is 3", UPLRULES_NO_UNIQUE_VALUE);
+ assertRuleValue("n is 2 and n is 3", UPLRULES_NO_UNIQUE_VALUE);
+ assertRuleValue("n is 2 or n in 2..3", UPLRULES_NO_UNIQUE_VALUE);
+ assertRuleValue("n is 2 and n in 2..3", 2);
+ assertRuleKeyValue("a: n is 1", "not_defined", UPLRULES_NO_UNIQUE_VALUE); // key not defined
+ assertRuleKeyValue("a: n is 1", "other", UPLRULES_NO_UNIQUE_VALUE); // key matches default rule
}
void PluralRulesTest::testGetSamples() {
- // TODO: fix samples, re-enable this test.
-
- // no get functional equivalent API in ICU4C, so just
- // test every locale...
- UErrorCode status = U_ZERO_ERROR;
- int32_t numLocales;
- const Locale* locales = Locale::getAvailableLocales(numLocales);
-
- double values[1000];
- for (int32_t i = 0; U_SUCCESS(status) && i < numLocales; ++i) {
- if (uprv_strcmp(locales[i].getLanguage(), "fr") == 0 &&
- logKnownIssue("21299", "PluralRules::getSamples cannot distinguish 1e5 from 100000")) {
- continue;
+ // TODO: fix samples, re-enable this test.
+
+ // no get functional equivalent API in ICU4C, so just
+ // test every locale...
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t numLocales;
+ const Locale* locales = Locale::getAvailableLocales(numLocales);
+
+ double values[1000];
+ for (int32_t i = 0; U_SUCCESS(status) && i < numLocales; ++i) {
+ if (uprv_strcmp(locales[i].getLanguage(), "fr") == 0 &&
+ logKnownIssue("21299", "PluralRules::getSamples cannot distinguish 1e5 from 100000")) {
+ continue;
+ }
+ LocalPointer<PluralRules> rules(PluralRules::forLocale(locales[i], status));
+ if (U_FAILURE(status)) {
+ break;
+ }
+ LocalPointer<StringEnumeration> keywords(rules->getKeywords(status));
+ if (U_FAILURE(status)) {
+ break;
+ }
+ const UnicodeString* keyword;
+ while (NULL != (keyword = keywords->snext(status))) {
+ int32_t count = rules->getSamples(*keyword, values, UPRV_LENGTHOF(values), status);
+ if (U_FAILURE(status)) {
+ errln(UnicodeString(u"getSamples() failed for locale ") +
+ locales[i].getName() +
+ UnicodeString(u", keyword ") + *keyword);
+ continue;
+ }
+ if (count == 0) {
+ // TODO: Lots of these.
+ // errln(UnicodeString(u"no samples for keyword ") + *keyword + UnicodeString(u" in locale ") + locales[i].getName() );
+ }
+ if (count > UPRV_LENGTHOF(values)) {
+ errln(UnicodeString(u"getSamples()=") + count +
+ UnicodeString(u", too many values, for locale ") +
+ locales[i].getName() +
+ UnicodeString(u", keyword ") + *keyword);
+ count = UPRV_LENGTHOF(values);
+ }
+ for (int32_t j = 0; j < count; ++j) {
+ if (values[j] == UPLRULES_NO_UNIQUE_VALUE) {
+ errln("got 'no unique value' among values");
+ } else {
+ UnicodeString resultKeyword = rules->select(values[j]);
+ // if (strcmp(locales[i].getName(), "uk") == 0) { // Debug only.
+ // std::cout << " uk " << US(resultKeyword).cstr() << " " << values[j] << std::endl;
+ // }
+ if (*keyword != resultKeyword) {
+ errln("file %s, line %d, Locale %s, sample for keyword \"%s\": %g, select(%g) returns keyword \"%s\"",
+ __FILE__, __LINE__, locales[i].getName(), US(*keyword).cstr(), values[j], values[j], US(resultKeyword).cstr());
+ }
+ }
+ }
+ }
}
- PluralRules *rules = PluralRules::forLocale(locales[i], status);
+}
+
+void PluralRulesTest::testGetFixedDecimalSamples() {
+ // TODO: fix samples, re-enable this test.
+
+ // no get functional equivalent API in ICU4C, so just
+ // test every locale...
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t numLocales;
+ const Locale* locales = Locale::getAvailableLocales(numLocales);
+
+ FixedDecimal values[1000];
+ for (int32_t i = 0; U_SUCCESS(status) && i < numLocales; ++i) {
+ if (uprv_strcmp(locales[i].getLanguage(), "fr") == 0 &&
+ logKnownIssue("21299", "PluralRules::getSamples cannot distinguish 1e5 from 100000")) {
+ continue;
+ }
+ LocalPointer<PluralRules> rules(PluralRules::forLocale(locales[i], status));
+ if (U_FAILURE(status)) {
+ break;
+ }
+ LocalPointer<StringEnumeration> keywords(rules->getKeywords(status));
+ if (U_FAILURE(status)) {
+ break;
+ }
+ const UnicodeString* keyword;
+ while (NULL != (keyword = keywords->snext(status))) {
+ int32_t count = rules->getSamples(*keyword, values, UPRV_LENGTHOF(values), status);
+ if (U_FAILURE(status)) {
+ errln(UnicodeString(u"getSamples() failed for locale ") +
+ locales[i].getName() +
+ UnicodeString(u", keyword ") + *keyword);
+ continue;
+ }
+ if (count == 0) {
+ // TODO: Lots of these.
+ // errln(UnicodeString(u"no samples for keyword ") + *keyword + UnicodeString(u" in locale ") + locales[i].getName() );
+ }
+ if (count > UPRV_LENGTHOF(values)) {
+ errln(UnicodeString(u"getSamples()=") + count +
+ UnicodeString(u", too many values, for locale ") +
+ locales[i].getName() +
+ UnicodeString(u", keyword ") + *keyword);
+ count = UPRV_LENGTHOF(values);
+ }
+ for (int32_t j = 0; j < count; ++j) {
+ if (values[j] == UPLRULES_NO_UNIQUE_VALUE_DECIMAL) {
+ errln("got 'no unique value' among values");
+ } else {
+ UnicodeString resultKeyword = rules->select(values[j]);
+ // if (strcmp(locales[i].getName(), "uk") == 0) { // Debug only.
+ // std::cout << " uk " << US(resultKeyword).cstr() << " " << values[j] << std::endl;
+ // }
+ if (*keyword != resultKeyword) {
+ errln("file %s, line %d, Locale %s, sample for keyword \"%s\": %s, select(%s) returns keyword \"%s\"",
+ __FILE__, __LINE__, locales[i].getName(), US(*keyword).cstr(), values[j].toString().getBuffer(), values[j].toString().getBuffer(), US(resultKeyword).cstr());
+ }
+ }
+ }
+ }
+ }
+}
+
+void PluralRulesTest::testSamplesWithExponent() {
+ // integer samples
+ UErrorCode status = U_ZERO_ERROR;
+ UnicodeString description(
+ u"one: i = 0,1 @integer 0, 1, 1e5 @decimal 0.0~1.5, 1.1e5; "
+ u"many: e = 0 and i != 0 and i % 1000000 = 0 and v = 0 or e != 0..5"
+ u" @integer 1000000, 2e6, 3e6, 4e6, 5e6, 6e6, 7e6, … @decimal 2.1e6, 3.1e6, 4.1e6, 5.1e6, 6.1e6, 7.1e6, …; "
+ u"other: @integer 2~17, 100, 1000, 10000, 100000, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, …"
+ u" @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 2.1e5, 3.1e5, 4.1e5, 5.1e5, 6.1e5, 7.1e5, …"
+ );
+ LocalPointer<PluralRules> test(PluralRules::createRules(description, status));
if (U_FAILURE(status)) {
- break;
+ errln("Couldn't create plural rules from a string using exponent notation, with error = %s", u_errorName(status));
+ return;
}
- StringEnumeration *keywords = rules->getKeywords(status);
+ checkNewSamples(description, test, u"one", u"@integer 0, 1, 1e5", FixedDecimal(0));
+ checkNewSamples(description, test, u"many", u"@integer 1000000, 2e6, 3e6, 4e6, 5e6, 6e6, 7e6, …", FixedDecimal(1000000));
+ checkNewSamples(description, test, u"other", u"@integer 2~17, 100, 1000, 10000, 100000, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, …", FixedDecimal(2));
+
+ // decimal samples
+ status = U_ZERO_ERROR;
+ UnicodeString description2(
+ u"one: i = 0,1 @decimal 0.0~1.5, 1.1e5; "
+ u"many: e = 0 and i != 0 and i % 1000000 = 0 and v = 0 or e != 0..5"
+ u" @decimal 2.1e6, 3.1e6, 4.1e6, 5.1e6, 6.1e6, 7.1e6, …; "
+ u"other: @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 2.1e5, 3.1e5, 4.1e5, 5.1e5, 6.1e5, 7.1e5, …"
+ );
+ LocalPointer<PluralRules> test2(PluralRules::createRules(description2, status));
if (U_FAILURE(status)) {
- delete rules;
- break;
+ errln("Couldn't create plural rules from a string using exponent notation, with error = %s", u_errorName(status));
+ return;
}
- const UnicodeString* keyword;
- while (NULL != (keyword = keywords->snext(status))) {
- int32_t count = rules->getSamples(*keyword, values, UPRV_LENGTHOF(values), status);
- if (U_FAILURE(status)) {
- errln(UNICODE_STRING_SIMPLE("getSamples() failed for locale ") +
- locales[i].getName() +
- UNICODE_STRING_SIMPLE(", keyword ") + *keyword);
- continue;
- }
- if (count == 0) {
- // TODO: Lots of these.
- // errln(UNICODE_STRING_SIMPLE("no samples for keyword ") + *keyword + UNICODE_STRING_SIMPLE(" in locale ") + locales[i].getName() );
- }
- if (count > UPRV_LENGTHOF(values)) {
- errln(UNICODE_STRING_SIMPLE("getSamples()=") + count +
- UNICODE_STRING_SIMPLE(", too many values, for locale ") +
- locales[i].getName() +
- UNICODE_STRING_SIMPLE(", keyword ") + *keyword);
- count = UPRV_LENGTHOF(values);
- }
- for (int32_t j = 0; j < count; ++j) {
- if (values[j] == UPLRULES_NO_UNIQUE_VALUE) {
- errln("got 'no unique value' among values");
- } else {
- UnicodeString resultKeyword = rules->select(values[j]);
- // if (strcmp(locales[i].getName(), "uk") == 0) { // Debug only.
- // std::cout << " uk " << US(resultKeyword).cstr() << " " << values[j] << std::endl;
- // }
- if (*keyword != resultKeyword) {
- errln("file %s, line %d, Locale %s, sample for keyword \"%s\": %g, select(%g) returns keyword \"%s\"",
- __FILE__, __LINE__, locales[i].getName(), US(*keyword).cstr(), values[j], values[j], US(resultKeyword).cstr());
- }
- }
- }
+ checkNewSamples(description2, test2, u"one", u"@decimal 0.0~1.5, 1.1e5", FixedDecimal(0, 1));
+ checkNewSamples(description2, test2, u"many", u"@decimal 2.1e6, 3.1e6, 4.1e6, 5.1e6, 6.1e6, 7.1e6, …", FixedDecimal::createWithExponent(2.1, 1, 6));
+ checkNewSamples(description2, test2, u"other", u"@decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 2.1e5, 3.1e5, 4.1e5, 5.1e5, 6.1e5, 7.1e5, …", FixedDecimal(2.0, 1));
+}
+
+void PluralRulesTest::checkNewSamples(
+ UnicodeString description,
+ const LocalPointer<PluralRules> &test,
+ UnicodeString keyword,
+ UnicodeString samplesString,
+ FixedDecimal firstInRange) {
+
+ UErrorCode status = U_ZERO_ERROR;
+ FixedDecimal samples[1000];
+
+ test->getSamples(keyword, samples, UPRV_LENGTHOF(samples), status);
+ if (U_FAILURE(status)) {
+ errln("Couldn't retrieve plural samples, with error = %s", u_errorName(status));
+ return;
+ }
+ FixedDecimal actualFirstSample = samples[0];
+
+ if (!(firstInRange == actualFirstSample)) {
+ CStr descCstr(description);
+ CStr samplesCstr(samplesString);
+ char errMsg[1000];
+ snprintf(errMsg, sizeof(errMsg), "First parsed sample FixedDecimal not equal to expected for samples: %s in rule string: %s\n", descCstr(), samplesCstr());
+ errln(errMsg);
}
- delete keywords;
- delete rules;
- }
}
void PluralRulesTest::testWithin() {
- // goes to show you what lack of testing will do.
- // of course, this has been broken for two years and no one has noticed...
- UErrorCode status = U_ZERO_ERROR;
- PluralRules *rules = PluralRules::createRules("a: n mod 10 in 5..8", status);
- if (!rules) {
- errln("couldn't instantiate rules");
- return;
- }
+ // goes to show you what lack of testing will do.
+ // of course, this has been broken for two years and no one has noticed...
+ UErrorCode status = U_ZERO_ERROR;
+ PluralRules *rules = PluralRules::createRules("a: n mod 10 in 5..8", status);
+ if (!rules) {
+ errln("couldn't instantiate rules");
+ return;
+ }
- UnicodeString keyword = rules->select((int32_t)26);
- if (keyword != "a") {
- errln("expected 'a' for 26 but didn't get it.");
- }
+ UnicodeString keyword = rules->select((int32_t)26);
+ if (keyword != "a") {
+ errln("expected 'a' for 26 but didn't get it.");
+ }
- keyword = rules->select(26.5);
- if (keyword != "other") {
- errln("expected 'other' for 26.5 but didn't get it.");
- }
+ keyword = rules->select(26.5);
+ if (keyword != "other") {
+ errln("expected 'other' for 26.5 but didn't get it.");
+ }
- delete rules;
+ delete rules;
}
void