Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 *   Copyright (C) 1996-2012, 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/udat.h"
     13 
     14 #include "unicode/uloc.h"
     15 #include "unicode/datefmt.h"
     16 #include "unicode/timezone.h"
     17 #include "unicode/smpdtfmt.h"
     18 #include "unicode/fieldpos.h"
     19 #include "unicode/parsepos.h"
     20 #include "unicode/calendar.h"
     21 #include "unicode/numfmt.h"
     22 #include "unicode/dtfmtsym.h"
     23 #include "unicode/ustring.h"
     24 #include "unicode/udisplaycontext.h"
     25 #include "cpputils.h"
     26 #include "reldtfmt.h"
     27 #include "umutex.h"
     28 
     29 U_NAMESPACE_USE
     30 
     31 /**
     32  * Verify that fmt is a SimpleDateFormat. Invalid error if not.
     33  * @param fmt the UDateFormat, definitely a DateFormat, maybe something else
     34  * @param status error code, will be set to failure if there is a familure or the fmt is NULL.
     35  */
     36 static void verifyIsSimpleDateFormat(const UDateFormat* fmt, UErrorCode *status) {
     37    if(U_SUCCESS(*status) &&
     38        dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) {
     39        *status = U_ILLEGAL_ARGUMENT_ERROR;
     40    }
     41 }
     42 
     43 // This mirrors the correspondence between the
     44 // SimpleDateFormat::fgPatternIndexToDateFormatField and
     45 // SimpleDateFormat::fgPatternIndexToCalendarField arrays.
     46 static UCalendarDateFields gDateFieldMapping[] = {
     47     UCAL_ERA,                  // UDAT_ERA_FIELD = 0
     48     UCAL_YEAR,                 // UDAT_YEAR_FIELD = 1
     49     UCAL_MONTH,                // UDAT_MONTH_FIELD = 2
     50     UCAL_DATE,                 // UDAT_DATE_FIELD = 3
     51     UCAL_HOUR_OF_DAY,          // UDAT_HOUR_OF_DAY1_FIELD = 4
     52     UCAL_HOUR_OF_DAY,          // UDAT_HOUR_OF_DAY0_FIELD = 5
     53     UCAL_MINUTE,               // UDAT_MINUTE_FIELD = 6
     54     UCAL_SECOND,               // UDAT_SECOND_FIELD = 7
     55     UCAL_MILLISECOND,          // UDAT_FRACTIONAL_SECOND_FIELD = 8
     56     UCAL_DAY_OF_WEEK,          // UDAT_DAY_OF_WEEK_FIELD = 9
     57     UCAL_DAY_OF_YEAR,          // UDAT_DAY_OF_YEAR_FIELD = 10
     58     UCAL_DAY_OF_WEEK_IN_MONTH, // UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11
     59     UCAL_WEEK_OF_YEAR,         // UDAT_WEEK_OF_YEAR_FIELD = 12
     60     UCAL_WEEK_OF_MONTH,        // UDAT_WEEK_OF_MONTH_FIELD = 13
     61     UCAL_AM_PM,                // UDAT_AM_PM_FIELD = 14
     62     UCAL_HOUR,                 // UDAT_HOUR1_FIELD = 15
     63     UCAL_HOUR,                 // UDAT_HOUR0_FIELD = 16
     64     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_FIELD = 17
     65     UCAL_YEAR_WOY,             // UDAT_YEAR_WOY_FIELD = 18
     66     UCAL_DOW_LOCAL,            // UDAT_DOW_LOCAL_FIELD = 19
     67     UCAL_EXTENDED_YEAR,        // UDAT_EXTENDED_YEAR_FIELD = 20
     68     UCAL_JULIAN_DAY,           // UDAT_JULIAN_DAY_FIELD = 21
     69     UCAL_MILLISECONDS_IN_DAY,  // UDAT_MILLISECONDS_IN_DAY_FIELD = 22
     70     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_RFC_FIELD = 23
     71     // UCAL_DST_OFFSET also
     72     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_GENERIC_FIELD = 24
     73     UCAL_DOW_LOCAL,            // UDAT_STANDALONE_DAY_FIELD = 25
     74     UCAL_MONTH,                // UDAT_STANDALONE_MONTH_FIELD = 26
     75     UCAL_MONTH,                // UDAT_QUARTER_FIELD = 27
     76     UCAL_MONTH,                // UDAT_STANDALONE_QUARTER_FIELD = 28
     77     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_SPECIAL_FIELD = 29
     78     UCAL_YEAR,                 // UDAT_YEAR_NAME_FIELD = 30
     79     UCAL_FIELD_COUNT,          // UDAT_FIELD_COUNT = 31
     80     // UCAL_IS_LEAP_MONTH is not the target of a mapping
     81 };
     82 
     83 U_CAPI UCalendarDateFields U_EXPORT2
     84 udat_toCalendarDateField(UDateFormatField field) {
     85   return gDateFieldMapping[field];
     86 }
     87 
     88 /* For now- one opener. */
     89 static UDateFormatOpener gOpener = NULL;
     90 
     91 U_INTERNAL void U_EXPORT2
     92 udat_registerOpener(UDateFormatOpener opener, UErrorCode *status)
     93 {
     94   if(U_FAILURE(*status)) return;
     95   umtx_lock(NULL);
     96   if(gOpener==NULL) {
     97     gOpener = opener;
     98   } else {
     99     *status = U_ILLEGAL_ARGUMENT_ERROR;
    100   }
    101   umtx_unlock(NULL);
    102 }
    103 
    104 U_INTERNAL UDateFormatOpener U_EXPORT2
    105 udat_unregisterOpener(UDateFormatOpener opener, UErrorCode *status)
    106 {
    107   if(U_FAILURE(*status)) return NULL;
    108   UDateFormatOpener oldOpener = NULL;
    109   umtx_lock(NULL);
    110   if(gOpener==NULL || gOpener!=opener) {
    111     *status = U_ILLEGAL_ARGUMENT_ERROR;
    112   } else {
    113     oldOpener=gOpener;
    114     gOpener=NULL;
    115   }
    116   umtx_unlock(NULL);
    117   return oldOpener;
    118 }
    119 
    120 
    121 
    122 U_CAPI UDateFormat* U_EXPORT2
    123 udat_open(UDateFormatStyle  timeStyle,
    124           UDateFormatStyle  dateStyle,
    125           const char        *locale,
    126           const UChar       *tzID,
    127           int32_t           tzIDLength,
    128           const UChar       *pattern,
    129           int32_t           patternLength,
    130           UErrorCode        *status)
    131 {
    132     DateFormat *fmt;
    133     if(U_FAILURE(*status)) {
    134         return 0;
    135     }
    136     if(gOpener!=NULL) { // if it's registered
    137       fmt = (DateFormat*) (*gOpener)(timeStyle,dateStyle,locale,tzID,tzIDLength,pattern,patternLength,status);
    138       if(fmt!=NULL) {
    139         return (UDateFormat*)fmt;
    140       } // else fall through.
    141     }
    142     if(timeStyle != UDAT_PATTERN) {
    143         if(locale == 0) {
    144             fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
    145                 (DateFormat::EStyle)timeStyle);
    146         }
    147         else {
    148             fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
    149                 (DateFormat::EStyle)timeStyle,
    150                 Locale(locale));
    151         }
    152     }
    153     else {
    154         UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength);
    155 
    156         if(locale == 0) {
    157             fmt = new SimpleDateFormat(pat, *status);
    158         }
    159         else {
    160             fmt = new SimpleDateFormat(pat, Locale(locale), *status);
    161         }
    162     }
    163 
    164     if(fmt == 0) {
    165         *status = U_MEMORY_ALLOCATION_ERROR;
    166         return 0;
    167     }
    168 
    169     if(tzID != 0) {
    170         TimeZone *zone = TimeZone::createTimeZone(UnicodeString((UBool)(tzIDLength == -1), tzID, tzIDLength));
    171         if(zone == 0) {
    172             *status = U_MEMORY_ALLOCATION_ERROR;
    173             delete fmt;
    174             return 0;
    175         }
    176         fmt->adoptTimeZone(zone);
    177     }
    178 
    179     return (UDateFormat*)fmt;
    180 }
    181 
    182 
    183 U_CAPI void U_EXPORT2
    184 udat_close(UDateFormat* format)
    185 {
    186     delete (DateFormat*)format;
    187 }
    188 
    189 U_CAPI UDateFormat* U_EXPORT2
    190 udat_clone(const UDateFormat *fmt,
    191        UErrorCode *status)
    192 {
    193     if(U_FAILURE(*status)) return 0;
    194 
    195     Format *res = ((DateFormat*)fmt)->clone();
    196 
    197     if(res == 0) {
    198         *status = U_MEMORY_ALLOCATION_ERROR;
    199         return 0;
    200     }
    201 
    202     return (UDateFormat*) res;
    203 }
    204 
    205 U_CAPI int32_t U_EXPORT2
    206 udat_format(    const    UDateFormat*    format,
    207         UDate           dateToFormat,
    208         UChar*          result,
    209         int32_t         resultLength,
    210         UFieldPosition* position,
    211         UErrorCode*     status)
    212 {
    213     if(U_FAILURE(*status)) return -1;
    214 
    215     UnicodeString res;
    216     if(!(result==NULL && resultLength==0)) {
    217         // NULL destination for pure preflighting: empty dummy string
    218         // otherwise, alias the destination buffer
    219         res.setTo(result, 0, resultLength);
    220     }
    221 
    222     FieldPosition fp;
    223 
    224     if(position != 0)
    225         fp.setField(position->field);
    226 
    227     ((DateFormat*)format)->format(dateToFormat, res, fp);
    228 
    229     if(position != 0) {
    230         position->beginIndex = fp.getBeginIndex();
    231         position->endIndex = fp.getEndIndex();
    232     }
    233 
    234     return res.extract(result, resultLength, *status);
    235 }
    236 
    237 U_CAPI UDate U_EXPORT2
    238 udat_parse(    const    UDateFormat*        format,
    239         const    UChar*          text,
    240         int32_t         textLength,
    241         int32_t         *parsePos,
    242         UErrorCode      *status)
    243 {
    244     if(U_FAILURE(*status)) return (UDate)0;
    245 
    246     const UnicodeString src((UBool)(textLength == -1), text, textLength);
    247     ParsePosition pp;
    248     int32_t stackParsePos = 0;
    249     UDate res;
    250 
    251     if(parsePos == NULL) {
    252         parsePos = &stackParsePos;
    253     }
    254 
    255     pp.setIndex(*parsePos);
    256 
    257     res = ((DateFormat*)format)->parse(src, pp);
    258 
    259     if(pp.getErrorIndex() == -1)
    260         *parsePos = pp.getIndex();
    261     else {
    262         *parsePos = pp.getErrorIndex();
    263         *status = U_PARSE_ERROR;
    264     }
    265 
    266     return res;
    267 }
    268 
    269 U_CAPI void U_EXPORT2
    270 udat_parseCalendar(const    UDateFormat*    format,
    271                             UCalendar*      calendar,
    272                    const    UChar*          text,
    273                             int32_t         textLength,
    274                             int32_t         *parsePos,
    275                             UErrorCode      *status)
    276 {
    277     if(U_FAILURE(*status)) return;
    278 
    279     const UnicodeString src((UBool)(textLength == -1), text, textLength);
    280     ParsePosition pp;
    281 
    282     if(parsePos != 0)
    283         pp.setIndex(*parsePos);
    284 
    285     ((DateFormat*)format)->parse(src, *(Calendar*)calendar, pp);
    286 
    287     if(parsePos != 0) {
    288         if(pp.getErrorIndex() == -1)
    289             *parsePos = pp.getIndex();
    290         else {
    291             *parsePos = pp.getErrorIndex();
    292             *status = U_PARSE_ERROR;
    293         }
    294     }
    295 }
    296 
    297 U_CAPI UBool U_EXPORT2
    298 udat_isLenient(const UDateFormat* fmt)
    299 {
    300     return ((DateFormat*)fmt)->isLenient();
    301 }
    302 
    303 U_CAPI void U_EXPORT2
    304 udat_setLenient(    UDateFormat*    fmt,
    305             UBool          isLenient)
    306 {
    307     ((DateFormat*)fmt)->setLenient(isLenient);
    308 }
    309 
    310 U_CAPI const UCalendar* U_EXPORT2
    311 udat_getCalendar(const UDateFormat* fmt)
    312 {
    313     return (const UCalendar*) ((DateFormat*)fmt)->getCalendar();
    314 }
    315 
    316 U_CAPI void U_EXPORT2
    317 udat_setCalendar(UDateFormat*    fmt,
    318                  const   UCalendar*      calendarToSet)
    319 {
    320     ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet));
    321 }
    322 
    323 U_CAPI const UNumberFormat* U_EXPORT2
    324 udat_getNumberFormat(const UDateFormat* fmt)
    325 {
    326     return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat();
    327 }
    328 
    329 U_CAPI void U_EXPORT2
    330 udat_setNumberFormat(UDateFormat*    fmt,
    331                      const   UNumberFormat*  numberFormatToSet)
    332 {
    333     ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet));
    334 }
    335 
    336 U_CAPI const char* U_EXPORT2
    337 udat_getAvailable(int32_t index)
    338 {
    339     return uloc_getAvailable(index);
    340 }
    341 
    342 U_CAPI int32_t U_EXPORT2
    343 udat_countAvailable()
    344 {
    345     return uloc_countAvailable();
    346 }
    347 
    348 U_CAPI UDate U_EXPORT2
    349 udat_get2DigitYearStart(    const   UDateFormat     *fmt,
    350                         UErrorCode      *status)
    351 {
    352     verifyIsSimpleDateFormat(fmt, status);
    353     if(U_FAILURE(*status)) return (UDate)0;
    354     return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status);
    355 }
    356 
    357 U_CAPI void U_EXPORT2
    358 udat_set2DigitYearStart(    UDateFormat     *fmt,
    359                         UDate           d,
    360                         UErrorCode      *status)
    361 {
    362     verifyIsSimpleDateFormat(fmt, status);
    363     if(U_FAILURE(*status)) return;
    364     ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status);
    365 }
    366 
    367 U_CAPI int32_t U_EXPORT2
    368 udat_toPattern(    const   UDateFormat     *fmt,
    369         UBool          localized,
    370         UChar           *result,
    371         int32_t         resultLength,
    372         UErrorCode      *status)
    373 {
    374     if(U_FAILURE(*status)) return -1;
    375 
    376     UnicodeString res;
    377     if(!(result==NULL && resultLength==0)) {
    378         // NULL destination for pure preflighting: empty dummy string
    379         // otherwise, alias the destination buffer
    380         res.setTo(result, 0, resultLength);
    381     }
    382 
    383     const DateFormat *df=reinterpret_cast<const DateFormat *>(fmt);
    384     const SimpleDateFormat *sdtfmt=dynamic_cast<const SimpleDateFormat *>(df);
    385     const RelativeDateFormat *reldtfmt;
    386     if (sdtfmt!=NULL) {
    387         if(localized)
    388             sdtfmt->toLocalizedPattern(res, *status);
    389         else
    390             sdtfmt->toPattern(res);
    391     } else if (!localized && (reldtfmt=dynamic_cast<const RelativeDateFormat *>(df))!=NULL) {
    392         reldtfmt->toPattern(res, *status);
    393     } else {
    394         *status = U_ILLEGAL_ARGUMENT_ERROR;
    395         return -1;
    396     }
    397 
    398     return res.extract(result, resultLength, *status);
    399 }
    400 
    401 // TODO: should this take an UErrorCode?
    402 // A: Yes. Of course.
    403 U_CAPI void U_EXPORT2
    404 udat_applyPattern(  UDateFormat     *format,
    405                     UBool          localized,
    406                     const   UChar           *pattern,
    407                     int32_t         patternLength)
    408 {
    409     const UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength);
    410     UErrorCode status = U_ZERO_ERROR;
    411 
    412     verifyIsSimpleDateFormat(format, &status);
    413     if(U_FAILURE(status)) {
    414         return;
    415     }
    416 
    417     if(localized)
    418         ((SimpleDateFormat*)format)->applyLocalizedPattern(pat, status);
    419     else
    420         ((SimpleDateFormat*)format)->applyPattern(pat);
    421 }
    422 
    423 U_CAPI int32_t U_EXPORT2
    424 udat_getSymbols(const   UDateFormat     *fmt,
    425                 UDateFormatSymbolType   type,
    426                 int32_t                 index,
    427                 UChar                   *result,
    428                 int32_t                 resultLength,
    429                 UErrorCode              *status)
    430 {
    431     const DateFormatSymbols *syms;
    432     const SimpleDateFormat* sdtfmt;
    433     const RelativeDateFormat* rdtfmt;
    434     if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
    435     	syms = sdtfmt->getDateFormatSymbols();
    436     } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
    437     	syms = rdtfmt->getDateFormatSymbols();
    438     } else {
    439         return -1;
    440     }
    441     int32_t count;
    442     const UnicodeString *res = NULL;
    443 
    444     switch(type) {
    445     case UDAT_ERAS:
    446         res = syms->getEras(count);
    447         break;
    448 
    449     case UDAT_ERA_NAMES:
    450         res = syms->getEraNames(count);
    451         break;
    452 
    453     case UDAT_MONTHS:
    454         res = syms->getMonths(count);
    455         break;
    456 
    457     case UDAT_SHORT_MONTHS:
    458         res = syms->getShortMonths(count);
    459         break;
    460 
    461     case UDAT_WEEKDAYS:
    462         res = syms->getWeekdays(count);
    463         break;
    464 
    465     case UDAT_SHORT_WEEKDAYS:
    466         res = syms->getShortWeekdays(count);
    467         break;
    468 
    469     case UDAT_AM_PMS:
    470         res = syms->getAmPmStrings(count);
    471         break;
    472 
    473     case UDAT_LOCALIZED_CHARS:
    474         {
    475             UnicodeString res1;
    476             if(!(result==NULL && resultLength==0)) {
    477                 // NULL destination for pure preflighting: empty dummy string
    478                 // otherwise, alias the destination buffer
    479                 res1.setTo(result, 0, resultLength);
    480             }
    481             syms->getLocalPatternChars(res1);
    482             return res1.extract(result, resultLength, *status);
    483         }
    484 
    485     case UDAT_NARROW_MONTHS:
    486         res = syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    487         break;
    488 
    489     case UDAT_NARROW_WEEKDAYS:
    490         res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    491         break;
    492 
    493     case UDAT_STANDALONE_MONTHS:
    494         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    495         break;
    496 
    497     case UDAT_STANDALONE_SHORT_MONTHS:
    498         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    499         break;
    500 
    501     case UDAT_STANDALONE_NARROW_MONTHS:
    502         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    503         break;
    504 
    505     case UDAT_STANDALONE_WEEKDAYS:
    506         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    507         break;
    508 
    509     case UDAT_STANDALONE_SHORT_WEEKDAYS:
    510         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    511         break;
    512 
    513     case UDAT_STANDALONE_NARROW_WEEKDAYS:
    514         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    515         break;
    516 
    517     case UDAT_QUARTERS:
    518         res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    519         break;
    520 
    521     case UDAT_SHORT_QUARTERS:
    522         res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
    523         break;
    524 
    525     case UDAT_STANDALONE_QUARTERS:
    526         res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    527         break;
    528 
    529     case UDAT_STANDALONE_SHORT_QUARTERS:
    530         res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    531         break;
    532 
    533     }
    534 
    535     if(index < count) {
    536         return res[index].extract(result, resultLength, *status);
    537     }
    538     return 0;
    539 }
    540 
    541 // TODO: also needs an errorCode.
    542 U_CAPI int32_t U_EXPORT2
    543 udat_countSymbols(    const    UDateFormat                *fmt,
    544             UDateFormatSymbolType    type)
    545 {
    546     const DateFormatSymbols *syms;
    547     const SimpleDateFormat* sdtfmt;
    548     const RelativeDateFormat* rdtfmt;
    549     if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
    550     	syms = sdtfmt->getDateFormatSymbols();
    551     } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
    552     	syms = rdtfmt->getDateFormatSymbols();
    553     } else {
    554         return 0;
    555     }
    556     int32_t count = 0;
    557 
    558     switch(type) {
    559     case UDAT_ERAS:
    560         syms->getEras(count);
    561         break;
    562 
    563     case UDAT_MONTHS:
    564         syms->getMonths(count);
    565         break;
    566 
    567     case UDAT_SHORT_MONTHS:
    568         syms->getShortMonths(count);
    569         break;
    570 
    571     case UDAT_WEEKDAYS:
    572         syms->getWeekdays(count);
    573         break;
    574 
    575     case UDAT_SHORT_WEEKDAYS:
    576         syms->getShortWeekdays(count);
    577         break;
    578 
    579     case UDAT_AM_PMS:
    580         syms->getAmPmStrings(count);
    581         break;
    582 
    583     case UDAT_LOCALIZED_CHARS:
    584         count = 1;
    585         break;
    586 
    587     case UDAT_ERA_NAMES:
    588         syms->getEraNames(count);
    589         break;
    590 
    591     case UDAT_NARROW_MONTHS:
    592         syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    593         break;
    594 
    595     case UDAT_NARROW_WEEKDAYS:
    596         syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    597         break;
    598 
    599     case UDAT_STANDALONE_MONTHS:
    600         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    601         break;
    602 
    603     case UDAT_STANDALONE_SHORT_MONTHS:
    604         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    605         break;
    606 
    607     case UDAT_STANDALONE_NARROW_MONTHS:
    608         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    609         break;
    610 
    611     case UDAT_STANDALONE_WEEKDAYS:
    612         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    613         break;
    614 
    615     case UDAT_STANDALONE_SHORT_WEEKDAYS:
    616         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    617         break;
    618 
    619     case UDAT_STANDALONE_NARROW_WEEKDAYS:
    620         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    621         break;
    622 
    623     case UDAT_QUARTERS:
    624         syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    625         break;
    626 
    627     case UDAT_SHORT_QUARTERS:
    628         syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
    629         break;
    630 
    631     case UDAT_STANDALONE_QUARTERS:
    632         syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    633         break;
    634 
    635     case UDAT_STANDALONE_SHORT_QUARTERS:
    636         syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    637         break;
    638 
    639     }
    640 
    641     return count;
    642 }
    643 
    644 U_NAMESPACE_BEGIN
    645 
    646 /*
    647  * This DateFormatSymbolsSingleSetter class is a friend of DateFormatSymbols
    648  * solely for the purpose of avoiding to clone the array of strings
    649  * just to modify one of them and then setting all of them back.
    650  * For example, the old code looked like this:
    651  *  case UDAT_MONTHS:
    652  *    res = syms->getMonths(count);
    653  *    array = new UnicodeString[count];
    654  *    if(array == 0) {
    655  *      *status = U_MEMORY_ALLOCATION_ERROR;
    656  *      return;
    657  *    }
    658  *    uprv_arrayCopy(res, array, count);
    659  *    if(index < count)
    660  *      array[index] = val;
    661  *    syms->setMonths(array, count);
    662  *    break;
    663  *
    664  * Even worse, the old code actually cloned the entire DateFormatSymbols object,
    665  * cloned one value array, changed one value, and then made the SimpleDateFormat
    666  * replace its DateFormatSymbols object with the new one.
    667  *
    668  * markus 2002-oct-14
    669  */
    670 class DateFormatSymbolsSingleSetter /* not : public UObject because all methods are static */ {
    671 public:
    672     static void
    673         setSymbol(UnicodeString *array, int32_t count, int32_t index,
    674         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    675     {
    676         if(array!=NULL) {
    677             if(index>=count) {
    678                 errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
    679             } else if(value==NULL) {
    680                 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
    681             } else {
    682                 array[index].setTo(value, valueLength);
    683             }
    684         }
    685     }
    686 
    687     static void
    688         setEra(DateFormatSymbols *syms, int32_t index,
    689         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    690     {
    691         setSymbol(syms->fEras, syms->fErasCount, index, value, valueLength, errorCode);
    692     }
    693 
    694     static void
    695         setEraName(DateFormatSymbols *syms, int32_t index,
    696         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    697     {
    698         setSymbol(syms->fEraNames, syms->fEraNamesCount, index, value, valueLength, errorCode);
    699     }
    700 
    701     static void
    702         setMonth(DateFormatSymbols *syms, int32_t index,
    703         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    704     {
    705         setSymbol(syms->fMonths, syms->fMonthsCount, index, value, valueLength, errorCode);
    706     }
    707 
    708     static void
    709         setShortMonth(DateFormatSymbols *syms, int32_t index,
    710         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    711     {
    712         setSymbol(syms->fShortMonths, syms->fShortMonthsCount, index, value, valueLength, errorCode);
    713     }
    714 
    715     static void
    716         setNarrowMonth(DateFormatSymbols *syms, int32_t index,
    717         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    718     {
    719         setSymbol(syms->fNarrowMonths, syms->fNarrowMonthsCount, index, value, valueLength, errorCode);
    720     }
    721 
    722     static void
    723         setStandaloneMonth(DateFormatSymbols *syms, int32_t index,
    724         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    725     {
    726         setSymbol(syms->fStandaloneMonths, syms->fStandaloneMonthsCount, index, value, valueLength, errorCode);
    727     }
    728 
    729     static void
    730         setStandaloneShortMonth(DateFormatSymbols *syms, int32_t index,
    731         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    732     {
    733         setSymbol(syms->fStandaloneShortMonths, syms->fStandaloneShortMonthsCount, index, value, valueLength, errorCode);
    734     }
    735 
    736     static void
    737         setStandaloneNarrowMonth(DateFormatSymbols *syms, int32_t index,
    738         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    739     {
    740         setSymbol(syms->fStandaloneNarrowMonths, syms->fStandaloneNarrowMonthsCount, index, value, valueLength, errorCode);
    741     }
    742 
    743     static void
    744         setWeekday(DateFormatSymbols *syms, int32_t index,
    745         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    746     {
    747         setSymbol(syms->fWeekdays, syms->fWeekdaysCount, index, value, valueLength, errorCode);
    748     }
    749 
    750     static void
    751         setShortWeekday(DateFormatSymbols *syms, int32_t index,
    752         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    753     {
    754         setSymbol(syms->fShortWeekdays, syms->fShortWeekdaysCount, index, value, valueLength, errorCode);
    755     }
    756 
    757     static void
    758         setNarrowWeekday(DateFormatSymbols *syms, int32_t index,
    759         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    760     {
    761         setSymbol(syms->fNarrowWeekdays, syms->fNarrowWeekdaysCount, index, value, valueLength, errorCode);
    762     }
    763 
    764     static void
    765         setStandaloneWeekday(DateFormatSymbols *syms, int32_t index,
    766         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    767     {
    768         setSymbol(syms->fStandaloneWeekdays, syms->fStandaloneWeekdaysCount, index, value, valueLength, errorCode);
    769     }
    770 
    771     static void
    772         setStandaloneShortWeekday(DateFormatSymbols *syms, int32_t index,
    773         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    774     {
    775         setSymbol(syms->fStandaloneShortWeekdays, syms->fStandaloneShortWeekdaysCount, index, value, valueLength, errorCode);
    776     }
    777 
    778     static void
    779         setStandaloneNarrowWeekday(DateFormatSymbols *syms, int32_t index,
    780         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    781     {
    782         setSymbol(syms->fStandaloneNarrowWeekdays, syms->fStandaloneNarrowWeekdaysCount, index, value, valueLength, errorCode);
    783     }
    784 
    785     static void
    786         setQuarter(DateFormatSymbols *syms, int32_t index,
    787         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    788     {
    789         setSymbol(syms->fQuarters, syms->fQuartersCount, index, value, valueLength, errorCode);
    790     }
    791 
    792     static void
    793         setShortQuarter(DateFormatSymbols *syms, int32_t index,
    794         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    795     {
    796         setSymbol(syms->fShortQuarters, syms->fShortQuartersCount, index, value, valueLength, errorCode);
    797     }
    798 
    799     static void
    800         setStandaloneQuarter(DateFormatSymbols *syms, int32_t index,
    801         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    802     {
    803         setSymbol(syms->fStandaloneQuarters, syms->fStandaloneQuartersCount, index, value, valueLength, errorCode);
    804     }
    805 
    806     static void
    807         setStandaloneShortQuarter(DateFormatSymbols *syms, int32_t index,
    808         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    809     {
    810         setSymbol(syms->fStandaloneShortQuarters, syms->fStandaloneShortQuartersCount, index, value, valueLength, errorCode);
    811     }
    812 
    813     static void
    814         setAmPm(DateFormatSymbols *syms, int32_t index,
    815         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    816     {
    817         setSymbol(syms->fAmPms, syms->fAmPmsCount, index, value, valueLength, errorCode);
    818     }
    819 
    820     static void
    821         setLocalPatternChars(DateFormatSymbols *syms,
    822         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    823     {
    824         setSymbol(&syms->fLocalPatternChars, 1, 0, value, valueLength, errorCode);
    825     }
    826 };
    827 
    828 U_NAMESPACE_END
    829 
    830 U_CAPI void U_EXPORT2
    831 udat_setSymbols(    UDateFormat             *format,
    832             UDateFormatSymbolType   type,
    833             int32_t                 index,
    834             UChar                   *value,
    835             int32_t                 valueLength,
    836             UErrorCode              *status)
    837 {
    838     verifyIsSimpleDateFormat(format, status);
    839     if(U_FAILURE(*status)) return;
    840 
    841     DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols();
    842 
    843     switch(type) {
    844     case UDAT_ERAS:
    845         DateFormatSymbolsSingleSetter::setEra(syms, index, value, valueLength, *status);
    846         break;
    847 
    848     case UDAT_ERA_NAMES:
    849         DateFormatSymbolsSingleSetter::setEraName(syms, index, value, valueLength, *status);
    850         break;
    851 
    852     case UDAT_MONTHS:
    853         DateFormatSymbolsSingleSetter::setMonth(syms, index, value, valueLength, *status);
    854         break;
    855 
    856     case UDAT_SHORT_MONTHS:
    857         DateFormatSymbolsSingleSetter::setShortMonth(syms, index, value, valueLength, *status);
    858         break;
    859 
    860     case UDAT_NARROW_MONTHS:
    861         DateFormatSymbolsSingleSetter::setNarrowMonth(syms, index, value, valueLength, *status);
    862         break;
    863 
    864     case UDAT_STANDALONE_MONTHS:
    865         DateFormatSymbolsSingleSetter::setStandaloneMonth(syms, index, value, valueLength, *status);
    866         break;
    867 
    868     case UDAT_STANDALONE_SHORT_MONTHS:
    869         DateFormatSymbolsSingleSetter::setStandaloneShortMonth(syms, index, value, valueLength, *status);
    870         break;
    871 
    872     case UDAT_STANDALONE_NARROW_MONTHS:
    873         DateFormatSymbolsSingleSetter::setStandaloneNarrowMonth(syms, index, value, valueLength, *status);
    874         break;
    875 
    876     case UDAT_WEEKDAYS:
    877         DateFormatSymbolsSingleSetter::setWeekday(syms, index, value, valueLength, *status);
    878         break;
    879 
    880     case UDAT_SHORT_WEEKDAYS:
    881         DateFormatSymbolsSingleSetter::setShortWeekday(syms, index, value, valueLength, *status);
    882         break;
    883 
    884     case UDAT_NARROW_WEEKDAYS:
    885         DateFormatSymbolsSingleSetter::setNarrowWeekday(syms, index, value, valueLength, *status);
    886         break;
    887 
    888     case UDAT_STANDALONE_WEEKDAYS:
    889         DateFormatSymbolsSingleSetter::setStandaloneWeekday(syms, index, value, valueLength, *status);
    890         break;
    891 
    892     case UDAT_STANDALONE_SHORT_WEEKDAYS:
    893         DateFormatSymbolsSingleSetter::setStandaloneShortWeekday(syms, index, value, valueLength, *status);
    894         break;
    895 
    896     case UDAT_STANDALONE_NARROW_WEEKDAYS:
    897         DateFormatSymbolsSingleSetter::setStandaloneNarrowWeekday(syms, index, value, valueLength, *status);
    898         break;
    899 
    900     case UDAT_QUARTERS:
    901         DateFormatSymbolsSingleSetter::setQuarter(syms, index, value, valueLength, *status);
    902         break;
    903 
    904     case UDAT_SHORT_QUARTERS:
    905         DateFormatSymbolsSingleSetter::setShortQuarter(syms, index, value, valueLength, *status);
    906         break;
    907 
    908     case UDAT_STANDALONE_QUARTERS:
    909         DateFormatSymbolsSingleSetter::setStandaloneQuarter(syms, index, value, valueLength, *status);
    910         break;
    911 
    912     case UDAT_STANDALONE_SHORT_QUARTERS:
    913         DateFormatSymbolsSingleSetter::setStandaloneShortQuarter(syms, index, value, valueLength, *status);
    914         break;
    915 
    916     case UDAT_AM_PMS:
    917         DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status);
    918         break;
    919 
    920     case UDAT_LOCALIZED_CHARS:
    921         DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status);
    922         break;
    923 
    924     default:
    925         *status = U_UNSUPPORTED_ERROR;
    926         break;
    927 
    928     }
    929 }
    930 
    931 U_CAPI const char* U_EXPORT2
    932 udat_getLocaleByType(const UDateFormat *fmt,
    933                      ULocDataLocaleType type,
    934                      UErrorCode* status)
    935 {
    936     if (fmt == NULL) {
    937         if (U_SUCCESS(*status)) {
    938             *status = U_ILLEGAL_ARGUMENT_ERROR;
    939         }
    940         return NULL;
    941     }
    942     return ((Format*)fmt)->getLocaleID(type, *status);
    943 }
    944 
    945 
    946 U_CAPI void U_EXPORT2
    947 udat_setContext(UDateFormat* fmt, UDisplayContext value, UErrorCode* status)
    948 {
    949     verifyIsSimpleDateFormat(fmt, status);
    950     if (U_FAILURE(*status)) {
    951         return;
    952     }
    953     ((SimpleDateFormat*)fmt)->setContext(value, *status);
    954 }
    955 
    956 U_CAPI UDisplayContext U_EXPORT2
    957 udat_getContext(UDateFormat* fmt, UDisplayContextType type, UErrorCode* status)
    958 {
    959     verifyIsSimpleDateFormat(fmt, status);
    960     if (U_FAILURE(*status)) {
    961         return (UDisplayContext)0;
    962     }
    963     return ((SimpleDateFormat*)fmt)->getContext(type, *status);
    964 }
    965 
    966 
    967 /**
    968  * Verify that fmt is a RelativeDateFormat. Invalid error if not.
    969  * @param fmt the UDateFormat, definitely a DateFormat, maybe something else
    970  * @param status error code, will be set to failure if there is a familure or the fmt is NULL.
    971  */
    972 static void verifyIsRelativeDateFormat(const UDateFormat* fmt, UErrorCode *status) {
    973    if(U_SUCCESS(*status) &&
    974        dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) {
    975        *status = U_ILLEGAL_ARGUMENT_ERROR;
    976    }
    977 }
    978 
    979 
    980 U_CAPI int32_t U_EXPORT2
    981 udat_toPatternRelativeDate(const UDateFormat *fmt,
    982                            UChar             *result,
    983                            int32_t           resultLength,
    984                            UErrorCode        *status)
    985 {
    986     verifyIsRelativeDateFormat(fmt, status);
    987     if(U_FAILURE(*status)) return -1;
    988 
    989     UnicodeString datePattern;
    990     if(!(result==NULL && resultLength==0)) {
    991         // NULL destination for pure preflighting: empty dummy string
    992         // otherwise, alias the destination buffer
    993         datePattern.setTo(result, 0, resultLength);
    994     }
    995     ((RelativeDateFormat*)fmt)->toPatternDate(datePattern, *status);
    996     return datePattern.extract(result, resultLength, *status);
    997 }
    998 
    999 U_CAPI int32_t U_EXPORT2
   1000 udat_toPatternRelativeTime(const UDateFormat *fmt,
   1001                            UChar             *result,
   1002                            int32_t           resultLength,
   1003                            UErrorCode        *status)
   1004 {
   1005     verifyIsRelativeDateFormat(fmt, status);
   1006     if(U_FAILURE(*status)) return -1;
   1007 
   1008     UnicodeString timePattern;
   1009     if(!(result==NULL && resultLength==0)) {
   1010         // NULL destination for pure preflighting: empty dummy string
   1011         // otherwise, alias the destination buffer
   1012         timePattern.setTo(result, 0, resultLength);
   1013     }
   1014     ((RelativeDateFormat*)fmt)->toPatternTime(timePattern, *status);
   1015     return timePattern.extract(result, resultLength, *status);
   1016 }
   1017 
   1018 U_CAPI void U_EXPORT2
   1019 udat_applyPatternRelative(UDateFormat *format,
   1020                           const UChar *datePattern,
   1021                           int32_t     datePatternLength,
   1022                           const UChar *timePattern,
   1023                           int32_t     timePatternLength,
   1024                           UErrorCode  *status)
   1025 {
   1026     verifyIsRelativeDateFormat(format, status);
   1027     if(U_FAILURE(*status)) return;
   1028     const UnicodeString datePat((UBool)(datePatternLength == -1), datePattern, datePatternLength);
   1029     const UnicodeString timePat((UBool)(timePatternLength == -1), timePattern, timePatternLength);
   1030     ((RelativeDateFormat*)format)->applyPatterns(datePat, timePat, *status);
   1031 }
   1032 
   1033 #endif /* #if !UCONFIG_NO_FORMATTING */
   1034