+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*******************************************************************************
-* Copyright (C) 2008-2011, International Business Machines Corporation and
+* Copyright (C) 2008-2016, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
-* File DTITVINF.CPP
+* File DTITVINF.CPP
*
*******************************************************************************
*/
//#define DTITVINF_DEBUG 1
-#ifdef DTITVINF_DEBUG
+#ifdef DTITVINF_DEBUG
#include <iostream>
#endif
+#include "cmemory.h"
#include "cstring.h"
#include "unicode/msgfmt.h"
#include "unicode/uloc.h"
#include "unicode/ures.h"
#include "dtitv_impl.h"
+#include "charstr.h"
#include "hash.h"
#include "gregoimp.h"
#include "uresimp.h"
U_NAMESPACE_BEGIN
-#ifdef DTITVINF_DEBUG
+#ifdef DTITVINF_DEBUG
#define PRINTMESG(msg) { std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; }
#endif
// default fall-back
static const UChar gDefaultFallbackPattern[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, EN_DASH, SPACE, LEFT_CURLY_BRACKET, DIGIT_ONE, RIGHT_CURLY_BRACKET, 0};
-
-
-DateIntervalInfo::DateIntervalInfo(UErrorCode& status)
+DateIntervalInfo::DateIntervalInfo(UErrorCode& status)
: fFallbackIntervalPattern(gDefaultFallbackPattern),
fFirstDateInPtnIsLaterDate(false),
fIntervalPatterns(NULL)
UCalendarDateFields lrgDiffCalUnit,
const UnicodeString& intervalPattern,
UErrorCode& status) {
-
+
if ( lrgDiffCalUnit == UCAL_HOUR_OF_DAY ) {
setIntervalPatternInternally(skeleton, UCAL_AM_PM, intervalPattern, status);
setIntervalPatternInternally(skeleton, UCAL_HOUR, intervalPattern, status);
if ( U_FAILURE(status) ) {
return;
}
- int32_t firstPatternIndex = fallbackPattern.indexOf(gFirstPattern,
- sizeof(gFirstPattern)/sizeof(gFirstPattern[0]), 0);
- int32_t secondPatternIndex = fallbackPattern.indexOf(gSecondPattern,
- sizeof(gSecondPattern)/sizeof(gSecondPattern[0]), 0);
+ int32_t firstPatternIndex = fallbackPattern.indexOf(gFirstPattern,
+ UPRV_LENGTHOF(gFirstPattern), 0);
+ int32_t secondPatternIndex = fallbackPattern.indexOf(gSecondPattern,
+ UPRV_LENGTHOF(gSecondPattern), 0);
if ( firstPatternIndex == -1 || secondPatternIndex == -1 ) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
- if ( firstPatternIndex > secondPatternIndex ) {
+ if ( firstPatternIndex > secondPatternIndex ) {
fFirstDateInPtnIsLaterDate = true;
}
fFallbackIntervalPattern = fallbackPattern;
{
*this = dtitvinf;
}
-
+
DateIntervalInfo&
if ( this == &dtitvinf ) {
return *this;
}
-
+
UErrorCode status = U_ZERO_ERROR;
deleteHash(fIntervalPatterns);
fIntervalPatterns = initHash(status);
copyHash(dtitvinf.fIntervalPatterns, fIntervalPatterns, status);
if ( U_FAILURE(status) ) {
return *this;
- }
+ }
fFallbackIntervalPattern = dtitvinf.fFallbackIntervalPattern;
fFirstDateInPtnIsLaterDate = dtitvinf.fFirstDateInPtnIsLaterDate;
UBool
DateIntervalInfo::operator==(const DateIntervalInfo& other) const {
- UBool equal = (
+ UBool equal = (
fFallbackIntervalPattern == other.fFallbackIntervalPattern &&
fFirstDateInPtnIsLaterDate == other.fFirstDateInPtnIsLaterDate );
if ( U_FAILURE(status) ) {
return result;
}
-
+
const UnicodeString* patternsOfOneSkeleton = (UnicodeString*) fIntervalPatterns->get(skeleton);
if ( patternsOfOneSkeleton != NULL ) {
IntervalPatternIndex index = calendarFieldToIntervalIndex(field, status);
#define ULOC_LOCALE_IDENTIFIER_CAPACITY (ULOC_FULLNAME_CAPACITY + 1 + ULOC_KEYWORD_AND_VALUES_CAPACITY)
-void
-DateIntervalInfo::initializeData(const Locale& locale, UErrorCode& err)
+
+static const int32_t PATH_PREFIX_LENGTH = 17;
+static const UChar PATH_PREFIX[] = {SOLIDUS, CAP_L, CAP_O, CAP_C, CAP_A, CAP_L, CAP_E, SOLIDUS,
+ LOW_C, LOW_A, LOW_L, LOW_E, LOW_N, LOW_D, LOW_A, LOW_R, SOLIDUS};
+static const int32_t PATH_SUFFIX_LENGTH = 16;
+static const UChar PATH_SUFFIX[] = {SOLIDUS, LOW_I, LOW_N, LOW_T, LOW_E, LOW_R, LOW_V, LOW_A,
+ LOW_L, CAP_F, LOW_O, LOW_R, LOW_M, LOW_A, LOW_T, LOW_S};
+
+/**
+ * Sink for enumerating all of the date interval skeletons.
+ */
+struct DateIntervalInfo::DateIntervalSink : public ResourceSink {
+
+ // Output data
+ DateIntervalInfo &dateIntervalInfo;
+
+ // Next calendar type
+ UnicodeString nextCalendarType;
+
+ DateIntervalSink(DateIntervalInfo &diInfo, const char *currentCalendarType)
+ : dateIntervalInfo(diInfo), nextCalendarType(currentCalendarType, -1, US_INV) { }
+ virtual ~DateIntervalSink();
+
+ virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/, UErrorCode &errorCode) {
+ if (U_FAILURE(errorCode)) { return; }
+
+ // 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; }
+
+ nextCalendarType.remove();
+ getCalendarTypeFromPath(aliasPath, nextCalendarType, errorCode);
+
+ if (U_FAILURE(errorCode)) {
+ resetNextCalendarType();
+ }
+ break;
+
+ } else if (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(const char *key, ResourceValue &value, UErrorCode &errorCode) {
+ if (U_FAILURE(errorCode)) { return; }
+
+ // Iterate over all the patterns in the current skeleton table
+ const char *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.
+ */
+ static void getCalendarTypeFromPath(const UnicodeString &path, UnicodeString &calendarType,
+ UErrorCode &errorCode) {
+ if (U_FAILURE(errorCode)) { return; }
+
+ if (!path.startsWith(PATH_PREFIX, PATH_PREFIX_LENGTH) || !path.endsWith(PATH_SUFFIX, PATH_SUFFIX_LENGTH)) {
+ errorCode = U_INVALID_FORMAT_ERROR;
+ return;
+ }
+
+ path.extractBetween(PATH_PREFIX_LENGTH, path.length() - PATH_SUFFIX_LENGTH, calendarType);
+ }
+
+ /**
+ * Validates and processes the pattern letter
+ */
+ UCalendarDateFields validateAndProcessPatternLetter(const char *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;
+ } else if (c0 == 'y') {
+ return UCAL_YEAR;
+ } else if (c0 == 'M') {
+ return UCAL_MONTH;
+ } else if (c0 == 'd') {
+ return UCAL_DATE;
+ } else if (c0 == 'a') {
+ return UCAL_AM_PM;
+ } else if (c0 == 'h' || c0 == 'H') {
+ return UCAL_HOUR;
+ } else if (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(const char *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; }
+
+ UnicodeString skeleton(currentSkeleton, -1, US_INV);
+ UnicodeString* patternsOfOneSkeleton =
+ (UnicodeString*)(dateIntervalInfo.fIntervalPatterns->get(skeleton));
+
+ if (patternsOfOneSkeleton == NULL || patternsOfOneSkeleton[index].isEmpty()) {
+ UnicodeString pattern = value.getUnicodeString(errorCode);
+ dateIntervalInfo.setIntervalPatternInternally(skeleton, lrgDiffCalUnit,
+ pattern, errorCode);
+ }
+ }
+
+ const UnicodeString &getNextCalendarType() {
+ return nextCalendarType;
+ }
+
+ void resetNextCalendarType() {
+ nextCalendarType.setToBogus();
+ }
+};
+
+// Virtual destructors must be defined out of line.
+DateIntervalInfo::DateIntervalSink::~DateIntervalSink() {}
+
+
+
+void
+DateIntervalInfo::initializeData(const Locale& locale, UErrorCode& status)
{
- fIntervalPatterns = initHash(err);
- if ( U_FAILURE(err) ) {
- return;
- }
- const char *locName = locale.getName();
- char parentLocale[ULOC_FULLNAME_CAPACITY];
- int32_t locNameLen;
- uprv_strcpy(parentLocale, locName);
- UErrorCode status = U_ZERO_ERROR;
- Hashtable skeletonSet(FALSE, status);
- if ( U_FAILURE(status) ) {
+ fIntervalPatterns = initHash(status);
+ if (U_FAILURE(status)) {
return;
- }
-
- // determine calendar type
- const char * calendarTypeToUse = gGregorianTag; // initial default
- char calendarType[ULOC_KEYWORDS_CAPACITY]; // to be filled in with the type to use, if all goes well
- 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, NULL,
+ }
+ const char *locName = locale.getName();
+
+ // Get the correct calendar type
+ const char * calendarTypeToUse = gGregorianTag; // initial default
+ char calendarType[ULOC_KEYWORDS_CAPACITY]; // to be filled in with the type to use, if all goes well
+ 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, NULL,
"calendar", "calendar", locName, NULL, FALSE, &status);
- localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination
- // now get the calendar key value from that locale
- int32_t calendarTypeLen = uloc_getKeywordValue(localeWithCalendarKey, "calendar", calendarType, ULOC_KEYWORDS_CAPACITY, &status);
- if (U_SUCCESS(status) && calendarTypeLen < ULOC_KEYWORDS_CAPACITY) {
- calendarTypeToUse = calendarType;
- }
- status = U_ZERO_ERROR;
-
- do {
- UResourceBundle *rb, *calBundle, *calTypeBundle, *itvDtPtnResource;
- rb = ures_open(NULL, parentLocale, &status);
- calBundle = ures_getByKey(rb, gCalendarTag, NULL, &status);
- calTypeBundle = ures_getByKey(calBundle, calendarTypeToUse, NULL, &status);
- itvDtPtnResource = ures_getByKeyWithFallback(calTypeBundle,
- gIntervalDateTimePatternTag, NULL, &status);
-
- if ( U_SUCCESS(status) ) {
- // look for fallback first, since it establishes the default order
+ localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination
+ // now get the calendar key value from that locale
+ int32_t calendarTypeLen = uloc_getKeywordValue(localeWithCalendarKey, "calendar", calendarType,
+ ULOC_KEYWORDS_CAPACITY, &status);
+ if (U_SUCCESS(status) && calendarTypeLen < ULOC_KEYWORDS_CAPACITY) {
+ calendarTypeToUse = calendarType;
+ }
+ status = U_ZERO_ERROR;
+
+ // Instantiate the resource bundles
+ UResourceBundle *rb, *calBundle;
+ rb = ures_open(NULL, locName, &status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+ calBundle = ures_getByKeyWithFallback(rb, gCalendarTag, NULL, &status);
+
+
+ if (U_SUCCESS(status)) {
+ UResourceBundle *calTypeBundle, *itvDtPtnResource;
+
+ // Get the fallback pattern
const UChar* resStr;
int32_t resStrLen = 0;
- resStr = ures_getStringByKeyWithFallback(itvDtPtnResource,
- gFallbackPatternTag,
- &resStrLen, &status);
+ calTypeBundle = ures_getByKeyWithFallback(calBundle, calendarTypeToUse, NULL, &status);
+ itvDtPtnResource = ures_getByKeyWithFallback(calTypeBundle,
+ gIntervalDateTimePatternTag, NULL, &status);
+ resStr = ures_getStringByKeyWithFallback(itvDtPtnResource, gFallbackPatternTag,
+ &resStrLen, &status);
if ( U_SUCCESS(status) ) {
UnicodeString pattern = UnicodeString(TRUE, resStr, resStrLen);
setFallbackIntervalPattern(pattern, status);
}
+ ures_close(itvDtPtnResource);
+ ures_close(calTypeBundle);
- int32_t size = ures_getSize(itvDtPtnResource);
- int32_t index;
- for ( index = 0; index < size; ++index ) {
- UResourceBundle* oneRes = ures_getByIndex(itvDtPtnResource, index,
- NULL, &status);
- if ( U_SUCCESS(status) ) {
- const char* skeleton = ures_getKey(oneRes);
- if ( skeleton == NULL ||
- skeletonSet.geti(UnicodeString(skeleton)) == 1 ) {
- ures_close(oneRes);
- continue;
- }
- skeletonSet.puti(UnicodeString(skeleton), 1, status);
- if ( uprv_strcmp(skeleton, gFallbackPatternTag) == 0 ) {
- ures_close(oneRes);
- continue; // fallback
- }
-
- UResourceBundle* intervalPatterns = ures_getByKey(
- itvDtPtnResource, skeleton, NULL, &status);
-
- if ( U_FAILURE(status) ) {
- ures_close(intervalPatterns);
- ures_close(oneRes);
+
+ // Instantiate the sink
+ DateIntervalSink sink(*this, calendarTypeToUse);
+ const UnicodeString &calendarTypeToUseUString = sink.getNextCalendarType();
+
+ // Already loaded calendar types
+ Hashtable loadedCalendarTypes(FALSE, 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;
}
- if ( intervalPatterns == NULL ) {
- ures_close(intervalPatterns);
- ures_close(oneRes);
- continue;
- }
-
- const UChar* pattern;
- const char* key;
- int32_t ptLength;
- int32_t ptnNum = ures_getSize(intervalPatterns);
- int32_t ptnIndex;
- for ( ptnIndex = 0; ptnIndex < ptnNum; ++ptnIndex ) {
- pattern = ures_getNextString(intervalPatterns, &ptLength, &key,
- &status);
- if ( U_FAILURE(status) ) {
- break;
- }
-
- UCalendarDateFields calendarField = UCAL_FIELD_COUNT;
- if ( !uprv_strcmp(key, "y") ) {
- calendarField = UCAL_YEAR;
- } else if ( !uprv_strcmp(key, "M") ) {
- calendarField = UCAL_MONTH;
- } else if ( !uprv_strcmp(key, "d") ) {
- calendarField = UCAL_DATE;
- } else if ( !uprv_strcmp(key, "a") ) {
- calendarField = UCAL_AM_PM;
- } else if ( !uprv_strcmp(key, "h") || !uprv_strcmp(key, "H") ) {
- calendarField = UCAL_HOUR;
- } else if ( !uprv_strcmp(key, "m") ) {
- calendarField = UCAL_MINUTE;
- }
- if ( calendarField != UCAL_FIELD_COUNT ) {
- setIntervalPatternInternally(skeleton, calendarField, pattern,status);
- }
- }
- ures_close(intervalPatterns);
+
+ // 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; }
+ const char *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);
}
- ures_close(oneRes);
}
}
- ures_close(itvDtPtnResource);
- ures_close(calTypeBundle);
+
+ // Close the opened resource bundles
ures_close(calBundle);
ures_close(rb);
- status = U_ZERO_ERROR;
- locNameLen = uloc_getParent(parentLocale, parentLocale,
- ULOC_FULLNAME_CAPACITY,&status);
- } while ( locNameLen > 0 );
}
-
-
void
DateIntervalInfo::setIntervalPatternInternally(const UnicodeString& skeleton,
UCalendarDateFields lrgDiffCalUnit,
patternsOfOneSkeleton = new UnicodeString[kIPI_MAX_INDEX];
emptyHash = true;
}
-
+
patternsOfOneSkeleton[index] = intervalPattern;
if ( emptyHash == TRUE ) {
fIntervalPatterns->put(skeleton, patternsOfOneSkeleton, status);
-void
-DateIntervalInfo::parseSkeleton(const UnicodeString& skeleton,
+void
+DateIntervalInfo::parseSkeleton(const UnicodeString& skeleton,
int32_t* skeletonFieldWidth) {
const int8_t PATTERN_CHAR_BASE = 0x41;
int32_t i;
for ( i = 0; i < skeleton.length(); ++i ) {
// it is an ASCII char in skeleton
- int8_t ch = (int8_t)skeleton.charAt(i);
+ int8_t ch = (int8_t)skeleton.charAt(i);
++skeletonFieldWidth[ch - PATTERN_CHAR_BASE];
}
}
-UBool
+UBool
DateIntervalInfo::stringNumeric(int32_t fieldWidth, int32_t anotherFieldWidth,
char patternLetter) {
if ( patternLetter == 'M' ) {
-const UnicodeString*
+const UnicodeString*
DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton,
int8_t& bestMatchDistanceInfo) const {
#ifdef DTITVINF_DEBUG
// resource bundle only have time skeletons ending with 'v',
// but not for time skeletons ending with 'z'.
UBool replaceZWithV = false;
- const UnicodeString* inputSkeleton = &skeleton;
+ const UnicodeString* inputSkeleton = &skeleton;
UnicodeString copySkeleton;
if ( skeleton.indexOf(CHAR_Z) != -1 ) {
- UChar zstr[2];
- UChar vstr[2];
- zstr[0]=CHAR_Z;
- vstr[0]=CHAR_V;
- zstr[1]=0;
- vstr[1]=0;
copySkeleton = skeleton;
- copySkeleton.findAndReplace(zstr, vstr);
+ copySkeleton.findAndReplace(UnicodeString(CHAR_Z), UnicodeString(CHAR_V));
inputSkeleton = ©Skeleton;
replaceZWithV = true;
}
// 2 means only z/v differs
// -1 means having different field.
bestMatchDistanceInfo = 0;
- int8_t fieldLength = sizeof(skeletonFieldWidth)/sizeof(skeletonFieldWidth[0]);
+ int8_t fieldLength = UPRV_LENGTHOF(skeletonFieldWidth);
- int32_t pos = -1;
+ int32_t pos = UHASH_FIRST;
const UHashElement* elem = NULL;
while ( (elem = fIntervalPatterns->nextElement(pos)) != NULL ) {
const UHashTok keyTok = elem->key;
- UnicodeString* skeleton = (UnicodeString*)keyTok.pointer;
+ UnicodeString* newSkeleton = (UnicodeString*)keyTok.pointer;
#ifdef DTITVINF_DEBUG
skeleton->extract(0, skeleton->length(), result, "UTF-8");
sprintf(mesg, "available skeletons: skeleton: %s; \n", result);
// clear skeleton field width
int8_t i;
for ( i = 0; i < fieldLength; ++i ) {
- skeletonFieldWidth[i] = 0;
+ skeletonFieldWidth[i] = 0;
}
- parseSkeleton(*skeleton, skeletonFieldWidth);
+ parseSkeleton(*newSkeleton, skeletonFieldWidth);
// calculate distance
int32_t distance = 0;
int8_t fieldDifference = 1;
} else if ( fieldWidth == 0 ) {
fieldDifference = -1;
distance += DIFFERENT_FIELD;
- } else if (stringNumeric(inputFieldWidth, fieldWidth,
+ } else if (stringNumeric(inputFieldWidth, fieldWidth,
(char)(i+BASE) ) ) {
distance += STRING_NUMERIC_DIFFERENCE;
} else {
- distance += (inputFieldWidth > fieldWidth) ?
- (inputFieldWidth - fieldWidth) :
+ distance += (inputFieldWidth > fieldWidth) ?
+ (inputFieldWidth - fieldWidth) :
(fieldWidth - inputFieldWidth);
}
}
if ( distance < bestDistance ) {
- bestSkeleton = skeleton;
+ bestSkeleton = newSkeleton;
bestDistance = distance;
bestMatchDistanceInfo = fieldDifference;
}
DateIntervalInfo::IntervalPatternIndex
-DateIntervalInfo::calendarFieldToIntervalIndex(UCalendarDateFields field,
+DateIntervalInfo::calendarFieldToIntervalIndex(UCalendarDateFields field,
UErrorCode& status) {
if ( U_FAILURE(status) ) {
return kIPI_MAX_INDEX;
case UCAL_MINUTE:
index = kIPI_MINUTE;
break;
+ case UCAL_SECOND:
+ index = kIPI_SECOND;
+ break;
default:
status = U_ILLEGAL_ARGUMENT_ERROR;
}
void
-DateIntervalInfo::deleteHash(Hashtable* hTable)
+DateIntervalInfo::deleteHash(Hashtable* hTable)
{
if ( hTable == NULL ) {
return;
}
- int32_t pos = -1;
+ int32_t pos = UHASH_FIRST;
const UHashElement* element = NULL;
while ( (element = hTable->nextElement(pos)) != NULL ) {
- const UHashTok keyTok = element->key;
const UHashTok valueTok = element->value;
const UnicodeString* value = (UnicodeString*)valueTok.pointer;
delete[] value;
}
-U_CDECL_BEGIN
+U_CDECL_BEGIN
/**
* set hash table value comparator
*/
static UBool U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2);
-static UBool
+static UBool
U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2) {
const UnicodeString* pattern1 = (UnicodeString*)val1.pointer;
const UnicodeString* pattern2 = (UnicodeString*)val2.pointer;
return NULL;
}
if ( U_FAILURE(status) ) {
- delete hTable;
+ delete hTable;
return NULL;
}
hTable->setValueComparator(dtitvinfHashTableValueComparator);
if ( U_FAILURE(status) ) {
return;
}
- int32_t pos = -1;
+ int32_t pos = UHASH_FIRST;
const UHashElement* element = NULL;
if ( source ) {
while ( (element = source->nextElement(pos)) != NULL ) {