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