ICU-12029 Measure unit display names, C++ version.
X-SVN-Rev: 39243
This commit is contained in:
parent
f8620a567b
commit
5b9fc6fc70
@ -110,6 +110,7 @@ public:
|
||||
UMeasureFormatWidth widthFallback[WIDTH_INDEX_COUNT];
|
||||
/** Measure unit -> format width -> array of patterns ("{0} meters") (plurals + PER_UNIT_INDEX) */
|
||||
SimpleFormatter *patterns[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT][PATTERN_COUNT];
|
||||
const UChar* dnams[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT];
|
||||
SimpleFormatter perFormatters[WIDTH_INDEX_COUNT];
|
||||
|
||||
MeasureFormatCacheData();
|
||||
@ -159,6 +160,7 @@ MeasureFormatCacheData::MeasureFormatCacheData() {
|
||||
currencyFormats[i] = NULL;
|
||||
}
|
||||
uprv_memset(patterns, 0, sizeof(patterns));
|
||||
uprv_memset(dnams, 0, sizeof(dnams));
|
||||
integerFormat = NULL;
|
||||
numericDateFormatters = NULL;
|
||||
}
|
||||
@ -174,6 +176,7 @@ MeasureFormatCacheData::~MeasureFormatCacheData() {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Note: the contents of 'dnams' are pointers into the resource bundle
|
||||
delete integerFormat;
|
||||
delete numericDateFormatters;
|
||||
}
|
||||
@ -232,17 +235,25 @@ struct UnitDataSink : public ResourceSink {
|
||||
|
||||
void setFormatterIfAbsent(int32_t index, const ResourceValue &value,
|
||||
int32_t minPlaceholders, UErrorCode &errorCode) {
|
||||
SimpleFormatter **patterns =
|
||||
&cacheData.patterns[unitIndex][width][0];
|
||||
SimpleFormatter **patterns = &cacheData.patterns[unitIndex][width][0];
|
||||
if (U_SUCCESS(errorCode) && patterns[index] == NULL) {
|
||||
patterns[index] = new SimpleFormatter(
|
||||
value.getUnicodeString(errorCode), minPlaceholders, 1, errorCode);
|
||||
if (minPlaceholders >= 0) {
|
||||
patterns[index] = new SimpleFormatter(
|
||||
value.getUnicodeString(errorCode), minPlaceholders, 1, errorCode);
|
||||
}
|
||||
if (U_SUCCESS(errorCode) && patterns[index] == NULL) {
|
||||
errorCode = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setDnamIfAbsent(const ResourceValue &value, UErrorCode& errorCode) {
|
||||
if (cacheData.dnams[unitIndex][width] == NULL) {
|
||||
int32_t length;
|
||||
cacheData.dnams[unitIndex][width] = value.getString(length, errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume a display pattern. For example,
|
||||
* unitsShort/duration/hour contains other{"{0} hrs"}.
|
||||
@ -250,7 +261,8 @@ struct UnitDataSink : public ResourceSink {
|
||||
void consumePattern(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
if (uprv_strcmp(key, "dnam") == 0) {
|
||||
// Skip the unit display name for now.
|
||||
// The display name for the unit in the current width.
|
||||
setDnamIfAbsent(value, errorCode);
|
||||
} else if (uprv_strcmp(key, "per") == 0) {
|
||||
// For example, "{0}/h".
|
||||
setFormatterIfAbsent(MeasureFormatCacheData::PER_UNIT_INDEX, value, 1, errorCode);
|
||||
@ -817,6 +829,24 @@ UnicodeString &MeasureFormat::formatMeasures(
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
UnicodeString MeasureFormat::getUnitDisplayName(const MeasureUnit& unit, UErrorCode& /*status*/) const {
|
||||
UMeasureFormatWidth width = getRegularWidth(this->width);
|
||||
const UChar* const* styleToDnam = cache->dnams[unit.getIndex()];
|
||||
const UChar* dnam = styleToDnam[width];
|
||||
if (dnam == NULL) {
|
||||
int32_t fallbackWidth = cache->widthFallback[width];
|
||||
dnam = styleToDnam[fallbackWidth];
|
||||
}
|
||||
|
||||
UnicodeString result;
|
||||
if (dnam == NULL) {
|
||||
result.setToBogus();
|
||||
} else {
|
||||
result.setTo(dnam, -1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void MeasureFormat::initMeasureFormat(
|
||||
const Locale &locale,
|
||||
UMeasureFormatWidth w,
|
||||
|
@ -210,6 +210,19 @@ class U_I18N_API MeasureFormat : public Format {
|
||||
FieldPosition &pos,
|
||||
UErrorCode &status) const;
|
||||
|
||||
/**
|
||||
* Gets the display name of the specified {@link MeasureUnit} corresponding to the current
|
||||
* locale and format width.
|
||||
* @param unit The unit for which to get a display name.
|
||||
* @param status the error.
|
||||
* @return The display name in the locale and width specified in
|
||||
* {@link MeasureFormat#getInstance}, or null if there is no display name available
|
||||
* for the specified unit.
|
||||
*
|
||||
* @draft ICU 58
|
||||
*/
|
||||
UnicodeString getUnitDisplayName(const MeasureUnit& unit, UErrorCode &status) const;
|
||||
|
||||
|
||||
/**
|
||||
* Return a formatter for CurrencyAmount objects in the given
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "unicode/tmunit.h"
|
||||
#include "unicode/plurrule.h"
|
||||
#include "charstr.h"
|
||||
#include "cstr.h"
|
||||
#include "unicode/reldatefmt.h"
|
||||
|
||||
struct ExpectedResult {
|
||||
@ -58,6 +59,7 @@ private:
|
||||
void TestManyLocaleDurations();
|
||||
void TestGram();
|
||||
void TestCurrencies();
|
||||
void TestDisplayNames();
|
||||
void TestFieldPosition();
|
||||
void TestFieldPositionMultiple();
|
||||
void TestBadArg();
|
||||
@ -111,6 +113,11 @@ private:
|
||||
const Measure *measures,
|
||||
int32_t measureCount,
|
||||
const char *expected);
|
||||
void helperTestDisplayName(
|
||||
const MeasureUnit *unit,
|
||||
const char *localeID,
|
||||
UMeasureFormatWidth width,
|
||||
const char *expected);
|
||||
void verifyFieldPosition(
|
||||
const char *description,
|
||||
const MeasureFormat &fmt,
|
||||
@ -147,6 +154,7 @@ void MeasureFormatTest::runIndexedTest(
|
||||
TESTCASE_AUTO(TestManyLocaleDurations);
|
||||
TESTCASE_AUTO(TestGram);
|
||||
TESTCASE_AUTO(TestCurrencies);
|
||||
TESTCASE_AUTO(TestDisplayNames);
|
||||
TESTCASE_AUTO(TestFieldPosition);
|
||||
TESTCASE_AUTO(TestFieldPositionMultiple);
|
||||
TESTCASE_AUTO(TestBadArg);
|
||||
@ -1592,6 +1600,61 @@ void MeasureFormatTest::TestCurrencies() {
|
||||
verifyFormat("TestCurrenciesNumeric", fmt, &USD_2, 1, "$2.00");
|
||||
}
|
||||
|
||||
void MeasureFormatTest::TestDisplayNames() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
helperTestDisplayName( MeasureUnit::createYear(status), "en", UMEASFMT_WIDTH_WIDE, "years" );
|
||||
helperTestDisplayName( MeasureUnit::createYear(status), "ja", UMEASFMT_WIDTH_WIDE, "\\u5E74" );
|
||||
helperTestDisplayName( MeasureUnit::createYear(status), "es", UMEASFMT_WIDTH_WIDE, "a\\u00F1os" );
|
||||
helperTestDisplayName( MeasureUnit::createYear(status), "pt", UMEASFMT_WIDTH_WIDE, "anos" );
|
||||
helperTestDisplayName( MeasureUnit::createYear(status), "pt-PT", UMEASFMT_WIDTH_WIDE, "anos" );
|
||||
helperTestDisplayName( MeasureUnit::createAmpere(status), "en", UMEASFMT_WIDTH_WIDE, "amperes" );
|
||||
helperTestDisplayName( MeasureUnit::createAmpere(status), "ja", UMEASFMT_WIDTH_WIDE, "\\u30A2\\u30F3\\u30DA\\u30A2" );
|
||||
helperTestDisplayName( MeasureUnit::createAmpere(status), "es", UMEASFMT_WIDTH_WIDE, "amperios" );
|
||||
helperTestDisplayName( MeasureUnit::createAmpere(status), "pt", UMEASFMT_WIDTH_WIDE, "amperes" );
|
||||
helperTestDisplayName( MeasureUnit::createAmpere(status), "pt-PT", UMEASFMT_WIDTH_WIDE, "amperes" );
|
||||
helperTestDisplayName( MeasureUnit::createMeterPerSecondSquared(status), "pt", UMEASFMT_WIDTH_WIDE, "metros por segundo ao quadrado" );
|
||||
helperTestDisplayName( MeasureUnit::createMeterPerSecondSquared(status), "pt-PT", UMEASFMT_WIDTH_WIDE, "metros por segundo quadrado" );
|
||||
helperTestDisplayName( MeasureUnit::createSquareKilometer(status), "pt", UMEASFMT_WIDTH_NARROW, "km\\u00B2" );
|
||||
helperTestDisplayName( MeasureUnit::createSquareKilometer(status), "pt", UMEASFMT_WIDTH_SHORT, "km\\u00B2" );
|
||||
helperTestDisplayName( MeasureUnit::createSquareKilometer(status), "pt", UMEASFMT_WIDTH_WIDE, "quil\\u00F4metros quadrados" );
|
||||
helperTestDisplayName( MeasureUnit::createSecond(status), "pt-PT", UMEASFMT_WIDTH_NARROW, "s" );
|
||||
helperTestDisplayName( MeasureUnit::createSecond(status), "pt-PT", UMEASFMT_WIDTH_SHORT, "s" );
|
||||
helperTestDisplayName( MeasureUnit::createSecond(status), "pt-PT", UMEASFMT_WIDTH_WIDE, "segundos" );
|
||||
helperTestDisplayName( MeasureUnit::createSecond(status), "pt", UMEASFMT_WIDTH_NARROW, "seg" );
|
||||
helperTestDisplayName( MeasureUnit::createSecond(status), "pt", UMEASFMT_WIDTH_SHORT, "segs" );
|
||||
helperTestDisplayName( MeasureUnit::createSecond(status), "pt", UMEASFMT_WIDTH_WIDE, "segundos" );
|
||||
assertSuccess("Error creating measure units", status);
|
||||
}
|
||||
|
||||
void MeasureFormatTest::helperTestDisplayName(const MeasureUnit *unit,
|
||||
const char *localeID,
|
||||
UMeasureFormatWidth width,
|
||||
const char *expected) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
MeasureFormat fmt(Locale(localeID), width, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Could not create MeasureFormat for locale %s, width %d, status: %s",
|
||||
localeID, (int)width, u_errorName(status));
|
||||
return;
|
||||
}
|
||||
|
||||
UnicodeString dnam = fmt.getUnitDisplayName(*unit, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("MeasureFormat::getUnitDisplayName failed for unit %s-%s, locale %s, width %d, status: %s",
|
||||
unit->getType(), unit->getSubtype(), localeID, (int)width, u_errorName(status));
|
||||
return;
|
||||
}
|
||||
|
||||
UnicodeString expStr(UnicodeString(expected).unescape());
|
||||
if (dnam != expStr) {
|
||||
errln("MeasureFormat::getUnitDisplayName for unit %s-%s, locale %s, width %d: expected \"%s\", got \"%s\"",
|
||||
unit->getType(), unit->getSubtype(), localeID, (int)width, CStr(expStr)(), CStr(dnam)());
|
||||
}
|
||||
|
||||
// Delete the measure unit
|
||||
delete unit;
|
||||
}
|
||||
|
||||
void MeasureFormatTest::TestFieldPosition() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
MeasureFormat fmt("en", UMEASFMT_WIDTH_SHORT, status);
|
||||
|
Loading…
Reference in New Issue
Block a user