]> git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/dtitvinf.cpp
ICU-461.13.tar.gz
[apple/icu.git] / icuSources / i18n / dtitvinf.cpp
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
61 DateIntervalInfo::DateIntervalInfo(UErrorCode& status)
62 : fFallbackIntervalPattern(gDefaultFallbackPattern),
63 fFirstDateInPtnIsLaterDate(false),
64 fIntervalPatterns(NULL)
65 {
66 fIntervalPatterns = initHash(status);
67 }
68
69
70
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
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
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
122 DateIntervalInfo::DateIntervalInfo(const DateIntervalInfo& dtitvinf)
123 : UObject(dtitvinf),
124 fIntervalPatterns(NULL)
125 {
126 *this = dtitvinf;
127 }
128
129
130
131 DateIntervalInfo&
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*
152 DateIntervalInfo::clone() const {
153 return new DateIntervalInfo(*this);
154 }
155
156
157 DateIntervalInfo::~DateIntervalInfo() {
158 deleteHash(fIntervalPatterns);
159 fIntervalPatterns = NULL;
160 }
161
162
163 UBool
164 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&
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 }
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
202 DateIntervalInfo::getDefaultOrder() const {
203 return fFirstDateInPtnIsLaterDate;
204 }
205
206
207 UnicodeString&
208 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
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 UResourceBundle* oneRes = ures_getByIndex(itvDtPtnResource, index,
271 NULL, &status);
272 if ( U_SUCCESS(status) ) {
273 const char* skeleton = ures_getKey(oneRes);
274 if ( skeleton == NULL ||
275 skeletonSet.geti(UnicodeString(skeleton)) == 1 ) {
276 ures_close(oneRes);
277 continue;
278 }
279 skeletonSet.puti(UnicodeString(skeleton), 1, status);
280 if ( uprv_strcmp(skeleton, gFallbackPatternTag) == 0 ) {
281 ures_close(oneRes);
282 continue; // fallback
283 }
284
285 UResourceBundle* intervalPatterns = ures_getByKey(
286 itvDtPtnResource, skeleton, NULL, &status);
287
288 if ( U_FAILURE(status) ) {
289 ures_close(intervalPatterns);
290 ures_close(oneRes);
291 break;
292 }
293 if ( intervalPatterns == NULL ) {
294 ures_close(intervalPatterns);
295 ures_close(oneRes);
296 continue;
297 }
298
299 const UChar* pattern;
300 const char* key;
301 int32_t ptLength;
302 int32_t ptnNum = ures_getSize(intervalPatterns);
303 int32_t ptnIndex;
304 for ( ptnIndex = 0; ptnIndex < ptnNum; ++ptnIndex ) {
305 pattern = ures_getNextString(intervalPatterns, &ptLength, &key,
306 &status);
307 if ( U_FAILURE(status) ) {
308 break;
309 }
310
311 UCalendarDateFields calendarField = UCAL_FIELD_COUNT;
312 if ( !uprv_strcmp(key, "y") ) {
313 calendarField = UCAL_YEAR;
314 } else if ( !uprv_strcmp(key, "M") ) {
315 calendarField = UCAL_MONTH;
316 } else if ( !uprv_strcmp(key, "d") ) {
317 calendarField = UCAL_DATE;
318 } else if ( !uprv_strcmp(key, "a") ) {
319 calendarField = UCAL_AM_PM;
320 } else if ( !uprv_strcmp(key, "h") || !uprv_strcmp(key, "H") ) {
321 calendarField = UCAL_HOUR;
322 } else if ( !uprv_strcmp(key, "m") ) {
323 calendarField = UCAL_MINUTE;
324 }
325 if ( calendarField != UCAL_FIELD_COUNT ) {
326 setIntervalPatternInternally(skeleton, calendarField, pattern,status);
327 }
328 }
329 ures_close(intervalPatterns);
330 }
331 ures_close(oneRes);
332 }
333 }
334 ures_close(itvDtPtnResource);
335 ures_close(calTypeBundle);
336 ures_close(calBundle);
337 ures_close(rb);
338 status = U_ZERO_ERROR;
339 locNameLen = uloc_getParent(parentLocale, parentLocale,
340 ULOC_FULLNAME_CAPACITY,&status);
341 } while ( locNameLen > 0 );
342 }
343
344
345
346 void
347 DateIntervalInfo::setIntervalPatternInternally(const UnicodeString& skeleton,
348 UCalendarDateFields lrgDiffCalUnit,
349 const UnicodeString& intervalPattern,
350 UErrorCode& status) {
351 IntervalPatternIndex index = calendarFieldToIntervalIndex(lrgDiffCalUnit,status);
352 if ( U_FAILURE(status) ) {
353 return;
354 }
355 UnicodeString* patternsOfOneSkeleton = (UnicodeString*)(fIntervalPatterns->get(skeleton));
356 UBool emptyHash = false;
357 if ( patternsOfOneSkeleton == NULL ) {
358 patternsOfOneSkeleton = new UnicodeString[kIPI_MAX_INDEX];
359 emptyHash = true;
360 }
361
362 patternsOfOneSkeleton[index] = intervalPattern;
363 if ( emptyHash == TRUE ) {
364 fIntervalPatterns->put(skeleton, patternsOfOneSkeleton, status);
365 }
366 }
367
368
369
370 void
371 DateIntervalInfo::parseSkeleton(const UnicodeString& skeleton,
372 int32_t* skeletonFieldWidth) {
373 const int8_t PATTERN_CHAR_BASE = 0x41;
374 int32_t i;
375 for ( i = 0; i < skeleton.length(); ++i ) {
376 // it is an ASCII char in skeleton
377 int8_t ch = (int8_t)skeleton.charAt(i);
378 ++skeletonFieldWidth[ch - PATTERN_CHAR_BASE];
379 }
380 }
381
382
383
384 UBool
385 DateIntervalInfo::stringNumeric(int32_t fieldWidth, int32_t anotherFieldWidth,
386 char patternLetter) {
387 if ( patternLetter == 'M' ) {
388 if ( (fieldWidth <= 2 && anotherFieldWidth > 2) ||
389 (fieldWidth > 2 && anotherFieldWidth <= 2 )) {
390 return true;
391 }
392 }
393 return false;
394 }
395
396
397
398 const UnicodeString*
399 DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton,
400 int8_t& bestMatchDistanceInfo) const {
401 #ifdef DTITVINF_DEBUG
402 char result[1000];
403 char result_1[1000];
404 char mesg[2000];
405 skeleton.extract(0, skeleton.length(), result, "UTF-8");
406 sprintf(mesg, "in getBestSkeleton: skeleton: %s; \n", result);
407 PRINTMESG(mesg)
408 #endif
409
410
411 int32_t inputSkeletonFieldWidth[] =
412 {
413 // A B C D E F G H I J K L M N O
414 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
415 // P Q R S T U V W X Y Z
416 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
417 // a b c d e f g h i j k l m n o
418 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
419 // p q r s t u v w x y z
420 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
421 };
422
423 int32_t skeletonFieldWidth[] =
424 {
425 // A B C D E F G H I J K L M N O
426 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
427 // P Q R S T U V W X Y Z
428 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
429 // a b c d e f g h i j k l m n o
430 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
431 // p q r s t u v w x y z
432 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
433 };
434
435 const int32_t DIFFERENT_FIELD = 0x1000;
436 const int32_t STRING_NUMERIC_DIFFERENCE = 0x100;
437 const int32_t BASE = 0x41;
438 const UChar CHAR_V = 0x0076;
439 const UChar CHAR_Z = 0x007A;
440
441 // hack for 'v' and 'z'.
442 // resource bundle only have time skeletons ending with 'v',
443 // but not for time skeletons ending with 'z'.
444 UBool replaceZWithV = false;
445 const UnicodeString* inputSkeleton = &skeleton;
446 UnicodeString copySkeleton;
447 if ( skeleton.indexOf(CHAR_Z) != -1 ) {
448 UChar zstr[2];
449 UChar vstr[2];
450 zstr[0]=CHAR_Z;
451 vstr[0]=CHAR_V;
452 zstr[1]=0;
453 vstr[1]=0;
454 copySkeleton = skeleton;
455 copySkeleton.findAndReplace(zstr, vstr);
456 inputSkeleton = &copySkeleton;
457 replaceZWithV = true;
458 }
459
460 parseSkeleton(*inputSkeleton, inputSkeletonFieldWidth);
461 int32_t bestDistance = MAX_POSITIVE_INT;
462 const UnicodeString* bestSkeleton = NULL;
463
464 // 0 means exact the same skeletons;
465 // 1 means having the same field, but with different length,
466 // 2 means only z/v differs
467 // -1 means having different field.
468 bestMatchDistanceInfo = 0;
469 int8_t fieldLength = sizeof(skeletonFieldWidth)/sizeof(skeletonFieldWidth[0]);
470
471 int32_t pos = -1;
472 const UHashElement* elem = NULL;
473 while ( (elem = fIntervalPatterns->nextElement(pos)) != NULL ) {
474 const UHashTok keyTok = elem->key;
475 UnicodeString* skeleton = (UnicodeString*)keyTok.pointer;
476 #ifdef DTITVINF_DEBUG
477 skeleton->extract(0, skeleton->length(), result, "UTF-8");
478 sprintf(mesg, "available skeletons: skeleton: %s; \n", result);
479 PRINTMESG(mesg)
480 #endif
481
482 // clear skeleton field width
483 int8_t i;
484 for ( i = 0; i < fieldLength; ++i ) {
485 skeletonFieldWidth[i] = 0;
486 }
487 parseSkeleton(*skeleton, skeletonFieldWidth);
488 // calculate distance
489 int32_t distance = 0;
490 int8_t fieldDifference = 1;
491 for ( i = 0; i < fieldLength; ++i ) {
492 int32_t inputFieldWidth = inputSkeletonFieldWidth[i];
493 int32_t fieldWidth = skeletonFieldWidth[i];
494 if ( inputFieldWidth == fieldWidth ) {
495 continue;
496 }
497 if ( inputFieldWidth == 0 ) {
498 fieldDifference = -1;
499 distance += DIFFERENT_FIELD;
500 } else if ( fieldWidth == 0 ) {
501 fieldDifference = -1;
502 distance += DIFFERENT_FIELD;
503 } else if (stringNumeric(inputFieldWidth, fieldWidth,
504 (char)(i+BASE) ) ) {
505 distance += STRING_NUMERIC_DIFFERENCE;
506 } else {
507 distance += (inputFieldWidth > fieldWidth) ?
508 (inputFieldWidth - fieldWidth) :
509 (fieldWidth - inputFieldWidth);
510 }
511 }
512 if ( distance < bestDistance ) {
513 bestSkeleton = skeleton;
514 bestDistance = distance;
515 bestMatchDistanceInfo = fieldDifference;
516 }
517 if ( distance == 0 ) {
518 bestMatchDistanceInfo = 0;
519 break;
520 }
521 }
522 if ( replaceZWithV && bestMatchDistanceInfo != -1 ) {
523 bestMatchDistanceInfo = 2;
524 }
525 return bestSkeleton;
526 }
527
528
529
530 DateIntervalInfo::IntervalPatternIndex
531 DateIntervalInfo::calendarFieldToIntervalIndex(UCalendarDateFields field,
532 UErrorCode& status) {
533 if ( U_FAILURE(status) ) {
534 return kIPI_MAX_INDEX;
535 }
536 IntervalPatternIndex index = kIPI_MAX_INDEX;
537 switch ( field ) {
538 case UCAL_ERA:
539 index = kIPI_ERA;
540 break;
541 case UCAL_YEAR:
542 index = kIPI_YEAR;
543 break;
544 case UCAL_MONTH:
545 index = kIPI_MONTH;
546 break;
547 case UCAL_DATE:
548 case UCAL_DAY_OF_WEEK:
549 //case UCAL_DAY_OF_MONTH:
550 index = kIPI_DATE;
551 break;
552 case UCAL_AM_PM:
553 index = kIPI_AM_PM;
554 break;
555 case UCAL_HOUR:
556 case UCAL_HOUR_OF_DAY:
557 index = kIPI_HOUR;
558 break;
559 case UCAL_MINUTE:
560 index = kIPI_MINUTE;
561 break;
562 default:
563 status = U_ILLEGAL_ARGUMENT_ERROR;
564 }
565 return index;
566 }
567
568
569
570 void
571 DateIntervalInfo::deleteHash(Hashtable* hTable)
572 {
573 if ( hTable == NULL ) {
574 return;
575 }
576 int32_t pos = -1;
577 const UHashElement* element = NULL;
578 while ( (element = hTable->nextElement(pos)) != NULL ) {
579 const UHashTok keyTok = element->key;
580 const UHashTok valueTok = element->value;
581 const UnicodeString* value = (UnicodeString*)valueTok.pointer;
582 delete[] value;
583 }
584 delete fIntervalPatterns;
585 }
586
587
588 U_CDECL_BEGIN
589
590 /**
591 * set hash table value comparator
592 *
593 * @param val1 one value in comparison
594 * @param val2 the other value in comparison
595 * @return TRUE if 2 values are the same, FALSE otherwise
596 */
597 static UBool U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2);
598
599 static UBool
600 U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2) {
601 const UnicodeString* pattern1 = (UnicodeString*)val1.pointer;
602 const UnicodeString* pattern2 = (UnicodeString*)val2.pointer;
603 UBool ret = TRUE;
604 int8_t i;
605 for ( i = 0; i < DateIntervalInfo::kMaxIntervalPatternIndex && ret == TRUE; ++i ) {
606 ret = (pattern1[i] == pattern2[i]);
607 }
608 return ret;
609 }
610
611 U_CDECL_END
612
613
614 Hashtable*
615 DateIntervalInfo::initHash(UErrorCode& status) {
616 if ( U_FAILURE(status) ) {
617 return NULL;
618 }
619 Hashtable* hTable;
620 if ( (hTable = new Hashtable(FALSE, status)) == NULL ) {
621 status = U_MEMORY_ALLOCATION_ERROR;
622 return NULL;
623 }
624 if ( U_FAILURE(status) ) {
625 delete hTable;
626 return NULL;
627 }
628 hTable->setValueComparator(dtitvinfHashTableValueComparator);
629 return hTable;
630 }
631
632
633 void
634 DateIntervalInfo::copyHash(const Hashtable* source,
635 Hashtable* target,
636 UErrorCode& status) {
637 if ( U_FAILURE(status) ) {
638 return;
639 }
640 int32_t pos = -1;
641 const UHashElement* element = NULL;
642 if ( source ) {
643 while ( (element = source->nextElement(pos)) != NULL ) {
644 const UHashTok keyTok = element->key;
645 const UnicodeString* key = (UnicodeString*)keyTok.pointer;
646 const UHashTok valueTok = element->value;
647 const UnicodeString* value = (UnicodeString*)valueTok.pointer;
648 UnicodeString* copy = new UnicodeString[kIPI_MAX_INDEX];
649 int8_t i;
650 for ( i = 0; i < kIPI_MAX_INDEX; ++i ) {
651 copy[i] = value[i];
652 }
653 target->put(UnicodeString(*key), copy, status);
654 if ( U_FAILURE(status) ) {
655 return;
656 }
657 }
658 }
659 }
660
661
662 U_NAMESPACE_END
663
664 #endif