// Iterate over all the calendar entries and only pick the 'intervalFormats' table.
ResourceTable dateIntervalData = value.getTable(errorCode); if (U_FAILURE(errorCode)) { return; } for (int32_t i = 0; dateIntervalData.getKeyAndValue(i, key, value); i++) { if (uprv_strcmp(key, gIntervalDateTimePatternTag) != 0) { continue;
}
// Handle aliases and tables. Ignore the rest. if (value.getType() == URES_ALIAS) { // Get the calendar type for the alias path. const UnicodeString &aliasPath = value.getAliasUnicodeString(errorCode); if (U_FAILURE(errorCode)) { return; }
if (U_FAILURE(errorCode)) {
resetNextCalendarType();
} break;
} elseif (value.getType() == URES_TABLE) { // Iterate over all the skeletons in the 'intervalFormat' table.
ResourceTable skeletonData = value.getTable(errorCode); if (U_FAILURE(errorCode)) { return; } for (int32_t j = 0; skeletonData.getKeyAndValue(j, key, value); j++) { if (value.getType() == URES_TABLE) { // Process the skeleton
processSkeletonTable(key, value, errorCode); if (U_FAILURE(errorCode)) { return; }
}
} break;
}
}
}
/** * Processes the patterns for a skeleton table
*/ void processSkeletonTable(constchar *key, ResourceValue &value, UErrorCode &errorCode) { if (U_FAILURE(errorCode)) { return; }
// Iterate over all the patterns in the current skeleton table constchar *currentSkeleton = key;
ResourceTable patternData = value.getTable(errorCode); if (U_FAILURE(errorCode)) { return; } for (int32_t k = 0; patternData.getKeyAndValue(k, key, value); k++) { if (value.getType() == URES_STRING) { // Process the key
UCalendarDateFields calendarField = validateAndProcessPatternLetter(key);
// If the calendar field has a valid value if (calendarField < UCAL_FIELD_COUNT) { // Set the interval pattern
setIntervalPatternIfAbsent(currentSkeleton, calendarField, value, errorCode); if (U_FAILURE(errorCode)) { return; }
}
}
}
}
/** * Extracts the calendar type from the path.
*/ staticvoid getCalendarTypeFromPath(const UnicodeString &path, UnicodeString &calendarType,
UErrorCode &errorCode) { if (U_FAILURE(errorCode)) { return; }
/** * Validates and processes the pattern letter
*/
UCalendarDateFields validateAndProcessPatternLetter(constchar *patternLetter) { // Check that patternLetter is just one letter char c0; if ((c0 = patternLetter[0]) != 0 && patternLetter[1] == 0) { // Check that the pattern letter is accepted if (c0 == 'G') { return UCAL_ERA;
} elseif (c0 == 'y') { return UCAL_YEAR;
} elseif (c0 == 'M') { return UCAL_MONTH;
} elseif (c0 == 'd') { return UCAL_DATE;
} elseif (c0 == 'a') { return UCAL_AM_PM;
} elseif (c0 == 'B') { // TODO: Using AM/PM as a proxy for flexible day period isn't really correct, but it's close return UCAL_AM_PM;
} elseif (c0 == 'h' || c0 == 'H') { return UCAL_HOUR;
} elseif (c0 == 'm') { return UCAL_MINUTE;
}// TODO(ticket:12190): Why icu4c doesn't accept the calendar field "s" but icu4j does?
} return UCAL_FIELD_COUNT;
}
/** * Stores the interval pattern for the current skeleton in the internal data structure * if it's not present.
*/ void setIntervalPatternIfAbsent(constchar *currentSkeleton, UCalendarDateFields lrgDiffCalUnit, const ResourceValue &value, UErrorCode &errorCode) { // Check if the pattern has already been stored on the data structure
IntervalPatternIndex index =
dateIntervalInfo.calendarFieldToIntervalIndex(lrgDiffCalUnit, errorCode); if (U_FAILURE(errorCode)) { return; }
// Get the correct calendar type constchar * calendarTypeToUse = gGregorianTag; // initial default char localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY]; // obtain a locale that always has the calendar key value that should be used
(void)ures_getFunctionalEquivalent(localeWithCalendarKey, ULOC_LOCALE_IDENTIFIER_CAPACITY, nullptr, "calendar", "calendar", locName, nullptr, false, &status);
localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination // now get the calendar key value from that locale
CharString calendarType = ulocimp_getKeywordValue(localeWithCalendarKey, "calendar", status); if (U_SUCCESS(status)) {
calendarTypeToUse = calendarType.data();
}
status = U_ZERO_ERROR;
if (U_SUCCESS(status)) {
UResourceBundle *calTypeBundle, *itvDtPtnResource;
// Get the fallback pattern const char16_t* resStr = nullptr;
int32_t resStrLen = 0;
calTypeBundle = ures_getByKeyWithFallback(calBundle, calendarTypeToUse, nullptr, &status);
itvDtPtnResource = ures_getByKeyWithFallback(calTypeBundle,
gIntervalDateTimePatternTag, nullptr, &status); // TODO(ICU-20400): After the fixing, we should find the "fallback" from // the rb directly by the path "calendar/${calendar}/intervalFormats/fallback". if ( U_SUCCESS(status) ) {
resStr = ures_getStringByKeyWithFallback(itvDtPtnResource, gFallbackPatternTag,
&resStrLen, &status);
}
if (U_SUCCESS(status)) { while (!calendarTypeToUseUString.isBogus()) { // Set an error when a loop is detected if (loadedCalendarTypes.geti(calendarTypeToUseUString) == 1) {
status = U_INVALID_FORMAT_ERROR; break;
}
// Register the calendar type to avoid loops
loadedCalendarTypes.puti(calendarTypeToUseUString, 1, status); if (U_FAILURE(status)) { break; }
// Get the calendar string
CharString calTypeBuffer;
calTypeBuffer.appendInvariantChars(calendarTypeToUseUString, status); if (U_FAILURE(status)) { break; } constchar *calType = calTypeBuffer.data();
// Reset the next calendar type to load.
sink.resetNextCalendarType();
// Get all resources for this calendar type
ures_getAllItemsWithFallback(calBundle, calType, sink, status);
}
}
}
// Close the opened resource bundles
ures_close(calBundle);
ures_close(rb);
}
void
DateIntervalInfo::setIntervalPatternInternally(const UnicodeString& skeleton,
UCalendarDateFields lrgDiffCalUnit, const UnicodeString& intervalPattern,
UErrorCode& status) {
IntervalPatternIndex index = calendarFieldToIntervalIndex(lrgDiffCalUnit,status); if ( U_FAILURE(status) ) { return;
}
UnicodeString* patternsOfOneSkeleton = static_cast<UnicodeString*>(fIntervalPatterns->get(skeleton));
UBool emptyHash = false; if ( patternsOfOneSkeleton == nullptr ) {
patternsOfOneSkeleton = new UnicodeString[kIPI_MAX_INDEX]; if (patternsOfOneSkeleton == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return;
}
emptyHash = true;
}
int32_t inputSkeletonFieldWidth[] =
{ // A B C D E F G H I J K L M N O
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // P Q R S T U V W X Y Z
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // a b c d e f g h i j k l m n o
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // p q r s t u v w x y z
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
int32_t skeletonFieldWidth[] =
{ // A B C D E F G H I J K L M N O
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // P Q R S T U V W X Y Z
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // a b c d e f g h i j k l m n o
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // p q r s t u v w x y z
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
// 0 means exact the same skeletons; // 1 means having the same field, but with different length, // 2 means only z/v, h/K, or H/k differs // -1 means having different field.
bestMatchDistanceInfo = 0;
int8_t fieldLength = UPRV_LENGTHOF(skeletonFieldWidth);
DateIntervalInfo::IntervalPatternIndex
DateIntervalInfo::calendarFieldToIntervalIndex(UCalendarDateFields field,
UErrorCode& status) { if ( U_FAILURE(status) ) { return kIPI_MAX_INDEX;
}
IntervalPatternIndex index = kIPI_MAX_INDEX; switch ( field ) { case UCAL_ERA:
index = kIPI_ERA; break; case UCAL_YEAR:
index = kIPI_YEAR; break; case UCAL_MONTH:
index = kIPI_MONTH; break; case UCAL_DATE: case UCAL_DAY_OF_WEEK: //case UCAL_DAY_OF_MONTH:
index = kIPI_DATE; break; case UCAL_AM_PM:
index = kIPI_AM_PM; break; case UCAL_HOUR: case UCAL_HOUR_OF_DAY:
index = kIPI_HOUR; break; case UCAL_MINUTE:
index = kIPI_MINUTE; break; case UCAL_SECOND:
index = kIPI_SECOND; break; case UCAL_MILLISECOND:
index = kIPI_MILLISECOND; break; default:
status = U_ILLEGAL_ARGUMENT_ERROR;
} return index;
}
/** * set hash table value comparator * * @param val1 one value in comparison * @param val2 the other value in comparison * @return true if 2 values are the same, false otherwise
*/ static UBool U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2);
static UBool
U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2) { const UnicodeString* pattern1 = (UnicodeString*)val1.pointer; const UnicodeString* pattern2 = (UnicodeString*)val2.pointer;
UBool ret = true;
int8_t i; for ( i = 0; i < DateIntervalInfo::kMaxIntervalPatternIndex && ret ; ++i ) {
ret = (pattern1[i] == pattern2[i]);
} return ret;
}
U_CDECL_END
Hashtable*
DateIntervalInfo::initHash(UErrorCode& status) { if ( U_FAILURE(status) ) { return nullptr;
}
Hashtable* hTable; if ( (hTable = new Hashtable(false, status)) == nullptr ) {
status = U_MEMORY_ALLOCATION_ERROR; return nullptr;
} if ( U_FAILURE(status) ) { delete hTable; return nullptr;
}
hTable->setValueComparator(dtitvinfHashTableValueComparator); return hTable;
}
void
DateIntervalInfo::copyHash(const Hashtable* source,
Hashtable* target,
UErrorCode& status) { if ( U_FAILURE(status) ) { return;
}
int32_t pos = UHASH_FIRST; const UHashElement* element = nullptr; if ( source ) { while ( (element = source->nextElement(pos)) != nullptr ) { const UHashTok keyTok = element->key; const UnicodeString* key = static_cast<UnicodeString*>(keyTok.pointer); const UHashTok valueTok = element->value; const UnicodeString* value = static_cast<UnicodeString*>(valueTok.pointer);
UnicodeString* copy = new UnicodeString[kIPI_MAX_INDEX]; if (copy == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return;
}
int8_t i; for ( i = 0; i < kIPI_MAX_INDEX; ++i ) {
copy[i] = value[i];
}
target->put(UnicodeString(*key), copy, status); if ( U_FAILURE(status) ) { return;
}
}
}
}
U_NAMESPACE_END
#endif
Messung V0.5
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.