OLD | NEW |
(Empty) | |
| 1 /* |
| 2 ******************************************************************************* |
| 3 * Copyright (C) 1996-2010, International Business Machines |
| 4 * Corporation and others. All Rights Reserved. |
| 5 ******************************************************************************* |
| 6 */ |
| 7 |
| 8 #include <typeinfo> // for 'typeid' to work |
| 9 |
| 10 #include "unicode/utypes.h" |
| 11 |
| 12 #if !UCONFIG_NO_FORMATTING |
| 13 |
| 14 #include "unicode/ucal.h" |
| 15 #include "unicode/uloc.h" |
| 16 #include "unicode/calendar.h" |
| 17 #include "unicode/timezone.h" |
| 18 #include "unicode/gregocal.h" |
| 19 #include "unicode/simpletz.h" |
| 20 #include "unicode/ustring.h" |
| 21 #include "unicode/strenum.h" |
| 22 #include "cmemory.h" |
| 23 #include "cstring.h" |
| 24 #include "ustrenum.h" |
| 25 #include "uenumimp.h" |
| 26 #include "ulist.h" |
| 27 |
| 28 U_NAMESPACE_USE |
| 29 |
| 30 static TimeZone* |
| 31 _createTimeZone(const UChar* zoneID, int32_t len, UErrorCode* ec) { |
| 32 TimeZone* zone = NULL; |
| 33 if (ec!=NULL && U_SUCCESS(*ec)) { |
| 34 // Note that if zoneID is invalid, we get back GMT. This odd |
| 35 // behavior is by design and goes back to the JDK. The only |
| 36 // failure we will see is a memory allocation failure. |
| 37 int32_t l = (len<0 ? u_strlen(zoneID) : len); |
| 38 UnicodeString zoneStrID; |
| 39 zoneStrID.setTo((UBool)(len < 0), zoneID, l); /* temporary read-only ali
as */ |
| 40 zone = TimeZone::createTimeZone(zoneStrID); |
| 41 if (zone == NULL) { |
| 42 *ec = U_MEMORY_ALLOCATION_ERROR; |
| 43 } |
| 44 } |
| 45 return zone; |
| 46 } |
| 47 |
| 48 U_CAPI UEnumeration* U_EXPORT2 |
| 49 ucal_openTimeZones(UErrorCode* ec) { |
| 50 return uenum_openFromStringEnumeration(TimeZone::createEnumeration(), ec); |
| 51 } |
| 52 |
| 53 U_CAPI UEnumeration* U_EXPORT2 |
| 54 ucal_openCountryTimeZones(const char* country, UErrorCode* ec) { |
| 55 return uenum_openFromStringEnumeration(TimeZone::createEnumeration(country),
ec); |
| 56 } |
| 57 |
| 58 U_CAPI int32_t U_EXPORT2 |
| 59 ucal_getDefaultTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* ec) { |
| 60 int32_t len = 0; |
| 61 if (ec!=NULL && U_SUCCESS(*ec)) { |
| 62 TimeZone* zone = TimeZone::createDefault(); |
| 63 if (zone == NULL) { |
| 64 *ec = U_MEMORY_ALLOCATION_ERROR; |
| 65 } else { |
| 66 UnicodeString id; |
| 67 zone->getID(id); |
| 68 delete zone; |
| 69 len = id.extract(result, resultCapacity, *ec); |
| 70 } |
| 71 } |
| 72 return len; |
| 73 } |
| 74 |
| 75 U_CAPI void U_EXPORT2 |
| 76 ucal_setDefaultTimeZone(const UChar* zoneID, UErrorCode* ec) { |
| 77 TimeZone* zone = _createTimeZone(zoneID, -1, ec); |
| 78 if (zone != NULL) { |
| 79 TimeZone::adoptDefault(zone); |
| 80 } |
| 81 } |
| 82 |
| 83 U_CAPI int32_t U_EXPORT2 |
| 84 ucal_getDSTSavings(const UChar* zoneID, UErrorCode* ec) { |
| 85 int32_t result = 0; |
| 86 TimeZone* zone = _createTimeZone(zoneID, -1, ec); |
| 87 if (U_SUCCESS(*ec)) { |
| 88 SimpleTimeZone* stz = dynamic_cast<SimpleTimeZone*>(zone); |
| 89 if (stz != NULL) { |
| 90 result = stz->getDSTSavings(); |
| 91 } else { |
| 92 // Since there is no getDSTSavings on TimeZone, we use a |
| 93 // heuristic: Starting with the current time, march |
| 94 // forwards for one year, looking for DST savings. |
| 95 // Stepping by weeks is sufficient. |
| 96 UDate d = Calendar::getNow(); |
| 97 for (int32_t i=0; i<53; ++i, d+=U_MILLIS_PER_DAY*7.0) { |
| 98 int32_t raw, dst; |
| 99 zone->getOffset(d, FALSE, raw, dst, *ec); |
| 100 if (U_FAILURE(*ec)) { |
| 101 break; |
| 102 } else if (dst != 0) { |
| 103 result = dst; |
| 104 break; |
| 105 } |
| 106 } |
| 107 } |
| 108 } |
| 109 delete zone; |
| 110 return result; |
| 111 } |
| 112 |
| 113 U_CAPI UDate U_EXPORT2 |
| 114 ucal_getNow() |
| 115 { |
| 116 |
| 117 return Calendar::getNow(); |
| 118 } |
| 119 |
| 120 #define ULOC_LOCALE_IDENTIFIER_CAPACITY (ULOC_FULLNAME_CAPACITY + 1 + ULOC_KEYWO
RD_AND_VALUES_CAPACITY) |
| 121 |
| 122 U_CAPI UCalendar* U_EXPORT2 |
| 123 ucal_open( const UChar* zoneID, |
| 124 int32_t len, |
| 125 const char* locale, |
| 126 UCalendarType caltype, |
| 127 UErrorCode* status) |
| 128 { |
| 129 |
| 130 if(U_FAILURE(*status)) return 0; |
| 131 |
| 132 TimeZone* zone = (zoneID==NULL) ? TimeZone::createDefault() |
| 133 : _createTimeZone(zoneID, len, status); |
| 134 |
| 135 if (U_FAILURE(*status)) { |
| 136 return NULL; |
| 137 } |
| 138 |
| 139 if ( caltype == UCAL_GREGORIAN ) { |
| 140 char localeBuf[ULOC_LOCALE_IDENTIFIER_CAPACITY]; |
| 141 if ( locale == NULL ) { |
| 142 locale = uloc_getDefault(); |
| 143 } |
| 144 uprv_strncpy(localeBuf, locale, ULOC_LOCALE_IDENTIFIER_CAPACITY); |
| 145 uloc_setKeywordValue("calendar", "gregorian", localeBuf, ULOC_LOCALE_IDENT
IFIER_CAPACITY, status); |
| 146 if (U_FAILURE(*status)) { |
| 147 return NULL; |
| 148 } |
| 149 return (UCalendar*)Calendar::createInstance(zone, Locale(localeBuf), *stat
us); |
| 150 } |
| 151 return (UCalendar*)Calendar::createInstance(zone, Locale(locale), *status); |
| 152 } |
| 153 |
| 154 U_CAPI void U_EXPORT2 |
| 155 ucal_close(UCalendar *cal) |
| 156 { |
| 157 |
| 158 delete (Calendar*) cal; |
| 159 } |
| 160 |
| 161 U_CAPI UCalendar* U_EXPORT2 |
| 162 ucal_clone(const UCalendar* cal, |
| 163 UErrorCode* status) |
| 164 { |
| 165 if(U_FAILURE(*status)) return 0; |
| 166 |
| 167 Calendar* res = ((Calendar*)cal)->clone(); |
| 168 |
| 169 if(res == 0) { |
| 170 *status = U_MEMORY_ALLOCATION_ERROR; |
| 171 return 0; |
| 172 } |
| 173 |
| 174 return (UCalendar*) res; |
| 175 } |
| 176 |
| 177 U_CAPI void U_EXPORT2 |
| 178 ucal_setTimeZone( UCalendar* cal, |
| 179 const UChar* zoneID, |
| 180 int32_t len, |
| 181 UErrorCode *status) |
| 182 { |
| 183 |
| 184 if(U_FAILURE(*status)) |
| 185 return; |
| 186 |
| 187 TimeZone* zone = (zoneID==NULL) ? TimeZone::createDefault() |
| 188 : _createTimeZone(zoneID, len, status); |
| 189 |
| 190 if (zone != NULL) { |
| 191 ((Calendar*)cal)->adoptTimeZone(zone); |
| 192 } |
| 193 } |
| 194 |
| 195 U_CAPI int32_t U_EXPORT2 |
| 196 ucal_getTimeZoneDisplayName(const UCalendar* cal, |
| 197 UCalendarDisplayNameType type, |
| 198 const char *locale, |
| 199 UChar* result, |
| 200 int32_t resultLength, |
| 201 UErrorCode* status) |
| 202 { |
| 203 |
| 204 if(U_FAILURE(*status)) return -1; |
| 205 |
| 206 const TimeZone& tz = ((Calendar*)cal)->getTimeZone(); |
| 207 UnicodeString id; |
| 208 if(!(result==NULL && resultLength==0)) { |
| 209 // NULL destination for pure preflighting: empty dummy string |
| 210 // otherwise, alias the destination buffer |
| 211 id.setTo(result, 0, resultLength); |
| 212 } |
| 213 |
| 214 switch(type) { |
| 215 case UCAL_STANDARD: |
| 216 tz.getDisplayName(FALSE, TimeZone::LONG, Locale(locale), id); |
| 217 break; |
| 218 |
| 219 case UCAL_SHORT_STANDARD: |
| 220 tz.getDisplayName(FALSE, TimeZone::SHORT, Locale(locale), id); |
| 221 break; |
| 222 |
| 223 case UCAL_DST: |
| 224 tz.getDisplayName(TRUE, TimeZone::LONG, Locale(locale), id); |
| 225 break; |
| 226 |
| 227 case UCAL_SHORT_DST: |
| 228 tz.getDisplayName(TRUE, TimeZone::SHORT, Locale(locale), id); |
| 229 break; |
| 230 } |
| 231 |
| 232 return id.extract(result, resultLength, *status); |
| 233 } |
| 234 |
| 235 U_CAPI UBool U_EXPORT2 |
| 236 ucal_inDaylightTime( const UCalendar* cal, |
| 237 UErrorCode* status ) |
| 238 { |
| 239 |
| 240 if(U_FAILURE(*status)) return (UBool) -1; |
| 241 return ((Calendar*)cal)->inDaylightTime(*status); |
| 242 } |
| 243 |
| 244 U_CAPI void U_EXPORT2 |
| 245 ucal_setGregorianChange(UCalendar *cal, UDate date, UErrorCode *pErrorCode) { |
| 246 if(U_FAILURE(*pErrorCode)) { |
| 247 return; |
| 248 } |
| 249 Calendar *cpp_cal = (Calendar *)cal; |
| 250 GregorianCalendar *gregocal = dynamic_cast<GregorianCalendar *>(cpp_cal); |
| 251 // Not if(gregocal == NULL) { |
| 252 // because we really want to work only with a GregorianCalendar, not with |
| 253 // its subclasses like BuddhistCalendar. |
| 254 if(typeid(*cpp_cal) != typeid(GregorianCalendar)) { |
| 255 *pErrorCode = U_UNSUPPORTED_ERROR; |
| 256 return; |
| 257 } |
| 258 gregocal->setGregorianChange(date, *pErrorCode); |
| 259 } |
| 260 |
| 261 U_CAPI UDate U_EXPORT2 |
| 262 ucal_getGregorianChange(const UCalendar *cal, UErrorCode *pErrorCode) { |
| 263 if(U_FAILURE(*pErrorCode)) { |
| 264 return (UDate)0; |
| 265 } |
| 266 const Calendar *cpp_cal = (const Calendar *)cal; |
| 267 const GregorianCalendar *gregocal = dynamic_cast<const GregorianCalendar *>(
cpp_cal); |
| 268 // Not if(gregocal == NULL) { |
| 269 // see comments in ucal_setGregorianChange(). |
| 270 if(typeid(*cpp_cal) != typeid(GregorianCalendar)) { |
| 271 *pErrorCode = U_UNSUPPORTED_ERROR; |
| 272 return (UDate)0; |
| 273 } |
| 274 return gregocal->getGregorianChange(); |
| 275 } |
| 276 |
| 277 U_CAPI int32_t U_EXPORT2 |
| 278 ucal_getAttribute( const UCalendar* cal, |
| 279 UCalendarAttribute attr) |
| 280 { |
| 281 |
| 282 switch(attr) { |
| 283 case UCAL_LENIENT: |
| 284 return ((Calendar*)cal)->isLenient(); |
| 285 |
| 286 case UCAL_FIRST_DAY_OF_WEEK: |
| 287 return ((Calendar*)cal)->getFirstDayOfWeek(); |
| 288 |
| 289 case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK: |
| 290 return ((Calendar*)cal)->getMinimalDaysInFirstWeek(); |
| 291 |
| 292 default: |
| 293 break; |
| 294 } |
| 295 return -1; |
| 296 } |
| 297 |
| 298 U_CAPI void U_EXPORT2 |
| 299 ucal_setAttribute( UCalendar* cal, |
| 300 UCalendarAttribute attr, |
| 301 int32_t newValue) |
| 302 { |
| 303 |
| 304 switch(attr) { |
| 305 case UCAL_LENIENT: |
| 306 ((Calendar*)cal)->setLenient((UBool)newValue); |
| 307 break; |
| 308 |
| 309 case UCAL_FIRST_DAY_OF_WEEK: |
| 310 ((Calendar*)cal)->setFirstDayOfWeek((UCalendarDaysOfWeek)newValue); |
| 311 break; |
| 312 |
| 313 case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK: |
| 314 ((Calendar*)cal)->setMinimalDaysInFirstWeek((uint8_t)newValue); |
| 315 break; |
| 316 } |
| 317 } |
| 318 |
| 319 U_CAPI const char* U_EXPORT2 |
| 320 ucal_getAvailable(int32_t index) |
| 321 { |
| 322 |
| 323 return uloc_getAvailable(index); |
| 324 } |
| 325 |
| 326 U_CAPI int32_t U_EXPORT2 |
| 327 ucal_countAvailable() |
| 328 { |
| 329 |
| 330 return uloc_countAvailable(); |
| 331 } |
| 332 |
| 333 U_CAPI UDate U_EXPORT2 |
| 334 ucal_getMillis( const UCalendar* cal, |
| 335 UErrorCode* status) |
| 336 { |
| 337 |
| 338 if(U_FAILURE(*status)) return (UDate) 0; |
| 339 |
| 340 return ((Calendar*)cal)->getTime(*status); |
| 341 } |
| 342 |
| 343 U_CAPI void U_EXPORT2 |
| 344 ucal_setMillis( UCalendar* cal, |
| 345 UDate dateTime, |
| 346 UErrorCode* status ) |
| 347 { |
| 348 if(U_FAILURE(*status)) return; |
| 349 |
| 350 ((Calendar*)cal)->setTime(dateTime, *status); |
| 351 } |
| 352 |
| 353 // TBD: why does this take an UErrorCode? |
| 354 U_CAPI void U_EXPORT2 |
| 355 ucal_setDate( UCalendar* cal, |
| 356 int32_t year, |
| 357 int32_t month, |
| 358 int32_t date, |
| 359 UErrorCode *status) |
| 360 { |
| 361 |
| 362 if(U_FAILURE(*status)) return; |
| 363 |
| 364 ((Calendar*)cal)->set(year, month, date); |
| 365 } |
| 366 |
| 367 // TBD: why does this take an UErrorCode? |
| 368 U_CAPI void U_EXPORT2 |
| 369 ucal_setDateTime( UCalendar* cal, |
| 370 int32_t year, |
| 371 int32_t month, |
| 372 int32_t date, |
| 373 int32_t hour, |
| 374 int32_t minute, |
| 375 int32_t second, |
| 376 UErrorCode *status) |
| 377 { |
| 378 if(U_FAILURE(*status)) return; |
| 379 |
| 380 ((Calendar*)cal)->set(year, month, date, hour, minute, second); |
| 381 } |
| 382 |
| 383 U_CAPI UBool U_EXPORT2 |
| 384 ucal_equivalentTo( const UCalendar* cal1, |
| 385 const UCalendar* cal2) |
| 386 { |
| 387 |
| 388 return ((Calendar*)cal1)->isEquivalentTo(*((Calendar*)cal2)); |
| 389 } |
| 390 |
| 391 U_CAPI void U_EXPORT2 |
| 392 ucal_add( UCalendar* cal, |
| 393 UCalendarDateFields field, |
| 394 int32_t amount, |
| 395 UErrorCode* status) |
| 396 { |
| 397 |
| 398 if(U_FAILURE(*status)) return; |
| 399 |
| 400 ((Calendar*)cal)->add(field, amount, *status); |
| 401 } |
| 402 |
| 403 U_CAPI void U_EXPORT2 |
| 404 ucal_roll( UCalendar* cal, |
| 405 UCalendarDateFields field, |
| 406 int32_t amount, |
| 407 UErrorCode* status) |
| 408 { |
| 409 |
| 410 if(U_FAILURE(*status)) return; |
| 411 |
| 412 ((Calendar*)cal)->roll(field, amount, *status); |
| 413 } |
| 414 |
| 415 U_CAPI int32_t U_EXPORT2 |
| 416 ucal_get( const UCalendar* cal, |
| 417 UCalendarDateFields field, |
| 418 UErrorCode* status ) |
| 419 { |
| 420 |
| 421 if(U_FAILURE(*status)) return -1; |
| 422 |
| 423 return ((Calendar*)cal)->get(field, *status); |
| 424 } |
| 425 |
| 426 U_CAPI void U_EXPORT2 |
| 427 ucal_set( UCalendar* cal, |
| 428 UCalendarDateFields field, |
| 429 int32_t value) |
| 430 { |
| 431 |
| 432 ((Calendar*)cal)->set(field, value); |
| 433 } |
| 434 |
| 435 U_CAPI UBool U_EXPORT2 |
| 436 ucal_isSet( const UCalendar* cal, |
| 437 UCalendarDateFields field) |
| 438 { |
| 439 |
| 440 return ((Calendar*)cal)->isSet(field); |
| 441 } |
| 442 |
| 443 U_CAPI void U_EXPORT2 |
| 444 ucal_clearField( UCalendar* cal, |
| 445 UCalendarDateFields field) |
| 446 { |
| 447 |
| 448 ((Calendar*)cal)->clear(field); |
| 449 } |
| 450 |
| 451 U_CAPI void U_EXPORT2 |
| 452 ucal_clear(UCalendar* calendar) |
| 453 { |
| 454 |
| 455 ((Calendar*)calendar)->clear(); |
| 456 } |
| 457 |
| 458 U_CAPI int32_t U_EXPORT2 |
| 459 ucal_getLimit( const UCalendar* cal, |
| 460 UCalendarDateFields field, |
| 461 UCalendarLimitType type, |
| 462 UErrorCode *status) |
| 463 { |
| 464 |
| 465 if(status==0 || U_FAILURE(*status)) { |
| 466 return -1; |
| 467 } |
| 468 |
| 469 switch(type) { |
| 470 case UCAL_MINIMUM: |
| 471 return ((Calendar*)cal)->getMinimum(field); |
| 472 |
| 473 case UCAL_MAXIMUM: |
| 474 return ((Calendar*)cal)->getMaximum(field); |
| 475 |
| 476 case UCAL_GREATEST_MINIMUM: |
| 477 return ((Calendar*)cal)->getGreatestMinimum(field); |
| 478 |
| 479 case UCAL_LEAST_MAXIMUM: |
| 480 return ((Calendar*)cal)->getLeastMaximum(field); |
| 481 |
| 482 case UCAL_ACTUAL_MINIMUM: |
| 483 return ((Calendar*)cal)->getActualMinimum(field, |
| 484 *status); |
| 485 |
| 486 case UCAL_ACTUAL_MAXIMUM: |
| 487 return ((Calendar*)cal)->getActualMaximum(field, |
| 488 *status); |
| 489 |
| 490 default: |
| 491 break; |
| 492 } |
| 493 return -1; |
| 494 } |
| 495 |
| 496 U_CAPI const char * U_EXPORT2 |
| 497 ucal_getLocaleByType(const UCalendar *cal, ULocDataLocaleType type, UErrorCode*
status) |
| 498 { |
| 499 if (cal == NULL) { |
| 500 if (U_SUCCESS(*status)) { |
| 501 *status = U_ILLEGAL_ARGUMENT_ERROR; |
| 502 } |
| 503 return NULL; |
| 504 } |
| 505 return ((Calendar*)cal)->getLocaleID(type, *status); |
| 506 } |
| 507 |
| 508 U_CAPI const char * U_EXPORT2 |
| 509 ucal_getTZDataVersion(UErrorCode* status) |
| 510 { |
| 511 return TimeZone::getTZDataVersion(*status); |
| 512 } |
| 513 |
| 514 U_CAPI int32_t U_EXPORT2 |
| 515 ucal_getCanonicalTimeZoneID(const UChar* id, int32_t len, |
| 516 UChar* result, int32_t resultCapacity, UBool *isSyst
emID, UErrorCode* status) { |
| 517 if(status == 0 || U_FAILURE(*status)) { |
| 518 return 0; |
| 519 } |
| 520 if (isSystemID) { |
| 521 *isSystemID = FALSE; |
| 522 } |
| 523 if (id == 0 || len == 0 || result == 0 || resultCapacity <= 0) { |
| 524 *status = U_ILLEGAL_ARGUMENT_ERROR; |
| 525 return 0; |
| 526 } |
| 527 int32_t reslen = 0; |
| 528 UnicodeString canonical; |
| 529 UBool systemID = FALSE; |
| 530 TimeZone::getCanonicalID(UnicodeString(id, len), canonical, systemID, *statu
s); |
| 531 if (U_SUCCESS(*status)) { |
| 532 if (isSystemID) { |
| 533 *isSystemID = systemID; |
| 534 } |
| 535 reslen = canonical.extract(result, resultCapacity, *status); |
| 536 } |
| 537 return reslen; |
| 538 } |
| 539 |
| 540 U_CAPI const char * U_EXPORT2 |
| 541 ucal_getType(const UCalendar *cal, UErrorCode* status) |
| 542 { |
| 543 if (U_FAILURE(*status)) { |
| 544 return NULL; |
| 545 } |
| 546 return ((Calendar*)cal)->getType(); |
| 547 } |
| 548 |
| 549 U_CAPI UCalendarWeekdayType U_EXPORT2 |
| 550 ucal_getDayOfWeekType(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErro
rCode* status) |
| 551 { |
| 552 if (U_FAILURE(*status)) { |
| 553 return UCAL_WEEKDAY; |
| 554 } |
| 555 return ((Calendar*)cal)->getDayOfWeekType(dayOfWeek, *status); |
| 556 } |
| 557 |
| 558 U_CAPI int32_t U_EXPORT2 |
| 559 ucal_getWeekendTransition(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, U
ErrorCode *status) |
| 560 { |
| 561 if (U_FAILURE(*status)) { |
| 562 return 0; |
| 563 } |
| 564 return ((Calendar*)cal)->getWeekendTransition(dayOfWeek, *status); |
| 565 } |
| 566 |
| 567 U_CAPI UBool U_EXPORT2 |
| 568 ucal_isWeekend(const UCalendar *cal, UDate date, UErrorCode *status) |
| 569 { |
| 570 if (U_FAILURE(*status)) { |
| 571 return FALSE; |
| 572 } |
| 573 return ((Calendar*)cal)->isWeekend(date, *status); |
| 574 } |
| 575 |
| 576 |
| 577 static const UEnumeration defaultKeywordValues = { |
| 578 NULL, |
| 579 NULL, |
| 580 ulist_close_keyword_values_iterator, |
| 581 ulist_count_keyword_values, |
| 582 uenum_unextDefault, |
| 583 ulist_next_keyword_value, |
| 584 ulist_reset_keyword_values_iterator |
| 585 }; |
| 586 |
| 587 static const char * const CAL_TYPES[] = { |
| 588 "gregorian", |
| 589 "japanese", |
| 590 "buddhist", |
| 591 "roc", |
| 592 "persian", |
| 593 "islamic-civil", |
| 594 "islamic", |
| 595 "hebrew", |
| 596 "chinese", |
| 597 "indian", |
| 598 "coptic", |
| 599 "ethiopic", |
| 600 "ethiopic-amete-alem", |
| 601 NULL |
| 602 }; |
| 603 |
| 604 U_CAPI UEnumeration* U_EXPORT2 |
| 605 ucal_getKeywordValuesForLocale(const char * /* key */, const char* locale, UBool
commonlyUsed, UErrorCode *status) { |
| 606 // Resolve region |
| 607 char prefRegion[ULOC_FULLNAME_CAPACITY] = ""; |
| 608 int32_t prefRegionLength = 0; |
| 609 prefRegionLength = uloc_getCountry(locale, prefRegion, sizeof(prefRegion), s
tatus); |
| 610 if (prefRegionLength == 0) { |
| 611 char loc[ULOC_FULLNAME_CAPACITY] = ""; |
| 612 int32_t locLength = 0; |
| 613 locLength = uloc_addLikelySubtags(locale, loc, sizeof(loc), status); |
| 614 |
| 615 prefRegionLength = uloc_getCountry(loc, prefRegion, sizeof(prefRegion),
status); |
| 616 } |
| 617 |
| 618 // Read preferred calendar values from supplementalData calendarPreference |
| 619 UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", status); |
| 620 ures_getByKey(rb, "calendarPreferenceData", rb, status); |
| 621 UResourceBundle *order = ures_getByKey(rb, prefRegion, NULL, status); |
| 622 if (*status == U_MISSING_RESOURCE_ERROR && rb != NULL) { |
| 623 *status = U_ZERO_ERROR; |
| 624 order = ures_getByKey(rb, "001", NULL, status); |
| 625 } |
| 626 |
| 627 // Create a list of calendar type strings |
| 628 UList *values = NULL; |
| 629 if (U_SUCCESS(*status)) { |
| 630 values = ulist_createEmptyList(status); |
| 631 if (U_SUCCESS(*status)) { |
| 632 for (int i = 0; i < ures_getSize(order); i++) { |
| 633 int32_t len; |
| 634 const UChar *type = ures_getStringByIndex(order, i, &len, status
); |
| 635 char *caltype = (char*)uprv_malloc(len + 1); |
| 636 if (caltype == NULL) { |
| 637 *status = U_MEMORY_ALLOCATION_ERROR; |
| 638 break; |
| 639 } |
| 640 u_UCharsToChars(type, caltype, len); |
| 641 *(caltype + len) = 0; |
| 642 |
| 643 ulist_addItemEndList(values, caltype, TRUE, status); |
| 644 if (U_FAILURE(*status)) { |
| 645 break; |
| 646 } |
| 647 } |
| 648 |
| 649 if (U_SUCCESS(*status) && !commonlyUsed) { |
| 650 // If not commonlyUsed, add other available values |
| 651 for (int32_t i = 0; CAL_TYPES[i] != NULL; i++) { |
| 652 if (!ulist_containsString(values, CAL_TYPES[i], (int32_t)upr
v_strlen(CAL_TYPES[i]))) { |
| 653 ulist_addItemEndList(values, CAL_TYPES[i], FALSE, status
); |
| 654 if (U_FAILURE(*status)) { |
| 655 break; |
| 656 } |
| 657 } |
| 658 } |
| 659 } |
| 660 if (U_FAILURE(*status)) { |
| 661 ulist_deleteList(values); |
| 662 values = NULL; |
| 663 } |
| 664 } |
| 665 } |
| 666 |
| 667 ures_close(order); |
| 668 ures_close(rb); |
| 669 |
| 670 if (U_FAILURE(*status) || values == NULL) { |
| 671 return NULL; |
| 672 } |
| 673 |
| 674 // Create string enumeration |
| 675 UEnumeration *en = (UEnumeration*)uprv_malloc(sizeof(UEnumeration)); |
| 676 if (en == NULL) { |
| 677 *status = U_MEMORY_ALLOCATION_ERROR; |
| 678 ulist_deleteList(values); |
| 679 return NULL; |
| 680 } |
| 681 ulist_resetList(values); |
| 682 memcpy(en, &defaultKeywordValues, sizeof(UEnumeration)); |
| 683 en->context = values; |
| 684 return en; |
| 685 } |
| 686 |
| 687 #endif /* #if !UCONFIG_NO_FORMATTING */ |
OLD | NEW |