intl/icu/source/i18n/dtitvinf.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*******************************************************************************
     2 * Copyright (C) 2008-2012, International Business Machines Corporation and
     3 * others. All Rights Reserved.
     4 *******************************************************************************
     5 *
     6 * File DTITVINF.CPP 
     7 *
     8 *******************************************************************************
     9 */
    11 #include "unicode/dtitvinf.h"
    14 #if !UCONFIG_NO_FORMATTING
    16 //TODO: define it in compiler time
    17 //#define DTITVINF_DEBUG 1
    20 #ifdef DTITVINF_DEBUG 
    21 #include <iostream>
    22 #endif
    24 #include "cstring.h"
    25 #include "unicode/msgfmt.h"
    26 #include "unicode/uloc.h"
    27 #include "unicode/ures.h"
    28 #include "dtitv_impl.h"
    29 #include "hash.h"
    30 #include "gregoimp.h"
    31 #include "uresimp.h"
    32 #include "hash.h"
    33 #include "gregoimp.h"
    34 #include "uresimp.h"
    37 U_NAMESPACE_BEGIN
    40 #ifdef DTITVINF_DEBUG 
    41 #define PRINTMESG(msg) { std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; }
    42 #endif
    44 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalInfo)
    46 static const char gCalendarTag[]="calendar";
    47 static const char gGregorianTag[]="gregorian";
    48 static const char gIntervalDateTimePatternTag[]="intervalFormats";
    49 static const char gFallbackPatternTag[]="fallback";
    51 // {0}
    52 static const UChar gFirstPattern[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET};
    53 // {1}
    54 static const UChar gSecondPattern[] = {LEFT_CURLY_BRACKET, DIGIT_ONE, RIGHT_CURLY_BRACKET};
    56 // default fall-back
    57 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};
    61 DateIntervalInfo::DateIntervalInfo(UErrorCode& status) 
    62 :   fFallbackIntervalPattern(gDefaultFallbackPattern),
    63     fFirstDateInPtnIsLaterDate(false),
    64     fIntervalPatterns(NULL)
    65 {
    66     fIntervalPatterns = initHash(status);
    67 }
    71 DateIntervalInfo::DateIntervalInfo(const Locale& locale, UErrorCode& status)
    72 :   fFallbackIntervalPattern(gDefaultFallbackPattern),
    73     fFirstDateInPtnIsLaterDate(false),
    74     fIntervalPatterns(NULL)
    75 {
    76     initializeData(locale, status);
    77 }
    81 void
    82 DateIntervalInfo::setIntervalPattern(const UnicodeString& skeleton,
    83                                      UCalendarDateFields lrgDiffCalUnit,
    84                                      const UnicodeString& intervalPattern,
    85                                      UErrorCode& status) {
    87     if ( lrgDiffCalUnit == UCAL_HOUR_OF_DAY ) {
    88         setIntervalPatternInternally(skeleton, UCAL_AM_PM, intervalPattern, status);
    89         setIntervalPatternInternally(skeleton, UCAL_HOUR, intervalPattern, status);
    90     } else if ( lrgDiffCalUnit == UCAL_DAY_OF_MONTH ||
    91                 lrgDiffCalUnit == UCAL_DAY_OF_WEEK ) {
    92         setIntervalPatternInternally(skeleton, UCAL_DATE, intervalPattern, status);
    93     } else {
    94         setIntervalPatternInternally(skeleton, lrgDiffCalUnit, intervalPattern, status);
    95     }
    96 }
    99 void
   100 DateIntervalInfo::setFallbackIntervalPattern(
   101                                     const UnicodeString& fallbackPattern,
   102                                     UErrorCode& status) {
   103     if ( U_FAILURE(status) ) {
   104         return;
   105     }
   106     int32_t firstPatternIndex = fallbackPattern.indexOf(gFirstPattern, 
   107                         sizeof(gFirstPattern)/sizeof(gFirstPattern[0]), 0);
   108     int32_t secondPatternIndex = fallbackPattern.indexOf(gSecondPattern, 
   109                         sizeof(gSecondPattern)/sizeof(gSecondPattern[0]), 0);
   110     if ( firstPatternIndex == -1 || secondPatternIndex == -1 ) {
   111         status = U_ILLEGAL_ARGUMENT_ERROR;
   112         return;
   113     }
   114     if ( firstPatternIndex > secondPatternIndex ) { 
   115         fFirstDateInPtnIsLaterDate = true;
   116     }
   117     fFallbackIntervalPattern = fallbackPattern;
   118 }
   122 DateIntervalInfo::DateIntervalInfo(const DateIntervalInfo& dtitvinf)
   123 :   UObject(dtitvinf),
   124     fIntervalPatterns(NULL)
   125 {
   126     *this = dtitvinf;
   127 }
   131 DateIntervalInfo&
   132 DateIntervalInfo::operator=(const DateIntervalInfo& dtitvinf) {
   133     if ( this == &dtitvinf ) {
   134         return *this;
   135     }
   137     UErrorCode status = U_ZERO_ERROR;
   138     deleteHash(fIntervalPatterns);
   139     fIntervalPatterns = initHash(status);
   140     copyHash(dtitvinf.fIntervalPatterns, fIntervalPatterns, status);
   141     if ( U_FAILURE(status) ) {
   142         return *this;
   143     } 
   145     fFallbackIntervalPattern = dtitvinf.fFallbackIntervalPattern;
   146     fFirstDateInPtnIsLaterDate = dtitvinf.fFirstDateInPtnIsLaterDate;
   147     return *this;
   148 }
   151 DateIntervalInfo*
   152 DateIntervalInfo::clone() const {
   153     return new DateIntervalInfo(*this);
   154 }
   157 DateIntervalInfo::~DateIntervalInfo() {
   158     deleteHash(fIntervalPatterns);
   159     fIntervalPatterns = NULL;
   160 }
   163 UBool
   164 DateIntervalInfo::operator==(const DateIntervalInfo& other) const {
   165     UBool equal = ( 
   166       fFallbackIntervalPattern == other.fFallbackIntervalPattern &&
   167       fFirstDateInPtnIsLaterDate == other.fFirstDateInPtnIsLaterDate );
   169     if ( equal == TRUE ) {
   170         equal = fIntervalPatterns->equals(*(other.fIntervalPatterns));
   171     }
   173     return equal;
   174 }
   177 UnicodeString&
   178 DateIntervalInfo::getIntervalPattern(const UnicodeString& skeleton,
   179                                      UCalendarDateFields field,
   180                                      UnicodeString& result,
   181                                      UErrorCode& status) const {
   182     if ( U_FAILURE(status) ) {
   183         return result;
   184     }
   186     const UnicodeString* patternsOfOneSkeleton = (UnicodeString*) fIntervalPatterns->get(skeleton);
   187     if ( patternsOfOneSkeleton != NULL ) {
   188         IntervalPatternIndex index = calendarFieldToIntervalIndex(field, status);
   189         if ( U_FAILURE(status) ) {
   190             return result;
   191         }
   192         const UnicodeString& intervalPattern =  patternsOfOneSkeleton[index];
   193         if ( !intervalPattern.isEmpty() ) {
   194             result = intervalPattern;
   195         }
   196     }
   197     return result;
   198 }
   201 UBool
   202 DateIntervalInfo::getDefaultOrder() const {
   203     return fFirstDateInPtnIsLaterDate;
   204 }
   207 UnicodeString&
   208 DateIntervalInfo::getFallbackIntervalPattern(UnicodeString& result) const {
   209     result = fFallbackIntervalPattern;
   210     return result;
   211 }
   213 #define ULOC_LOCALE_IDENTIFIER_CAPACITY (ULOC_FULLNAME_CAPACITY + 1 + ULOC_KEYWORD_AND_VALUES_CAPACITY)
   215 void 
   216 DateIntervalInfo::initializeData(const Locale& locale, UErrorCode& err)
   217 {
   218   fIntervalPatterns = initHash(err);
   219   if ( U_FAILURE(err) ) {
   220       return;
   221   }
   222   const char *locName = locale.getName();
   223   char parentLocale[ULOC_FULLNAME_CAPACITY];
   224   uprv_strcpy(parentLocale, locName);
   225   UErrorCode status = U_ZERO_ERROR;
   226   Hashtable skeletonSet(FALSE, status);
   227   if ( U_FAILURE(status) ) {
   228       return;
   229   }
   231   // determine calendar type
   232   const char * calendarTypeToUse = gGregorianTag; // initial default
   233   char         calendarType[ULOC_KEYWORDS_CAPACITY]; // to be filled in with the type to use, if all goes well
   234   char         localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY];
   235   // obtain a locale that always has the calendar key value that should be used
   236   (void)ures_getFunctionalEquivalent(localeWithCalendarKey, ULOC_LOCALE_IDENTIFIER_CAPACITY, NULL,
   237                                      "calendar", "calendar", locName, NULL, FALSE, &status);
   238   localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination
   239   // now get the calendar key value from that locale
   240   int32_t calendarTypeLen = uloc_getKeywordValue(localeWithCalendarKey, "calendar", calendarType, ULOC_KEYWORDS_CAPACITY, &status);
   241   if (U_SUCCESS(status) && calendarTypeLen < ULOC_KEYWORDS_CAPACITY) {
   242     calendarTypeToUse = calendarType;
   243   }
   244   status = U_ZERO_ERROR;
   246   do {
   247     UResourceBundle *rb, *calBundle, *calTypeBundle, *itvDtPtnResource;
   248     rb = ures_open(NULL, parentLocale, &status);
   249     if ( U_FAILURE(status) ) {
   250         break;
   251     }
   252     calBundle = ures_getByKey(rb, gCalendarTag, NULL, &status); 
   253     calTypeBundle = ures_getByKey(calBundle, calendarTypeToUse, NULL, &status);
   254     itvDtPtnResource = ures_getByKeyWithFallback(calTypeBundle, 
   255                          gIntervalDateTimePatternTag, NULL, &status);
   257     if ( U_SUCCESS(status) ) {
   258         // look for fallback first, since it establishes the default order
   259         const UChar* resStr;
   260         int32_t resStrLen = 0;
   261         resStr = ures_getStringByKeyWithFallback(itvDtPtnResource, 
   262                                              gFallbackPatternTag, 
   263                                              &resStrLen, &status);
   264         if ( U_SUCCESS(status) ) {
   265             UnicodeString pattern = UnicodeString(TRUE, resStr, resStrLen);
   266             setFallbackIntervalPattern(pattern, status);
   267         }
   269         int32_t size = ures_getSize(itvDtPtnResource);
   270         int32_t index;
   271         for ( index = 0; index < size; ++index ) {
   272             LocalUResourceBundlePointer oneRes(ures_getByIndex(itvDtPtnResource, index, 
   273                                                      NULL, &status));
   274             if ( U_SUCCESS(status) ) {
   275                 const char* skeleton = ures_getKey(oneRes.getAlias());
   276                 if (skeleton == NULL) {
   277                     continue;
   278                 }
   279                 UnicodeString skeletonUniStr(skeleton, -1, US_INV);
   280                 if ( skeletonSet.geti(skeletonUniStr) == 1 ) {
   281                     continue;
   282                 }
   283                 skeletonSet.puti(skeletonUniStr, 1, status);
   284                 if ( uprv_strcmp(skeleton, gFallbackPatternTag) == 0 ) {
   285                     continue;  // fallback
   286                 }
   288                 LocalUResourceBundlePointer intervalPatterns(ures_getByKey(
   289                                      itvDtPtnResource, skeleton, NULL, &status));
   291                 if ( U_FAILURE(status) ) {
   292                     break;
   293                 }
   294                 if ( intervalPatterns == NULL ) {
   295                     continue;
   296                 }
   298                 const char* key;
   299                 int32_t ptnNum = ures_getSize(intervalPatterns.getAlias());
   300                 int32_t ptnIndex;
   301                 for ( ptnIndex = 0; ptnIndex < ptnNum; ++ptnIndex ) {
   302                     UnicodeString pattern =
   303                         ures_getNextUnicodeString(intervalPatterns.getAlias(), &key, &status);
   304                     if ( U_FAILURE(status) ) {
   305                         break;
   306                     }
   308                     UCalendarDateFields calendarField = UCAL_FIELD_COUNT;
   309                     if ( !uprv_strcmp(key, "y") ) {
   310                         calendarField = UCAL_YEAR;
   311                     } else if ( !uprv_strcmp(key, "M") ) {
   312                         calendarField = UCAL_MONTH;
   313                     } else if ( !uprv_strcmp(key, "d") ) {
   314                         calendarField = UCAL_DATE;
   315                     } else if ( !uprv_strcmp(key, "a") ) {
   316                         calendarField = UCAL_AM_PM;
   317                     } else if ( !uprv_strcmp(key, "h") || !uprv_strcmp(key, "H") ) {
   318                         calendarField = UCAL_HOUR;
   319                     } else if ( !uprv_strcmp(key, "m") ) {
   320                         calendarField = UCAL_MINUTE;
   321                     }
   322                     if ( calendarField != UCAL_FIELD_COUNT ) {
   323                         setIntervalPatternInternally(skeletonUniStr, calendarField, pattern,status);
   324                     }
   325                 }
   326             }
   327         }
   328     }
   329     ures_close(itvDtPtnResource);
   330     ures_close(calTypeBundle);
   331     ures_close(calBundle);
   333     status = U_ZERO_ERROR;
   334     // Find the name of the appropriate parent locale (from %%Parent if present, else
   335     // uloc_getParent on the actual locale name)
   336     // (It would be nice to have a ures function that did this...)
   337     int32_t locNameLen;
   338     const UChar * parentUName = ures_getStringByKey(rb, "%%Parent", &locNameLen, &status);
   339     if (U_SUCCESS(status) && status != U_USING_FALLBACK_WARNING && locNameLen < ULOC_FULLNAME_CAPACITY) {
   340         u_UCharsToChars(parentUName, parentLocale, locNameLen + 1);
   341     } else {
   342         status = U_ZERO_ERROR;
   343         // Get the actual name of the current locale being used
   344         const char *curLocaleName=ures_getLocaleByType(rb, ULOC_ACTUAL_LOCALE, &status);
   345         if ( U_FAILURE(status) ) {
   346             curLocaleName = parentLocale;
   347             status = U_ZERO_ERROR;
   348         }
   349         uloc_getParent(curLocaleName, parentLocale, ULOC_FULLNAME_CAPACITY, &status);
   350         if (U_FAILURE(err) || err == U_STRING_NOT_TERMINATED_WARNING) {
   351             parentLocale[0] = 0; // just fallback to root, will cause us to stop
   352             status = U_ZERO_ERROR;
   353         }
   354     }
   355     // Now we can close the current locale bundle
   356     ures_close(rb);
   357     // If the new current locale is root, then stop
   358     // (unlike for DateTimePatternGenerator, DateIntervalFormat does not go all the way up
   359     // to root to find additional data for non-root locales)
   360   } while ( parentLocale[0] != 0 && uprv_strcmp(parentLocale,"root")!=0 );
   361 }
   365 void
   366 DateIntervalInfo::setIntervalPatternInternally(const UnicodeString& skeleton,
   367                                       UCalendarDateFields lrgDiffCalUnit,
   368                                       const UnicodeString& intervalPattern,
   369                                       UErrorCode& status) {
   370     IntervalPatternIndex index = calendarFieldToIntervalIndex(lrgDiffCalUnit,status);
   371     if ( U_FAILURE(status) ) {
   372         return;
   373     }
   374     UnicodeString* patternsOfOneSkeleton = (UnicodeString*)(fIntervalPatterns->get(skeleton));
   375     UBool emptyHash = false;
   376     if ( patternsOfOneSkeleton == NULL ) {
   377         patternsOfOneSkeleton = new UnicodeString[kIPI_MAX_INDEX];
   378         emptyHash = true;
   379     }
   381     patternsOfOneSkeleton[index] = intervalPattern;
   382     if ( emptyHash == TRUE ) {
   383         fIntervalPatterns->put(skeleton, patternsOfOneSkeleton, status);
   384     }
   385 }
   389 void 
   390 DateIntervalInfo::parseSkeleton(const UnicodeString& skeleton, 
   391                                 int32_t* skeletonFieldWidth) {
   392     const int8_t PATTERN_CHAR_BASE = 0x41;
   393     int32_t i;
   394     for ( i = 0; i < skeleton.length(); ++i ) {
   395         // it is an ASCII char in skeleton
   396         int8_t ch = (int8_t)skeleton.charAt(i);  
   397         ++skeletonFieldWidth[ch - PATTERN_CHAR_BASE];
   398     }
   399 }
   403 UBool 
   404 DateIntervalInfo::stringNumeric(int32_t fieldWidth, int32_t anotherFieldWidth,
   405                                 char patternLetter) {
   406     if ( patternLetter == 'M' ) {
   407         if ( (fieldWidth <= 2 && anotherFieldWidth > 2) ||
   408              (fieldWidth > 2 && anotherFieldWidth <= 2 )) {
   409             return true;
   410         }
   411     }
   412     return false;
   413 }
   417 const UnicodeString* 
   418 DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton,
   419                                   int8_t& bestMatchDistanceInfo) const {
   420 #ifdef DTITVINF_DEBUG
   421     char result[1000];
   422     char result_1[1000];
   423     char mesg[2000];
   424     skeleton.extract(0,  skeleton.length(), result, "UTF-8");
   425     sprintf(mesg, "in getBestSkeleton: skeleton: %s; \n", result);
   426     PRINTMESG(mesg)
   427 #endif
   430     int32_t inputSkeletonFieldWidth[] =
   431     {
   432     //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
   433              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   434     //   P   Q   R   S   T   U   V   W   X   Y   Z
   435          0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
   436     //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
   437          0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   438     //   p   q   r   s   t   u   v   w   x   y   z
   439          0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
   440     };
   442     int32_t skeletonFieldWidth[] =
   443     {
   444     //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
   445              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   446     //   P   Q   R   S   T   U   V   W   X   Y   Z
   447          0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
   448     //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
   449          0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   450     //   p   q   r   s   t   u   v   w   x   y   z
   451          0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
   452     };
   454     const int32_t DIFFERENT_FIELD = 0x1000;
   455     const int32_t STRING_NUMERIC_DIFFERENCE = 0x100;
   456     const int32_t BASE = 0x41;
   457     const UChar CHAR_V = 0x0076;
   458     const UChar CHAR_Z = 0x007A;
   460     // hack for 'v' and 'z'.
   461     // resource bundle only have time skeletons ending with 'v',
   462     // but not for time skeletons ending with 'z'.
   463     UBool replaceZWithV = false;
   464     const UnicodeString* inputSkeleton = &skeleton; 
   465     UnicodeString copySkeleton;
   466     if ( skeleton.indexOf(CHAR_Z) != -1 ) {
   467         copySkeleton = skeleton;
   468         copySkeleton.findAndReplace(UnicodeString(CHAR_Z), UnicodeString(CHAR_V));
   469         inputSkeleton = &copySkeleton;
   470         replaceZWithV = true;
   471     }
   473     parseSkeleton(*inputSkeleton, inputSkeletonFieldWidth);
   474     int32_t bestDistance = MAX_POSITIVE_INT;
   475     const UnicodeString* bestSkeleton = NULL;
   477     // 0 means exact the same skeletons;
   478     // 1 means having the same field, but with different length,
   479     // 2 means only z/v differs
   480     // -1 means having different field.
   481     bestMatchDistanceInfo = 0;
   482     int8_t fieldLength = sizeof(skeletonFieldWidth)/sizeof(skeletonFieldWidth[0]);
   484     int32_t pos = -1;
   485     const UHashElement* elem = NULL;
   486     while ( (elem = fIntervalPatterns->nextElement(pos)) != NULL ) {
   487         const UHashTok keyTok = elem->key;
   488         UnicodeString* skeleton = (UnicodeString*)keyTok.pointer;
   489 #ifdef DTITVINF_DEBUG
   490     skeleton->extract(0,  skeleton->length(), result, "UTF-8");
   491     sprintf(mesg, "available skeletons: skeleton: %s; \n", result);
   492     PRINTMESG(mesg)
   493 #endif
   495         // clear skeleton field width
   496         int8_t i;
   497         for ( i = 0; i < fieldLength; ++i ) {
   498             skeletonFieldWidth[i] = 0;    
   499         }
   500         parseSkeleton(*skeleton, skeletonFieldWidth);
   501         // calculate distance
   502         int32_t distance = 0;
   503         int8_t fieldDifference = 1;
   504         for ( i = 0; i < fieldLength; ++i ) {
   505             int32_t inputFieldWidth = inputSkeletonFieldWidth[i];
   506             int32_t fieldWidth = skeletonFieldWidth[i];
   507             if ( inputFieldWidth == fieldWidth ) {
   508                 continue;
   509             }
   510             if ( inputFieldWidth == 0 ) {
   511                 fieldDifference = -1;
   512                 distance += DIFFERENT_FIELD;
   513             } else if ( fieldWidth == 0 ) {
   514                 fieldDifference = -1;
   515                 distance += DIFFERENT_FIELD;
   516             } else if (stringNumeric(inputFieldWidth, fieldWidth, 
   517                                      (char)(i+BASE) ) ) {
   518                 distance += STRING_NUMERIC_DIFFERENCE;
   519             } else {
   520                 distance += (inputFieldWidth > fieldWidth) ? 
   521                             (inputFieldWidth - fieldWidth) : 
   522                             (fieldWidth - inputFieldWidth);
   523             }
   524         }
   525         if ( distance < bestDistance ) {
   526             bestSkeleton = skeleton;
   527             bestDistance = distance;
   528             bestMatchDistanceInfo = fieldDifference;
   529         }
   530         if ( distance == 0 ) {
   531             bestMatchDistanceInfo = 0;
   532             break;
   533         }
   534     }
   535     if ( replaceZWithV && bestMatchDistanceInfo != -1 ) {
   536         bestMatchDistanceInfo = 2;
   537     }
   538     return bestSkeleton;
   539 }
   543 DateIntervalInfo::IntervalPatternIndex
   544 DateIntervalInfo::calendarFieldToIntervalIndex(UCalendarDateFields field, 
   545                                                UErrorCode& status) {
   546     if ( U_FAILURE(status) ) {
   547         return kIPI_MAX_INDEX;
   548     }
   549     IntervalPatternIndex index = kIPI_MAX_INDEX;
   550     switch ( field ) {
   551       case UCAL_ERA:
   552         index = kIPI_ERA;
   553         break;
   554       case UCAL_YEAR:
   555         index = kIPI_YEAR;
   556         break;
   557       case UCAL_MONTH:
   558         index = kIPI_MONTH;
   559         break;
   560       case UCAL_DATE:
   561       case UCAL_DAY_OF_WEEK:
   562       //case UCAL_DAY_OF_MONTH:
   563         index = kIPI_DATE;
   564         break;
   565       case UCAL_AM_PM:
   566         index = kIPI_AM_PM;
   567         break;
   568       case UCAL_HOUR:
   569       case UCAL_HOUR_OF_DAY:
   570         index = kIPI_HOUR;
   571         break;
   572       case UCAL_MINUTE:
   573         index = kIPI_MINUTE;
   574         break;
   575       default:
   576         status = U_ILLEGAL_ARGUMENT_ERROR;
   577     }
   578     return index;
   579 }
   583 void
   584 DateIntervalInfo::deleteHash(Hashtable* hTable) 
   585 {
   586     if ( hTable == NULL ) {
   587         return;
   588     }
   589     int32_t pos = -1;
   590     const UHashElement* element = NULL;
   591     while ( (element = hTable->nextElement(pos)) != NULL ) {
   592         const UHashTok valueTok = element->value;
   593         const UnicodeString* value = (UnicodeString*)valueTok.pointer;
   594         delete[] value;
   595     }
   596     delete fIntervalPatterns;
   597 }
   600 U_CDECL_BEGIN 
   602 /**
   603  * set hash table value comparator
   604  *
   605  * @param val1  one value in comparison
   606  * @param val2  the other value in comparison
   607  * @return      TRUE if 2 values are the same, FALSE otherwise
   608  */
   609 static UBool U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2);
   611 static UBool 
   612 U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2) {
   613     const UnicodeString* pattern1 = (UnicodeString*)val1.pointer;
   614     const UnicodeString* pattern2 = (UnicodeString*)val2.pointer;
   615     UBool ret = TRUE;
   616     int8_t i;
   617     for ( i = 0; i < DateIntervalInfo::kMaxIntervalPatternIndex && ret == TRUE; ++i ) {
   618         ret = (pattern1[i] == pattern2[i]);
   619     }
   620     return ret;
   621 }
   623 U_CDECL_END
   626 Hashtable*
   627 DateIntervalInfo::initHash(UErrorCode& status) {
   628     if ( U_FAILURE(status) ) {
   629         return NULL;
   630     }
   631     Hashtable* hTable;
   632     if ( (hTable = new Hashtable(FALSE, status)) == NULL ) {
   633         status = U_MEMORY_ALLOCATION_ERROR;
   634         return NULL;
   635     }
   636     if ( U_FAILURE(status) ) {
   637         delete hTable; 
   638         return NULL;
   639     }
   640     hTable->setValueComparator(dtitvinfHashTableValueComparator);
   641     return hTable;
   642 }
   645 void
   646 DateIntervalInfo::copyHash(const Hashtable* source,
   647                            Hashtable* target,
   648                            UErrorCode& status) {
   649     if ( U_FAILURE(status) ) {
   650         return;
   651     }
   652     int32_t pos = -1;
   653     const UHashElement* element = NULL;
   654     if ( source ) {
   655         while ( (element = source->nextElement(pos)) != NULL ) {
   656             const UHashTok keyTok = element->key;
   657             const UnicodeString* key = (UnicodeString*)keyTok.pointer;
   658             const UHashTok valueTok = element->value;
   659             const UnicodeString* value = (UnicodeString*)valueTok.pointer;
   660             UnicodeString* copy = new UnicodeString[kIPI_MAX_INDEX];
   661             int8_t i;
   662             for ( i = 0; i < kIPI_MAX_INDEX; ++i ) {
   663                 copy[i] = value[i];
   664             }
   665             target->put(UnicodeString(*key), copy, status);
   666             if ( U_FAILURE(status) ) {
   667                 return;
   668             }
   669         }
   670     }
   671 }
   674 U_NAMESPACE_END
   676 #endif

mercurial