mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-07 06:25:30 +00:00
ICU-12666 Update C++ RelativeDateTimeFormatter to new data loading scheme
X-SVN-Rev: 39102
This commit is contained in:
parent
7fbe4098b4
commit
2b166d876e
1 changed files with 152 additions and 198 deletions
|
@ -180,14 +180,11 @@ namespace {
|
|||
|
||||
/**
|
||||
* Sink for enumerating all of the measurement unit display names.
|
||||
* Contains inner sink classes, each one corresponding to a level of the resource table.
|
||||
*
|
||||
* More specific bundles (en_GB) are enumerated before their parents (en_001, en, root):
|
||||
* Only store a value if it is still missing, that is, it has not been overridden.
|
||||
*
|
||||
* C++: Each inner sink class has a reference to the main outer sink.
|
||||
*/
|
||||
struct RelDateTimeFmtDataSink : public ResourceTableSink {
|
||||
struct RelDateTimeFmtDataSink : public ResourceSink {
|
||||
|
||||
/**
|
||||
* Sink for patterns for relative dates and times. For example,
|
||||
|
@ -293,172 +290,16 @@ struct RelDateTimeFmtDataSink : public ResourceTableSink {
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Sinks for additional levels under /fields/*/relative/ and /fields/*/relativeTime/
|
||||
|
||||
/**
|
||||
* Make list of simplePatternFmtList, for past and for future.
|
||||
* Set a SimpleFormatter for the <style, relative unit, plurality>
|
||||
*
|
||||
* Fill in values for the particular plural given, e.g., ONE, FEW, OTHER, etc.
|
||||
*/
|
||||
struct RelDateTimeDetailSink : public ResourceTableSink {
|
||||
RelDateTimeDetailSink(RelDateTimeFmtDataSink &sink) : outer(sink) {}
|
||||
~RelDateTimeDetailSink();
|
||||
|
||||
virtual void put(const char *key, const ResourceValue &value,
|
||||
UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
outer.relUnitIndex = relUnitFromGeneric(outer.genericUnit);
|
||||
if (outer.relUnitIndex < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make two lists of simplePatternFmtList, one for past and one for future.
|
||||
* Set a SimpleFormatter pattern for the <style, relative unit, plurality>
|
||||
*
|
||||
* Fill in values for the particular plural given, e.g., ONE, FEW, OTHER, etc.
|
||||
*/
|
||||
int32_t pluralIndex = StandardPlural::indexOrNegativeFromString(key);
|
||||
if (pluralIndex >= 0) {
|
||||
SimpleFormatter **patterns =
|
||||
outer.outputData.relativeUnitsFormatters[outer.style][outer.relUnitIndex]
|
||||
[outer.pastFutureIndex];
|
||||
// Only set if not already established.
|
||||
if (patterns[pluralIndex] == NULL) {
|
||||
patterns[pluralIndex] = new SimpleFormatter(
|
||||
value.getUnicodeString(errorCode), 0, 1, errorCode);
|
||||
if (patterns[pluralIndex] == NULL) {
|
||||
errorCode = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RelDateTimeFmtDataSink &outer;
|
||||
} relDateTimeDetailSink;
|
||||
|
||||
/*
|
||||
* Handles "relativeTime" entries, e.g., under "day", "hour", "minute",
|
||||
* "minute-short", etc.
|
||||
*/
|
||||
struct RelativeTimeSink : public ResourceTableSink {
|
||||
RelativeTimeSink(RelDateTimeFmtDataSink &sink) : outer(sink) {}
|
||||
~RelativeTimeSink();
|
||||
|
||||
virtual ResourceTableSink *getOrCreateTableSink(const char *key, UErrorCode& errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return NULL; }
|
||||
outer.relUnitIndex = relUnitFromGeneric(outer.genericUnit);
|
||||
if (outer.relUnitIndex < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uprv_strcmp(key, "past") == 0) {
|
||||
outer.pastFutureIndex = 0;
|
||||
} else if (uprv_strcmp(key, "future") == 0) {
|
||||
outer.pastFutureIndex = 1;
|
||||
} else {
|
||||
// Unknown key.
|
||||
return NULL;
|
||||
}
|
||||
return &outer.relDateTimeDetailSink;
|
||||
}
|
||||
|
||||
RelDateTimeFmtDataSink &outer;
|
||||
} relativeTimeSink;
|
||||
|
||||
/*
|
||||
* Handles "relative" entries, e.g., under "day", "day-short", "fri",
|
||||
* "fri-narrow", "fri-short", etc.
|
||||
*/
|
||||
struct RelativeSink : public ResourceTableSink {
|
||||
RelativeSink(RelDateTimeFmtDataSink &sink) : outer(sink) {}
|
||||
~RelativeSink();
|
||||
|
||||
virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
int32_t direction = keyToDirection(key);
|
||||
if (direction < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t relUnitIndex = relUnitFromGeneric(outer.genericUnit);
|
||||
if (relUnitIndex == UDAT_RELATIVE_SECONDS &&
|
||||
direction == UDAT_DIRECTION_THIS &&
|
||||
outer.outputData.absoluteUnits[outer.style][UDAT_ABSOLUTE_NOW]
|
||||
[UDAT_DIRECTION_PLAIN].isEmpty()) {
|
||||
// Handle "NOW"
|
||||
outer.outputData.absoluteUnits[outer.style][UDAT_ABSOLUTE_NOW]
|
||||
[UDAT_DIRECTION_PLAIN].fastCopyFrom(value.getUnicodeString(errorCode));
|
||||
}
|
||||
|
||||
int32_t absUnitIndex = absUnitFromGeneric(outer.genericUnit);
|
||||
if (absUnitIndex < 0) {
|
||||
return;
|
||||
}
|
||||
// Only reset if slot is empty.
|
||||
if (outer.outputData.absoluteUnits[outer.style][absUnitIndex][direction].isEmpty()) {
|
||||
outer.outputData.absoluteUnits[outer.style][absUnitIndex]
|
||||
[direction].fastCopyFrom(value.getUnicodeString(errorCode));
|
||||
}
|
||||
}
|
||||
|
||||
RelDateTimeFmtDataSink &outer;
|
||||
} relativeSink;
|
||||
|
||||
/*
|
||||
* Handles entries under "fields", recognizing "relative" and "relativeTime" entries.
|
||||
*/
|
||||
struct UnitSink : public ResourceTableSink {
|
||||
UnitSink(RelDateTimeFmtDataSink &sink) : outer(sink) {}
|
||||
~UnitSink();
|
||||
|
||||
virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
if (uprv_strcmp(key, "dn") != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle Display Name for PLAIN direction for some units.
|
||||
int32_t absUnit = absUnitFromGeneric(outer.genericUnit);
|
||||
if (absUnit < 0) {
|
||||
return; // Not interesting.
|
||||
}
|
||||
|
||||
// Store displayname if not set.
|
||||
if (outer.outputData.absoluteUnits[outer.style]
|
||||
[absUnit][UDAT_DIRECTION_PLAIN].isEmpty()) {
|
||||
outer.outputData.absoluteUnits[outer.style]
|
||||
[absUnit][UDAT_DIRECTION_PLAIN].fastCopyFrom(value.getUnicodeString(errorCode));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ResourceTableSink *getOrCreateTableSink(const char *key, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return NULL; }
|
||||
if (uprv_strcmp(key, "relative") == 0) {
|
||||
return &outer.relativeSink;
|
||||
} else if (uprv_strcmp(key, "relativeTime") == 0) {
|
||||
return &outer.relativeTimeSink;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RelDateTimeFmtDataSink &outer;
|
||||
} unitSink;
|
||||
|
||||
// Values kept between levels of parsing the CLDR data.
|
||||
int32_t pastFutureIndex; // 0 == past or 1 == future
|
||||
UDateRelativeDateTimeFormatterStyle style; // {LONG, SHORT, NARROW}
|
||||
RelAbsUnit genericUnit;
|
||||
int32_t relUnitIndex;
|
||||
|
||||
RelativeDateTimeCacheData &outputData;
|
||||
|
||||
// Constructor
|
||||
RelDateTimeFmtDataSink(RelativeDateTimeCacheData& cacheData)
|
||||
: relDateTimeDetailSink(*this), relativeTimeSink(*this), relativeSink(*this),
|
||||
unitSink(*this), outputData(cacheData) {
|
||||
: outputData(cacheData) {
|
||||
// Clear cacheData.fallBackCache
|
||||
cacheData.fallBackCache[UDAT_STYLE_LONG] = -1;
|
||||
cacheData.fallBackCache[UDAT_STYLE_SHORT] = -1;
|
||||
|
@ -557,54 +398,165 @@ struct RelDateTimeFmtDataSink : public ResourceTableSink {
|
|||
return INVALID_UNIT;
|
||||
}
|
||||
|
||||
// Member functions of top level sink.
|
||||
virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
||||
// Only handle aliases, storing information about alias fallback.
|
||||
void handlePlainDirection(ResourceValue &value, UErrorCode &errorCode) {
|
||||
// Handle Display Name for PLAIN direction for some units.
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
if (U_SUCCESS(errorCode)) {
|
||||
if (value.getType() != URES_ALIAS) {
|
||||
return;
|
||||
}
|
||||
const UnicodeString valueStr = value.getAliasUnicodeString(errorCode);
|
||||
if (U_SUCCESS(errorCode)) {
|
||||
UDateRelativeDateTimeFormatterStyle sourceStyle= styleFromString(key);
|
||||
UDateRelativeDateTimeFormatterStyle targetStyle =
|
||||
styleFromAliasUnicodeString(valueStr);
|
||||
int32_t absUnit = absUnitFromGeneric(genericUnit);
|
||||
if (absUnit < 0) {
|
||||
return; // Not interesting.
|
||||
}
|
||||
|
||||
if (sourceStyle == targetStyle) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return;
|
||||
// Store displayname if not set.
|
||||
if (outputData.absoluteUnits[style]
|
||||
[absUnit][UDAT_DIRECTION_PLAIN].isEmpty()) {
|
||||
outputData.absoluteUnits[style]
|
||||
[absUnit][UDAT_DIRECTION_PLAIN].fastCopyFrom(value.getUnicodeString(errorCode));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void consumeTableRelative(const char *key, ResourceValue &value, UErrorCode &errorCode) {
|
||||
ResourceTable unitTypesTable = value.getTable(errorCode);
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
for (int32_t i = 0; unitTypesTable.getKeyAndValue(i, key, value); ++i) {
|
||||
if (value.getType() == URES_STRING) {
|
||||
int32_t direction = keyToDirection(key);
|
||||
if (direction < 0) {
|
||||
continue;
|
||||
}
|
||||
if (outputData.fallBackCache[sourceStyle] != -1 &&
|
||||
outputData.fallBackCache[sourceStyle] != targetStyle) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return;
|
||||
|
||||
int32_t relUnitIndex = relUnitFromGeneric(genericUnit);
|
||||
if (relUnitIndex == UDAT_RELATIVE_SECONDS && uprv_strcmp(key, "0") == 0 &&
|
||||
outputData.absoluteUnits[style][UDAT_ABSOLUTE_NOW][UDAT_DIRECTION_PLAIN].isEmpty()) {
|
||||
// Handle "NOW"
|
||||
outputData.absoluteUnits[style][UDAT_ABSOLUTE_NOW]
|
||||
[UDAT_DIRECTION_PLAIN].fastCopyFrom(value.getUnicodeString(errorCode));
|
||||
}
|
||||
|
||||
int32_t absUnitIndex = absUnitFromGeneric(genericUnit);
|
||||
if (absUnitIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
// Only reset if slot is empty.
|
||||
if (outputData.absoluteUnits[style][absUnitIndex][direction].isEmpty()) {
|
||||
outputData.absoluteUnits[style][absUnitIndex]
|
||||
[direction].fastCopyFrom(value.getUnicodeString(errorCode));
|
||||
}
|
||||
outputData.fallBackCache[sourceStyle] = targetStyle;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Top level sink
|
||||
virtual ResourceTableSink *getOrCreateTableSink(const char *key, UErrorCode& /* errorCode */) {
|
||||
style= styleFromString(key);
|
||||
int32_t unitSize = uprv_strlen(key) - styleSuffixLength(style);
|
||||
genericUnit = unitOrNegativeFromString(key, unitSize);
|
||||
if (style < 0 || genericUnit == INVALID_UNIT) {
|
||||
return NULL;
|
||||
}
|
||||
return &unitSink;
|
||||
void consumeTimeDetail(int32_t relUnitIndex,
|
||||
const char *key, ResourceValue &value, UErrorCode &errorCode) {
|
||||
ResourceTable unitTypesTable = value.getTable(errorCode);
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
for (int32_t i = 0; unitTypesTable.getKeyAndValue(i, key, value); ++i) {
|
||||
if (value.getType() == URES_STRING) {
|
||||
int32_t pluralIndex = StandardPlural::indexOrNegativeFromString(key);
|
||||
if (pluralIndex >= 0) {
|
||||
SimpleFormatter **patterns =
|
||||
outputData.relativeUnitsFormatters[style][relUnitIndex]
|
||||
[pastFutureIndex];
|
||||
// Only set if not already established.
|
||||
if (patterns[pluralIndex] == NULL) {
|
||||
patterns[pluralIndex] = new SimpleFormatter(
|
||||
value.getUnicodeString(errorCode), 0, 1, errorCode);
|
||||
if (patterns[pluralIndex] == NULL) {
|
||||
errorCode = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void consumeTableRelativeTime(const char *key, ResourceValue &value, UErrorCode &errorCode) {
|
||||
ResourceTable relativeTimeTable = value.getTable(errorCode);
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
int32_t relUnitIndex = relUnitFromGeneric(genericUnit);
|
||||
if (relUnitIndex < 0) {
|
||||
return;
|
||||
}
|
||||
for (int32_t i = 0; relativeTimeTable.getKeyAndValue(i, key, value); ++i) {
|
||||
if (uprv_strcmp(key, "past") == 0) {
|
||||
pastFutureIndex = 0;
|
||||
} else if (uprv_strcmp(key, "future") == 0) {
|
||||
pastFutureIndex = 1;
|
||||
} else {
|
||||
// Unknown key.
|
||||
continue;
|
||||
}
|
||||
consumeTimeDetail(relUnitIndex, key, value, errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
void consumeAlias(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
||||
|
||||
UDateRelativeDateTimeFormatterStyle sourceStyle = styleFromString(key);
|
||||
const UnicodeString valueStr = value.getAliasUnicodeString(errorCode);
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
UDateRelativeDateTimeFormatterStyle targetStyle =
|
||||
styleFromAliasUnicodeString(valueStr);
|
||||
|
||||
if (sourceStyle == targetStyle) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return;
|
||||
}
|
||||
if (outputData.fallBackCache[sourceStyle] != -1 &&
|
||||
outputData.fallBackCache[sourceStyle] != targetStyle) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return;
|
||||
}
|
||||
outputData.fallBackCache[sourceStyle] = targetStyle;
|
||||
}
|
||||
|
||||
void consumeTimeUnit(const char *key, ResourceValue &value, UErrorCode &errorCode) {
|
||||
ResourceTable unitTypesTable = value.getTable(errorCode);
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
for (int32_t i = 0; unitTypesTable.getKeyAndValue(i, key, value); ++i) {
|
||||
// Handle display name.
|
||||
if (uprv_strcmp(key, "dn") == 0 && value.getType() == URES_STRING) {
|
||||
handlePlainDirection(value, errorCode);
|
||||
}
|
||||
if (value.getType() == URES_TABLE) {
|
||||
if (uprv_strcmp(key, "relative") == 0) {
|
||||
consumeTableRelative(key, value, errorCode);
|
||||
} else if (uprv_strcmp(key, "relativeTime") == 0) {
|
||||
consumeTableRelativeTime(key, value, errorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void put(const char *key, ResourceValue &value,
|
||||
UBool /*noFallback*/, UErrorCode &errorCode) {
|
||||
// Main entry point to sink
|
||||
ResourceTable table = value.getTable(errorCode);
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
for (int32_t i = 0; table.getKeyAndValue(i, key, value); ++i) {
|
||||
if (value.getType() == URES_ALIAS) {
|
||||
consumeAlias(key, value, errorCode);
|
||||
} else {
|
||||
style = styleFromString(key);
|
||||
int32_t unitSize = uprv_strlen(key) - styleSuffixLength(style);
|
||||
genericUnit = unitOrNegativeFromString(key, unitSize);
|
||||
if (style >= 0 && genericUnit != INVALID_UNIT) {
|
||||
consumeTimeUnit(key, value, errorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Virtual destructors must be defined out of line.
|
||||
RelDateTimeFmtDataSink::RelDateTimeDetailSink::~RelDateTimeDetailSink() {}
|
||||
RelDateTimeFmtDataSink::RelativeTimeSink::~RelativeTimeSink() {}
|
||||
RelDateTimeFmtDataSink::RelativeSink::~RelativeSink() {}
|
||||
RelDateTimeFmtDataSink::UnitSink::~UnitSink() {}
|
||||
RelDateTimeFmtDataSink::~RelDateTimeFmtDataSink() {}
|
||||
|
||||
RelDateTimeFmtDataSink::~RelDateTimeFmtDataSink() {};
|
||||
} // namespace
|
||||
|
||||
DateFormatSymbols::DtWidthType styleToDateFormatSymbolWidth[UDAT_STYLE_COUNT] = {
|
||||
|
@ -637,8 +589,10 @@ static UBool loadUnitData(
|
|||
RelativeDateTimeCacheData &cacheData,
|
||||
const char* localeId,
|
||||
UErrorCode &status) {
|
||||
|
||||
RelDateTimeFmtDataSink sink(cacheData);
|
||||
ures_getAllTableItemsWithFallback(resource, "fields", sink, status);
|
||||
|
||||
ures_getAllItemsWithFallback(resource, "fields", sink, status);
|
||||
|
||||
// Get the weekday names from DateFormatSymbols.
|
||||
loadWeekdayNames(cacheData.absoluteUnits, localeId, status);
|
||||
|
|
Loading…
Add table
Reference in a new issue