+// Copyright (C) 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
* Copyright (C) 2016, International Business Machines
} // namespace
-struct DayPeriodRulesDataSink : public ResourceTableSink {
- // Initialize sub-sinks.
- DayPeriodRulesDataSink() :
- rulesSink(*this), ruleSetSink(*this), periodSink(*this), cutoffSink(*this) {
+struct DayPeriodRulesDataSink : public ResourceSink {
+ DayPeriodRulesDataSink() {
for (int32_t i = 0; i < UPRV_LENGTHOF(cutoffs); ++i) { cutoffs[i] = 0; }
}
virtual ~DayPeriodRulesDataSink();
- // Entry point.
- virtual ResourceTableSink *getOrCreateTableSink(const char *key, int32_t, UErrorCode &errorCode) {
- if (U_FAILURE(errorCode)) { return NULL; }
-
- if (uprv_strcmp(key, "locales") == 0) {
- return &localesSink;
- } else if (uprv_strcmp(key, "rules") == 0) {
- // Allocate one more than needed to skip [0]. See comment in parseSetNum().
- data->rules = new DayPeriodRules[data->maxRuleSetNum + 1];
- if (data->rules == NULL) {
- errorCode = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- } else {
- return &rulesSink;
+ virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) {
+ ResourceTable dayPeriodData = value.getTable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+
+ for (int32_t i = 0; dayPeriodData.getKeyAndValue(i, key, value); ++i) {
+ if (uprv_strcmp(key, "locales") == 0) {
+ ResourceTable locales = value.getTable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+
+ for (int32_t j = 0; locales.getKeyAndValue(j, key, value); ++j) {
+ UnicodeString setNum_str = value.getUnicodeString(errorCode);
+ int32_t setNum = parseSetNum(setNum_str, errorCode);
+ uhash_puti(data->localeToRuleSetNumMap, const_cast<char *>(key), setNum, &errorCode);
+ }
+ } else if (uprv_strcmp(key, "rules") == 0) {
+ // Allocate one more than needed to skip [0]. See comment in parseSetNum().
+ data->rules = new DayPeriodRules[data->maxRuleSetNum + 1];
+ if (data->rules == NULL) {
+ errorCode = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ ResourceTable rules = value.getTable(errorCode);
+ processRules(rules, key, value, errorCode);
+ if (U_FAILURE(errorCode)) { return; }
}
}
- return NULL;
}
- // Data root -> locales.
- struct LocalesSink : public ResourceTableSink {
- virtual ~LocalesSink();
+ void processRules(const ResourceTable &rules, const char *key,
+ ResourceValue &value, UErrorCode &errorCode) {
+ if (U_FAILURE(errorCode)) { return; }
- virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
+ for (int32_t i = 0; rules.getKeyAndValue(i, key, value); ++i) {
+ ruleSetNum = parseSetNum(key, errorCode);
+ ResourceTable ruleSet = value.getTable(errorCode);
if (U_FAILURE(errorCode)) { return; }
- UnicodeString setNum_str = value.getUnicodeString(errorCode);
- int32_t setNum = parseSetNum(setNum_str, errorCode);
- uhash_puti(data->localeToRuleSetNumMap, const_cast<char *>(key), setNum, &errorCode);
- }
- } localesSink;
-
- // Data root -> rules.
- struct RulesSink : public ResourceTableSink {
- DayPeriodRulesDataSink &outer;
- RulesSink(DayPeriodRulesDataSink &outer) : outer(outer) {}
- virtual ~RulesSink();
-
- virtual ResourceTableSink *getOrCreateTableSink(const char *key, int32_t, UErrorCode &errorCode) {
- if (U_FAILURE(errorCode)) { return NULL; }
-
- outer.ruleSetNum = parseSetNum(key, errorCode);
- return &outer.ruleSetSink;
- }
- } rulesSink;
-
- // Data root -> rules -> a rule set.
- struct RuleSetSink : public ResourceTableSink {
- DayPeriodRulesDataSink &outer;
- RuleSetSink(DayPeriodRulesDataSink &outer) : outer(outer) {}
- virtual ~RuleSetSink();
-
- virtual ResourceTableSink *getOrCreateTableSink(const char *key, int32_t, UErrorCode &errorCode) {
- if (U_FAILURE(errorCode)) { return NULL; }
-
- outer.period = DayPeriodRules::getDayPeriodFromString(key);
- if (outer.period == DayPeriodRules::DAYPERIOD_UNKNOWN) {
- errorCode = U_INVALID_FORMAT_ERROR;
- return NULL;
+ for (int32_t j = 0; ruleSet.getKeyAndValue(j, key, value); ++j) {
+ period = DayPeriodRules::getDayPeriodFromString(key);
+ if (period == DayPeriodRules::DAYPERIOD_UNKNOWN) {
+ errorCode = U_INVALID_FORMAT_ERROR;
+ return;
+ }
+ ResourceTable periodDefinition = value.getTable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+
+ for (int32_t k = 0; periodDefinition.getKeyAndValue(k, key, value); ++k) {
+ if (value.getType() == URES_STRING) {
+ // Key-value pairs (e.g. before{6:00}).
+ CutoffType type = getCutoffTypeFromString(key);
+ addCutoff(type, value.getUnicodeString(errorCode), errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ } else {
+ // Arrays (e.g. before{6:00, 24:00}).
+ cutoffType = getCutoffTypeFromString(key);
+ ResourceArray cutoffArray = value.getArray(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+
+ int32_t length = cutoffArray.getSize();
+ for (int32_t l = 0; l < length; ++l) {
+ cutoffArray.getValue(l, value);
+ addCutoff(cutoffType, value.getUnicodeString(errorCode), errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ }
+ }
+ }
+ setDayPeriodForHoursFromCutoffs(errorCode);
+ for (int32_t k = 0; k < UPRV_LENGTHOF(cutoffs); ++k) {
+ cutoffs[k] = 0;
+ }
}
- return &outer.periodSink;
- }
-
- virtual void leave(UErrorCode &errorCode) {
- if (U_FAILURE(errorCode)) { return; }
-
- if (!data->rules[outer.ruleSetNum].allHoursAreSet()) {
+ if (!data->rules[ruleSetNum].allHoursAreSet()) {
errorCode = U_INVALID_FORMAT_ERROR;
+ return;
}
}
- } ruleSetSink;
-
- // Data root -> rules -> a rule set -> a period (e.g. "morning1").
- // Key-value pairs (e.g. before{6:00}) will be captured here.
- // Arrays (e.g. before{6:00, 24:00}) will be redirected to the next sink.
- struct PeriodSink : public ResourceTableSink {
- DayPeriodRulesDataSink &outer;
- PeriodSink(DayPeriodRulesDataSink &outer) : outer(outer) {}
- virtual ~PeriodSink();
-
- virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
- if (U_FAILURE(errorCode)) { return; }
-
- CutoffType type = getCutoffTypeFromString(key);
- outer.addCutoff(type, value.getUnicodeString(errorCode), errorCode);
- }
-
- virtual ResourceArraySink *getOrCreateArraySink(const char *key, int32_t, UErrorCode &errorCode) {
- if (U_FAILURE(errorCode)) { return NULL; }
- outer.cutoffType = getCutoffTypeFromString(key);
- return &outer.cutoffSink;
- }
-
- virtual void leave(UErrorCode &errorCode) {
- if (U_FAILURE(errorCode)) { return; }
-
- outer.setDayPeriodForHoursFromCutoffs(errorCode);
- for (int32_t i = 0; i < UPRV_LENGTHOF(outer.cutoffs); ++i) {
- outer.cutoffs[i] = 0;
- }
- }
- } periodSink;
-
- // Data root -> rules -> a rule set -> a period -> a cutoff type.
- // Will enter this sink if 2+ times appear in a single cutoff type (e.g. before{6:00, 24:00}).
- struct CutoffSink : public ResourceArraySink {
- DayPeriodRulesDataSink &outer;
- CutoffSink(DayPeriodRulesDataSink &outer) : outer(outer) {}
- virtual ~CutoffSink();
-
- virtual void put(int32_t, const ResourceValue &value, UErrorCode &errorCode) {
- outer.addCutoff(outer.cutoffType, value.getUnicodeString(errorCode), errorCode);
- }
- } cutoffSink;
+ }
// Members.
int32_t cutoffs[25]; // [0] thru [24]: 24 is allowed in "before 24".
}
}; // struct DayPeriodRulesDataSink
-struct DayPeriodRulesCountSink : public ResourceTableSink {
+struct DayPeriodRulesCountSink : public ResourceSink {
virtual ~DayPeriodRulesCountSink();
- virtual ResourceTableSink *getOrCreateTableSink(const char *key, int32_t, UErrorCode &errorCode) {
- if (U_FAILURE(errorCode)) { return NULL; }
- int32_t setNum = DayPeriodRulesDataSink::parseSetNum(key, errorCode);
- if (setNum > data->maxRuleSetNum) {
- data->maxRuleSetNum = setNum;
- }
+ virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) {
+ ResourceTable rules = value.getTable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
- return NULL;
+ for (int32_t i = 0; rules.getKeyAndValue(i, key, value); ++i) {
+ int32_t setNum = DayPeriodRulesDataSink::parseSetNum(key, errorCode);
+ if (setNum > data->maxRuleSetNum) {
+ data->maxRuleSetNum = setNum;
+ }
+ }
}
};
// Out-of-line virtual destructors.
-DayPeriodRulesDataSink::LocalesSink::~LocalesSink() {}
-DayPeriodRulesDataSink::CutoffSink::~CutoffSink() {}
-DayPeriodRulesDataSink::PeriodSink::~PeriodSink() {}
-DayPeriodRulesDataSink::RuleSetSink::~RuleSetSink() {}
-DayPeriodRulesDataSink::RulesSink::~RulesSink() {}
DayPeriodRulesDataSink::~DayPeriodRulesDataSink() {}
-
DayPeriodRulesCountSink::~DayPeriodRulesCountSink() {}
namespace {
UInitOnce initOnce = U_INITONCE_INITIALIZER;
-UBool dayPeriodRulesCleanup() {
+U_CFUNC UBool U_CALLCONV dayPeriodRulesCleanup() {
delete[] data->rules;
uhash_close(data->localeToRuleSetNumMap);
delete data;
} // namespace
-void DayPeriodRules::load(UErrorCode &errorCode) {
+void U_CALLCONV DayPeriodRules::load(UErrorCode &errorCode) {
if (U_FAILURE(errorCode)) {
return;
}
// Get the largest rule set number (so we allocate enough objects).
DayPeriodRulesCountSink countSink;
- ures_getAllTableItemsWithFallback(rb_dayPeriods.getAlias(), "rules", countSink, errorCode);
+ ures_getAllItemsWithFallback(rb_dayPeriods.getAlias(), "rules", countSink, errorCode);
// Populate rules.
DayPeriodRulesDataSink sink;
- ures_getAllTableItemsWithFallback(rb_dayPeriods.getAlias(), "", sink, errorCode);
+ ures_getAllItemsWithFallback(rb_dayPeriods.getAlias(), "", sink, errorCode);
ucln_i18n_registerCleanup(UCLN_I18N_DAYPERIODRULES, dayPeriodRulesCleanup);
}