1 /*******************************************************************************
2 * Copyright (C) 2008-2011, International Business Machines Corporation and
3 * others. All Rights Reserved.
4 *******************************************************************************
5 *
6 * File DTITVINF.CPP
7 *
8 *******************************************************************************
9 */
10
11 #include "unicode/dtitvinf.h"
12
13
14 #if !UCONFIG_NO_FORMATTING
15
16 //TODO: define it in compiler time
17 //#define DTITVINF_DEBUG 1
18
19
20 #ifdef DTITVINF_DEBUG
21 #include <iostream>
22 #endif
23
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"
35
36
37 U_NAMESPACE_BEGIN
38
39
40 #ifdef DTITVINF_DEBUG
41 #define PRINTMESG(msg) { std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; }
42 #endif
43
44 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalInfo)
45
46 static const char gCalendarTag[]="calendar";
47 static const char gGregorianTag[]="gregorian";
48 static const char gIntervalDateTimePatternTag[]="intervalFormats";
49 static const char gFallbackPatternTag[]="fallback";
50
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};
55
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};
58
59
60
DateIntervalInfo(UErrorCode & status)61 DateIntervalInfo::DateIntervalInfo(UErrorCode& status)
62 : fFallbackIntervalPattern(gDefaultFallbackPattern),
63 fFirstDateInPtnIsLaterDate(false),
64 fIntervalPatterns(NULL)
65 {
66 fIntervalPatterns = initHash(status);
67 }
68
69
70
DateIntervalInfo(const Locale & locale,UErrorCode & status)71 DateIntervalInfo::DateIntervalInfo(const Locale& locale, UErrorCode& status)
72 : fFallbackIntervalPattern(gDefaultFallbackPattern),
73 fFirstDateInPtnIsLaterDate(false),
74 fIntervalPatterns(NULL)
75 {
76 initializeData(locale, status);
77 }
78
79
80
81 void
setIntervalPattern(const UnicodeString & skeleton,UCalendarDateFields lrgDiffCalUnit,const UnicodeString & intervalPattern,UErrorCode & status)82 DateIntervalInfo::setIntervalPattern(const UnicodeString& skeleton,
83 UCalendarDateFields lrgDiffCalUnit,
84 const UnicodeString& intervalPattern,
85 UErrorCode& status) {
86
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 }
97
98
99 void
setFallbackIntervalPattern(const UnicodeString & fallbackPattern,UErrorCode & status)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 }
119
120
121
DateIntervalInfo(const DateIntervalInfo & dtitvinf)122 DateIntervalInfo::DateIntervalInfo(const DateIntervalInfo& dtitvinf)
123 : UObject(dtitvinf),
124 fIntervalPatterns(NULL)
125 {
126 *this = dtitvinf;
127 }
128
129
130
131 DateIntervalInfo&
operator =(const DateIntervalInfo & dtitvinf)132 DateIntervalInfo::operator=(const DateIntervalInfo& dtitvinf) {
133 if ( this == &dtitvinf ) {
134 return *this;
135 }
136
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 }
144
145 fFallbackIntervalPattern = dtitvinf.fFallbackIntervalPattern;
146 fFirstDateInPtnIsLaterDate = dtitvinf.fFirstDateInPtnIsLaterDate;
147 return *this;
148 }
149
150
151 DateIntervalInfo*
clone() const152 DateIntervalInfo::clone() const {
153 return new DateIntervalInfo(*this);
154 }
155
156
~DateIntervalInfo()157 DateIntervalInfo::~DateIntervalInfo() {
158 deleteHash(fIntervalPatterns);
159 fIntervalPatterns = NULL;
160 }
161
162
163 UBool
operator ==(const DateIntervalInfo & other) const164 DateIntervalInfo::operator==(const DateIntervalInfo& other) const {
165 UBool equal = (
166 fFallbackIntervalPattern == other.fFallbackIntervalPattern &&
167 fFirstDateInPtnIsLaterDate == other.fFirstDateInPtnIsLaterDate );
168
169 if ( equal == TRUE ) {
170 equal = fIntervalPatterns->equals(*(other.fIntervalPatterns));
171 }
172
173 return equal;
174 }
175
176
177 UnicodeString&
getIntervalPattern(const UnicodeString & skeleton,UCalendarDateFields field,UnicodeString & result,UErrorCode & status) const178 DateIntervalInfo::getIntervalPattern(const UnicodeString& skeleton,
179 UCalendarDateFields field,
180 UnicodeString& result,
181 UErrorCode& status) const {
182 if ( U_FAILURE(status) ) {
183 return result;
184 }
185
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 }
199
200
201 UBool
getDefaultOrder() const202 DateIntervalInfo::getDefaultOrder() const {
203 return fFirstDateInPtnIsLaterDate;
204 }
205
206
207 UnicodeString&
getFallbackIntervalPattern(UnicodeString & result) const208 DateIntervalInfo::getFallbackIntervalPattern(UnicodeString& result) const {
209 result = fFallbackIntervalPattern;
210 return result;
211 }
212
213 #define ULOC_LOCALE_IDENTIFIER_CAPACITY (ULOC_FULLNAME_CAPACITY + 1 + ULOC_KEYWORD_AND_VALUES_CAPACITY)
214
215 void
initializeData(const Locale & locale,UErrorCode & err)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 int32_t locNameLen;
225 uprv_strcpy(parentLocale, locName);
226 UErrorCode status = U_ZERO_ERROR;
227 Hashtable skeletonSet(FALSE, status);
228 if ( U_FAILURE(status) ) {
229 return;
230 }
231
232 // determine calendar type
233 const char * calendarTypeToUse = gGregorianTag; // initial default
234 char calendarType[ULOC_KEYWORDS_CAPACITY]; // to be filled in with the type to use, if all goes well
235 char localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY];
236 // obtain a locale that always has the calendar key value that should be used
237 (void)ures_getFunctionalEquivalent(localeWithCalendarKey, ULOC_LOCALE_IDENTIFIER_CAPACITY, NULL,
238 "calendar", "calendar", locName, NULL, FALSE, &status);
239 localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination
240 // now get the calendar key value from that locale
241 int32_t calendarTypeLen = uloc_getKeywordValue(localeWithCalendarKey, "calendar", calendarType, ULOC_KEYWORDS_CAPACITY, &status);
242 if (U_SUCCESS(status) && calendarTypeLen < ULOC_KEYWORDS_CAPACITY) {
243 calendarTypeToUse = calendarType;
244 }
245 status = U_ZERO_ERROR;
246
247 do {
248 UResourceBundle *rb, *calBundle, *calTypeBundle, *itvDtPtnResource;
249 rb = ures_open(NULL, parentLocale, &status);
250 calBundle = ures_getByKey(rb, gCalendarTag, NULL, &status);
251 calTypeBundle = ures_getByKey(calBundle, calendarTypeToUse, NULL, &status);
252 itvDtPtnResource = ures_getByKeyWithFallback(calTypeBundle,
253 gIntervalDateTimePatternTag, NULL, &status);
254
255 if ( U_SUCCESS(status) ) {
256 // look for fallback first, since it establishes the default order
257 const UChar* resStr;
258 int32_t resStrLen = 0;
259 resStr = ures_getStringByKeyWithFallback(itvDtPtnResource,
260 gFallbackPatternTag,
261 &resStrLen, &status);
262 if ( U_SUCCESS(status) ) {
263 UnicodeString pattern = UnicodeString(TRUE, resStr, resStrLen);
264 setFallbackIntervalPattern(pattern, status);
265 }
266
267 int32_t size = ures_getSize(itvDtPtnResource);
268 int32_t index;
269 for ( index = 0; index < size; ++index ) {
270 LocalUResourceBundlePointer oneRes(ures_getByIndex(itvDtPtnResource, index,
271 NULL, &status));
272 if ( U_SUCCESS(status) ) {
273 const char* skeleton = ures_getKey(oneRes.getAlias());
274 if (skeleton == NULL) {
275 continue;
276 }
277 UnicodeString skeletonUniStr(skeleton, -1, US_INV);
278 if ( skeletonSet.geti(skeletonUniStr) == 1 ) {
279 continue;
280 }
281 skeletonSet.puti(skeletonUniStr, 1, status);
282 if ( uprv_strcmp(skeleton, gFallbackPatternTag) == 0 ) {
283 continue; // fallback
284 }
285
286 LocalUResourceBundlePointer intervalPatterns(ures_getByKey(
287 itvDtPtnResource, skeleton, NULL, &status));
288
289 if ( U_FAILURE(status) ) {
290 break;
291 }
292 if ( intervalPatterns == NULL ) {
293 continue;
294 }
295
296 const char* key;
297 int32_t ptnNum = ures_getSize(intervalPatterns.getAlias());
298 int32_t ptnIndex;
299 for ( ptnIndex = 0; ptnIndex < ptnNum; ++ptnIndex ) {
300 UnicodeString pattern =
301 ures_getNextUnicodeString(intervalPatterns.getAlias(), &key, &status);
302 if ( U_FAILURE(status) ) {
303 break;
304 }
305
306 UCalendarDateFields calendarField = UCAL_FIELD_COUNT;
307 if ( !uprv_strcmp(key, "y") ) {
308 calendarField = UCAL_YEAR;
309 } else if ( !uprv_strcmp(key, "M") ) {
310 calendarField = UCAL_MONTH;
311 } else if ( !uprv_strcmp(key, "d") ) {
312 calendarField = UCAL_DATE;
313 } else if ( !uprv_strcmp(key, "a") ) {
314 calendarField = UCAL_AM_PM;
315 } else if ( !uprv_strcmp(key, "h") || !uprv_strcmp(key, "H") ) {
316 calendarField = UCAL_HOUR;
317 } else if ( !uprv_strcmp(key, "m") ) {
318 calendarField = UCAL_MINUTE;
319 }
320 if ( calendarField != UCAL_FIELD_COUNT ) {
321 setIntervalPatternInternally(skeletonUniStr, calendarField, pattern,status);
322 }
323 }
324 }
325 }
326 }
327 ures_close(itvDtPtnResource);
328 ures_close(calTypeBundle);
329 ures_close(calBundle);
330 ures_close(rb);
331 status = U_ZERO_ERROR;
332 locNameLen = uloc_getParent(parentLocale, parentLocale,
333 ULOC_FULLNAME_CAPACITY,&status);
334 } while ( locNameLen > 0 );
335 }
336
337
338
339 void
setIntervalPatternInternally(const UnicodeString & skeleton,UCalendarDateFields lrgDiffCalUnit,const UnicodeString & intervalPattern,UErrorCode & status)340 DateIntervalInfo::setIntervalPatternInternally(const UnicodeString& skeleton,
341 UCalendarDateFields lrgDiffCalUnit,
342 const UnicodeString& intervalPattern,
343 UErrorCode& status) {
344 IntervalPatternIndex index = calendarFieldToIntervalIndex(lrgDiffCalUnit,status);
345 if ( U_FAILURE(status) ) {
346 return;
347 }
348 UnicodeString* patternsOfOneSkeleton = (UnicodeString*)(fIntervalPatterns->get(skeleton));
349 UBool emptyHash = false;
350 if ( patternsOfOneSkeleton == NULL ) {
351 patternsOfOneSkeleton = new UnicodeString[kIPI_MAX_INDEX];
352 emptyHash = true;
353 }
354
355 patternsOfOneSkeleton[index] = intervalPattern;
356 if ( emptyHash == TRUE ) {
357 fIntervalPatterns->put(skeleton, patternsOfOneSkeleton, status);
358 }
359 }
360
361
362
363 void
parseSkeleton(const UnicodeString & skeleton,int32_t * skeletonFieldWidth)364 DateIntervalInfo::parseSkeleton(const UnicodeString& skeleton,
365 int32_t* skeletonFieldWidth) {
366 const int8_t PATTERN_CHAR_BASE = 0x41;
367 int32_t i;
368 for ( i = 0; i < skeleton.length(); ++i ) {
369 // it is an ASCII char in skeleton
370 int8_t ch = (int8_t)skeleton.charAt(i);
371 ++skeletonFieldWidth[ch - PATTERN_CHAR_BASE];
372 }
373 }
374
375
376
377 UBool
stringNumeric(int32_t fieldWidth,int32_t anotherFieldWidth,char patternLetter)378 DateIntervalInfo::stringNumeric(int32_t fieldWidth, int32_t anotherFieldWidth,
379 char patternLetter) {
380 if ( patternLetter == 'M' ) {
381 if ( (fieldWidth <= 2 && anotherFieldWidth > 2) ||
382 (fieldWidth > 2 && anotherFieldWidth <= 2 )) {
383 return true;
384 }
385 }
386 return false;
387 }
388
389
390
391 const UnicodeString*
getBestSkeleton(const UnicodeString & skeleton,int8_t & bestMatchDistanceInfo) const392 DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton,
393 int8_t& bestMatchDistanceInfo) const {
394 #ifdef DTITVINF_DEBUG
395 char result[1000];
396 char result_1[1000];
397 char mesg[2000];
398 skeleton.extract(0, skeleton.length(), result, "UTF-8");
399 sprintf(mesg, "in getBestSkeleton: skeleton: %s; \n", result);
400 PRINTMESG(mesg)
401 #endif
402
403
404 int32_t inputSkeletonFieldWidth[] =
405 {
406 // A B C D E F G H I J K L M N O
407 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
408 // P Q R S T U V W X Y Z
409 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
410 // a b c d e f g h i j k l m n o
411 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
412 // p q r s t u v w x y z
413 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
414 };
415
416 int32_t skeletonFieldWidth[] =
417 {
418 // A B C D E F G H I J K L M N O
419 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
420 // P Q R S T U V W X Y Z
421 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
422 // a b c d e f g h i j k l m n o
423 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
424 // p q r s t u v w x y z
425 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
426 };
427
428 const int32_t DIFFERENT_FIELD = 0x1000;
429 const int32_t STRING_NUMERIC_DIFFERENCE = 0x100;
430 const int32_t BASE = 0x41;
431 const UChar CHAR_V = 0x0076;
432 const UChar CHAR_Z = 0x007A;
433
434 // hack for 'v' and 'z'.
435 // resource bundle only have time skeletons ending with 'v',
436 // but not for time skeletons ending with 'z'.
437 UBool replaceZWithV = false;
438 const UnicodeString* inputSkeleton = &skeleton;
439 UnicodeString copySkeleton;
440 if ( skeleton.indexOf(CHAR_Z) != -1 ) {
441 copySkeleton = skeleton;
442 copySkeleton.findAndReplace(UnicodeString(CHAR_Z), UnicodeString(CHAR_V));
443 inputSkeleton = ©Skeleton;
444 replaceZWithV = true;
445 }
446
447 parseSkeleton(*inputSkeleton, inputSkeletonFieldWidth);
448 int32_t bestDistance = MAX_POSITIVE_INT;
449 const UnicodeString* bestSkeleton = NULL;
450
451 // 0 means exact the same skeletons;
452 // 1 means having the same field, but with different length,
453 // 2 means only z/v differs
454 // -1 means having different field.
455 bestMatchDistanceInfo = 0;
456 int8_t fieldLength = sizeof(skeletonFieldWidth)/sizeof(skeletonFieldWidth[0]);
457
458 int32_t pos = -1;
459 const UHashElement* elem = NULL;
460 while ( (elem = fIntervalPatterns->nextElement(pos)) != NULL ) {
461 const UHashTok keyTok = elem->key;
462 UnicodeString* skeleton = (UnicodeString*)keyTok.pointer;
463 #ifdef DTITVINF_DEBUG
464 skeleton->extract(0, skeleton->length(), result, "UTF-8");
465 sprintf(mesg, "available skeletons: skeleton: %s; \n", result);
466 PRINTMESG(mesg)
467 #endif
468
469 // clear skeleton field width
470 int8_t i;
471 for ( i = 0; i < fieldLength; ++i ) {
472 skeletonFieldWidth[i] = 0;
473 }
474 parseSkeleton(*skeleton, skeletonFieldWidth);
475 // calculate distance
476 int32_t distance = 0;
477 int8_t fieldDifference = 1;
478 for ( i = 0; i < fieldLength; ++i ) {
479 int32_t inputFieldWidth = inputSkeletonFieldWidth[i];
480 int32_t fieldWidth = skeletonFieldWidth[i];
481 if ( inputFieldWidth == fieldWidth ) {
482 continue;
483 }
484 if ( inputFieldWidth == 0 ) {
485 fieldDifference = -1;
486 distance += DIFFERENT_FIELD;
487 } else if ( fieldWidth == 0 ) {
488 fieldDifference = -1;
489 distance += DIFFERENT_FIELD;
490 } else if (stringNumeric(inputFieldWidth, fieldWidth,
491 (char)(i+BASE) ) ) {
492 distance += STRING_NUMERIC_DIFFERENCE;
493 } else {
494 distance += (inputFieldWidth > fieldWidth) ?
495 (inputFieldWidth - fieldWidth) :
496 (fieldWidth - inputFieldWidth);
497 }
498 }
499 if ( distance < bestDistance ) {
500 bestSkeleton = skeleton;
501 bestDistance = distance;
502 bestMatchDistanceInfo = fieldDifference;
503 }
504 if ( distance == 0 ) {
505 bestMatchDistanceInfo = 0;
506 break;
507 }
508 }
509 if ( replaceZWithV && bestMatchDistanceInfo != -1 ) {
510 bestMatchDistanceInfo = 2;
511 }
512 return bestSkeleton;
513 }
514
515
516
517 DateIntervalInfo::IntervalPatternIndex
calendarFieldToIntervalIndex(UCalendarDateFields field,UErrorCode & status)518 DateIntervalInfo::calendarFieldToIntervalIndex(UCalendarDateFields field,
519 UErrorCode& status) {
520 if ( U_FAILURE(status) ) {
521 return kIPI_MAX_INDEX;
522 }
523 IntervalPatternIndex index = kIPI_MAX_INDEX;
524 switch ( field ) {
525 case UCAL_ERA:
526 index = kIPI_ERA;
527 break;
528 case UCAL_YEAR:
529 index = kIPI_YEAR;
530 break;
531 case UCAL_MONTH:
532 index = kIPI_MONTH;
533 break;
534 case UCAL_DATE:
535 case UCAL_DAY_OF_WEEK:
536 //case UCAL_DAY_OF_MONTH:
537 index = kIPI_DATE;
538 break;
539 case UCAL_AM_PM:
540 index = kIPI_AM_PM;
541 break;
542 case UCAL_HOUR:
543 case UCAL_HOUR_OF_DAY:
544 index = kIPI_HOUR;
545 break;
546 case UCAL_MINUTE:
547 index = kIPI_MINUTE;
548 break;
549 default:
550 status = U_ILLEGAL_ARGUMENT_ERROR;
551 }
552 return index;
553 }
554
555
556
557 void
deleteHash(Hashtable * hTable)558 DateIntervalInfo::deleteHash(Hashtable* hTable)
559 {
560 if ( hTable == NULL ) {
561 return;
562 }
563 int32_t pos = -1;
564 const UHashElement* element = NULL;
565 while ( (element = hTable->nextElement(pos)) != NULL ) {
566 const UHashTok valueTok = element->value;
567 const UnicodeString* value = (UnicodeString*)valueTok.pointer;
568 delete[] value;
569 }
570 delete fIntervalPatterns;
571 }
572
573
574 U_CDECL_BEGIN
575
576 /**
577 * set hash table value comparator
578 *
579 * @param val1 one value in comparison
580 * @param val2 the other value in comparison
581 * @return TRUE if 2 values are the same, FALSE otherwise
582 */
583 static UBool U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2);
584
585 static UBool
dtitvinfHashTableValueComparator(UHashTok val1,UHashTok val2)586 U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2) {
587 const UnicodeString* pattern1 = (UnicodeString*)val1.pointer;
588 const UnicodeString* pattern2 = (UnicodeString*)val2.pointer;
589 UBool ret = TRUE;
590 int8_t i;
591 for ( i = 0; i < DateIntervalInfo::kMaxIntervalPatternIndex && ret == TRUE; ++i ) {
592 ret = (pattern1[i] == pattern2[i]);
593 }
594 return ret;
595 }
596
597 U_CDECL_END
598
599
600 Hashtable*
initHash(UErrorCode & status)601 DateIntervalInfo::initHash(UErrorCode& status) {
602 if ( U_FAILURE(status) ) {
603 return NULL;
604 }
605 Hashtable* hTable;
606 if ( (hTable = new Hashtable(FALSE, status)) == NULL ) {
607 status = U_MEMORY_ALLOCATION_ERROR;
608 return NULL;
609 }
610 if ( U_FAILURE(status) ) {
611 delete hTable;
612 return NULL;
613 }
614 hTable->setValueComparator(dtitvinfHashTableValueComparator);
615 return hTable;
616 }
617
618
619 void
copyHash(const Hashtable * source,Hashtable * target,UErrorCode & status)620 DateIntervalInfo::copyHash(const Hashtable* source,
621 Hashtable* target,
622 UErrorCode& status) {
623 if ( U_FAILURE(status) ) {
624 return;
625 }
626 int32_t pos = -1;
627 const UHashElement* element = NULL;
628 if ( source ) {
629 while ( (element = source->nextElement(pos)) != NULL ) {
630 const UHashTok keyTok = element->key;
631 const UnicodeString* key = (UnicodeString*)keyTok.pointer;
632 const UHashTok valueTok = element->value;
633 const UnicodeString* value = (UnicodeString*)valueTok.pointer;
634 UnicodeString* copy = new UnicodeString[kIPI_MAX_INDEX];
635 int8_t i;
636 for ( i = 0; i < kIPI_MAX_INDEX; ++i ) {
637 copy[i] = value[i];
638 }
639 target->put(UnicodeString(*key), copy, status);
640 if ( U_FAILURE(status) ) {
641 return;
642 }
643 }
644 }
645 }
646
647
648 U_NAMESPACE_END
649
650 #endif
651