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