Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 *   Copyright (C) 1996-2013, 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_SHORTER_WEEKDAYS:
    490         res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::SHORT);
    491         break;
    492 
    493     case UDAT_NARROW_WEEKDAYS:
    494         res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    495         break;
    496 
    497     case UDAT_STANDALONE_MONTHS:
    498         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    499         break;
    500 
    501     case UDAT_STANDALONE_SHORT_MONTHS:
    502         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    503         break;
    504 
    505     case UDAT_STANDALONE_NARROW_MONTHS:
    506         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    507         break;
    508 
    509     case UDAT_STANDALONE_WEEKDAYS:
    510         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    511         break;
    512 
    513     case UDAT_STANDALONE_SHORT_WEEKDAYS:
    514         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    515         break;
    516 
    517     case UDAT_STANDALONE_SHORTER_WEEKDAYS:
    518         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::SHORT);
    519         break;
    520 
    521     case UDAT_STANDALONE_NARROW_WEEKDAYS:
    522         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    523         break;
    524 
    525     case UDAT_QUARTERS:
    526         res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    527         break;
    528 
    529     case UDAT_SHORT_QUARTERS:
    530         res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
    531         break;
    532 
    533     case UDAT_STANDALONE_QUARTERS:
    534         res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    535         break;
    536 
    537     case UDAT_STANDALONE_SHORT_QUARTERS:
    538         res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    539         break;
    540 
    541     }
    542 
    543     if(index < count) {
    544         return res[index].extract(result, resultLength, *status);
    545     }
    546     return 0;
    547 }
    548 
    549 // TODO: also needs an errorCode.
    550 U_CAPI int32_t U_EXPORT2
    551 udat_countSymbols(    const    UDateFormat                *fmt,
    552             UDateFormatSymbolType    type)
    553 {
    554     const DateFormatSymbols *syms;
    555     const SimpleDateFormat* sdtfmt;
    556     const RelativeDateFormat* rdtfmt;
    557     if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
    558         syms = sdtfmt->getDateFormatSymbols();
    559     } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
    560         syms = rdtfmt->getDateFormatSymbols();
    561     } else {
    562         return 0;
    563     }
    564     int32_t count = 0;
    565 
    566     switch(type) {
    567     case UDAT_ERAS:
    568         syms->getEras(count);
    569         break;
    570 
    571     case UDAT_MONTHS:
    572         syms->getMonths(count);
    573         break;
    574 
    575     case UDAT_SHORT_MONTHS:
    576         syms->getShortMonths(count);
    577         break;
    578 
    579     case UDAT_WEEKDAYS:
    580         syms->getWeekdays(count);
    581         break;
    582 
    583     case UDAT_SHORT_WEEKDAYS:
    584         syms->getShortWeekdays(count);
    585         break;
    586 
    587     case UDAT_AM_PMS:
    588         syms->getAmPmStrings(count);
    589         break;
    590 
    591     case UDAT_LOCALIZED_CHARS:
    592         count = 1;
    593         break;
    594 
    595     case UDAT_ERA_NAMES:
    596         syms->getEraNames(count);
    597         break;
    598 
    599     case UDAT_NARROW_MONTHS:
    600         syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    601         break;
    602 
    603     case UDAT_SHORTER_WEEKDAYS:
    604         syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::SHORT);
    605         break;
    606 
    607     case UDAT_NARROW_WEEKDAYS:
    608         syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    609         break;
    610 
    611     case UDAT_STANDALONE_MONTHS:
    612         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    613         break;
    614 
    615     case UDAT_STANDALONE_SHORT_MONTHS:
    616         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    617         break;
    618 
    619     case UDAT_STANDALONE_NARROW_MONTHS:
    620         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    621         break;
    622 
    623     case UDAT_STANDALONE_WEEKDAYS:
    624         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    625         break;
    626 
    627     case UDAT_STANDALONE_SHORT_WEEKDAYS:
    628         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    629         break;
    630 
    631     case UDAT_STANDALONE_SHORTER_WEEKDAYS:
    632         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::SHORT);
    633         break;
    634 
    635     case UDAT_STANDALONE_NARROW_WEEKDAYS:
    636         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    637         break;
    638 
    639     case UDAT_QUARTERS:
    640         syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    641         break;
    642 
    643     case UDAT_SHORT_QUARTERS:
    644         syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
    645         break;
    646 
    647     case UDAT_STANDALONE_QUARTERS:
    648         syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    649         break;
    650 
    651     case UDAT_STANDALONE_SHORT_QUARTERS:
    652         syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    653         break;
    654 
    655     }
    656 
    657     return count;
    658 }
    659 
    660 U_NAMESPACE_BEGIN
    661 
    662 /*
    663  * This DateFormatSymbolsSingleSetter class is a friend of DateFormatSymbols
    664  * solely for the purpose of avoiding to clone the array of strings
    665  * just to modify one of them and then setting all of them back.
    666  * For example, the old code looked like this:
    667  *  case UDAT_MONTHS:
    668  *    res = syms->getMonths(count);
    669  *    array = new UnicodeString[count];
    670  *    if(array == 0) {
    671  *      *status = U_MEMORY_ALLOCATION_ERROR;
    672  *      return;
    673  *    }
    674  *    uprv_arrayCopy(res, array, count);
    675  *    if(index < count)
    676  *      array[index] = val;
    677  *    syms->setMonths(array, count);
    678  *    break;
    679  *
    680  * Even worse, the old code actually cloned the entire DateFormatSymbols object,
    681  * cloned one value array, changed one value, and then made the SimpleDateFormat
    682  * replace its DateFormatSymbols object with the new one.
    683  *
    684  * markus 2002-oct-14
    685  */
    686 class DateFormatSymbolsSingleSetter /* not : public UObject because all methods are static */ {
    687 public:
    688     static void
    689         setSymbol(UnicodeString *array, int32_t count, int32_t index,
    690         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    691     {
    692         if(array!=NULL) {
    693             if(index>=count) {
    694                 errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
    695             } else if(value==NULL) {
    696                 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
    697             } else {
    698                 array[index].setTo(value, valueLength);
    699             }
    700         }
    701     }
    702 
    703     static void
    704         setEra(DateFormatSymbols *syms, int32_t index,
    705         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    706     {
    707         setSymbol(syms->fEras, syms->fErasCount, index, value, valueLength, errorCode);
    708     }
    709 
    710     static void
    711         setEraName(DateFormatSymbols *syms, int32_t index,
    712         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    713     {
    714         setSymbol(syms->fEraNames, syms->fEraNamesCount, index, value, valueLength, errorCode);
    715     }
    716 
    717     static void
    718         setMonth(DateFormatSymbols *syms, int32_t index,
    719         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    720     {
    721         setSymbol(syms->fMonths, syms->fMonthsCount, index, value, valueLength, errorCode);
    722     }
    723 
    724     static void
    725         setShortMonth(DateFormatSymbols *syms, int32_t index,
    726         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    727     {
    728         setSymbol(syms->fShortMonths, syms->fShortMonthsCount, index, value, valueLength, errorCode);
    729     }
    730 
    731     static void
    732         setNarrowMonth(DateFormatSymbols *syms, int32_t index,
    733         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    734     {
    735         setSymbol(syms->fNarrowMonths, syms->fNarrowMonthsCount, index, value, valueLength, errorCode);
    736     }
    737 
    738     static void
    739         setStandaloneMonth(DateFormatSymbols *syms, int32_t index,
    740         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    741     {
    742         setSymbol(syms->fStandaloneMonths, syms->fStandaloneMonthsCount, index, value, valueLength, errorCode);
    743     }
    744 
    745     static void
    746         setStandaloneShortMonth(DateFormatSymbols *syms, int32_t index,
    747         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    748     {
    749         setSymbol(syms->fStandaloneShortMonths, syms->fStandaloneShortMonthsCount, index, value, valueLength, errorCode);
    750     }
    751 
    752     static void
    753         setStandaloneNarrowMonth(DateFormatSymbols *syms, int32_t index,
    754         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    755     {
    756         setSymbol(syms->fStandaloneNarrowMonths, syms->fStandaloneNarrowMonthsCount, index, value, valueLength, errorCode);
    757     }
    758 
    759     static void
    760         setWeekday(DateFormatSymbols *syms, int32_t index,
    761         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    762     {
    763         setSymbol(syms->fWeekdays, syms->fWeekdaysCount, index, value, valueLength, errorCode);
    764     }
    765 
    766     static void
    767         setShortWeekday(DateFormatSymbols *syms, int32_t index,
    768         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    769     {
    770         setSymbol(syms->fShortWeekdays, syms->fShortWeekdaysCount, index, value, valueLength, errorCode);
    771     }
    772 
    773     static void
    774         setShorterWeekday(DateFormatSymbols *syms, int32_t index,
    775         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    776     {
    777         setSymbol(syms->fShorterWeekdays, syms->fShorterWeekdaysCount, index, value, valueLength, errorCode);
    778     }
    779 
    780     static void
    781         setNarrowWeekday(DateFormatSymbols *syms, int32_t index,
    782         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    783     {
    784         setSymbol(syms->fNarrowWeekdays, syms->fNarrowWeekdaysCount, index, value, valueLength, errorCode);
    785     }
    786 
    787     static void
    788         setStandaloneWeekday(DateFormatSymbols *syms, int32_t index,
    789         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    790     {
    791         setSymbol(syms->fStandaloneWeekdays, syms->fStandaloneWeekdaysCount, index, value, valueLength, errorCode);
    792     }
    793 
    794     static void
    795         setStandaloneShortWeekday(DateFormatSymbols *syms, int32_t index,
    796         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    797     {
    798         setSymbol(syms->fStandaloneShortWeekdays, syms->fStandaloneShortWeekdaysCount, index, value, valueLength, errorCode);
    799     }
    800 
    801     static void
    802         setStandaloneShorterWeekday(DateFormatSymbols *syms, int32_t index,
    803         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    804     {
    805         setSymbol(syms->fStandaloneShorterWeekdays, syms->fStandaloneShorterWeekdaysCount, index, value, valueLength, errorCode);
    806     }
    807 
    808     static void
    809         setStandaloneNarrowWeekday(DateFormatSymbols *syms, int32_t index,
    810         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    811     {
    812         setSymbol(syms->fStandaloneNarrowWeekdays, syms->fStandaloneNarrowWeekdaysCount, index, value, valueLength, errorCode);
    813     }
    814 
    815     static void
    816         setQuarter(DateFormatSymbols *syms, int32_t index,
    817         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    818     {
    819         setSymbol(syms->fQuarters, syms->fQuartersCount, index, value, valueLength, errorCode);
    820     }
    821 
    822     static void
    823         setShortQuarter(DateFormatSymbols *syms, int32_t index,
    824         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    825     {
    826         setSymbol(syms->fShortQuarters, syms->fShortQuartersCount, index, value, valueLength, errorCode);
    827     }
    828 
    829     static void
    830         setStandaloneQuarter(DateFormatSymbols *syms, int32_t index,
    831         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    832     {
    833         setSymbol(syms->fStandaloneQuarters, syms->fStandaloneQuartersCount, index, value, valueLength, errorCode);
    834     }
    835 
    836     static void
    837         setStandaloneShortQuarter(DateFormatSymbols *syms, int32_t index,
    838         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    839     {
    840         setSymbol(syms->fStandaloneShortQuarters, syms->fStandaloneShortQuartersCount, index, value, valueLength, errorCode);
    841     }
    842 
    843     static void
    844         setAmPm(DateFormatSymbols *syms, int32_t index,
    845         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    846     {
    847         setSymbol(syms->fAmPms, syms->fAmPmsCount, index, value, valueLength, errorCode);
    848     }
    849 
    850     static void
    851         setLocalPatternChars(DateFormatSymbols *syms,
    852         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
    853     {
    854         setSymbol(&syms->fLocalPatternChars, 1, 0, value, valueLength, errorCode);
    855     }
    856 };
    857 
    858 U_NAMESPACE_END
    859 
    860 U_CAPI void U_EXPORT2
    861 udat_setSymbols(    UDateFormat             *format,
    862             UDateFormatSymbolType   type,
    863             int32_t                 index,
    864             UChar                   *value,
    865             int32_t                 valueLength,
    866             UErrorCode              *status)
    867 {
    868     verifyIsSimpleDateFormat(format, status);
    869     if(U_FAILURE(*status)) return;
    870 
    871     DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols();
    872 
    873     switch(type) {
    874     case UDAT_ERAS:
    875         DateFormatSymbolsSingleSetter::setEra(syms, index, value, valueLength, *status);
    876         break;
    877 
    878     case UDAT_ERA_NAMES:
    879         DateFormatSymbolsSingleSetter::setEraName(syms, index, value, valueLength, *status);
    880         break;
    881 
    882     case UDAT_MONTHS:
    883         DateFormatSymbolsSingleSetter::setMonth(syms, index, value, valueLength, *status);
    884         break;
    885 
    886     case UDAT_SHORT_MONTHS:
    887         DateFormatSymbolsSingleSetter::setShortMonth(syms, index, value, valueLength, *status);
    888         break;
    889 
    890     case UDAT_NARROW_MONTHS:
    891         DateFormatSymbolsSingleSetter::setNarrowMonth(syms, index, value, valueLength, *status);
    892         break;
    893 
    894     case UDAT_STANDALONE_MONTHS:
    895         DateFormatSymbolsSingleSetter::setStandaloneMonth(syms, index, value, valueLength, *status);
    896         break;
    897 
    898     case UDAT_STANDALONE_SHORT_MONTHS:
    899         DateFormatSymbolsSingleSetter::setStandaloneShortMonth(syms, index, value, valueLength, *status);
    900         break;
    901 
    902     case UDAT_STANDALONE_NARROW_MONTHS:
    903         DateFormatSymbolsSingleSetter::setStandaloneNarrowMonth(syms, index, value, valueLength, *status);
    904         break;
    905 
    906     case UDAT_WEEKDAYS:
    907         DateFormatSymbolsSingleSetter::setWeekday(syms, index, value, valueLength, *status);
    908         break;
    909 
    910     case UDAT_SHORT_WEEKDAYS:
    911         DateFormatSymbolsSingleSetter::setShortWeekday(syms, index, value, valueLength, *status);
    912         break;
    913 
    914     case UDAT_SHORTER_WEEKDAYS:
    915         DateFormatSymbolsSingleSetter::setShorterWeekday(syms, index, value, valueLength, *status);
    916         break;
    917 
    918     case UDAT_NARROW_WEEKDAYS:
    919         DateFormatSymbolsSingleSetter::setNarrowWeekday(syms, index, value, valueLength, *status);
    920         break;
    921 
    922     case UDAT_STANDALONE_WEEKDAYS:
    923         DateFormatSymbolsSingleSetter::setStandaloneWeekday(syms, index, value, valueLength, *status);
    924         break;
    925 
    926     case UDAT_STANDALONE_SHORT_WEEKDAYS:
    927         DateFormatSymbolsSingleSetter::setStandaloneShortWeekday(syms, index, value, valueLength, *status);
    928         break;
    929 
    930     case UDAT_STANDALONE_SHORTER_WEEKDAYS:
    931         DateFormatSymbolsSingleSetter::setStandaloneShorterWeekday(syms, index, value, valueLength, *status);
    932         break;
    933 
    934     case UDAT_STANDALONE_NARROW_WEEKDAYS:
    935         DateFormatSymbolsSingleSetter::setStandaloneNarrowWeekday(syms, index, value, valueLength, *status);
    936         break;
    937 
    938     case UDAT_QUARTERS:
    939         DateFormatSymbolsSingleSetter::setQuarter(syms, index, value, valueLength, *status);
    940         break;
    941 
    942     case UDAT_SHORT_QUARTERS:
    943         DateFormatSymbolsSingleSetter::setShortQuarter(syms, index, value, valueLength, *status);
    944         break;
    945 
    946     case UDAT_STANDALONE_QUARTERS:
    947         DateFormatSymbolsSingleSetter::setStandaloneQuarter(syms, index, value, valueLength, *status);
    948         break;
    949 
    950     case UDAT_STANDALONE_SHORT_QUARTERS:
    951         DateFormatSymbolsSingleSetter::setStandaloneShortQuarter(syms, index, value, valueLength, *status);
    952         break;
    953 
    954     case UDAT_AM_PMS:
    955         DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status);
    956         break;
    957 
    958     case UDAT_LOCALIZED_CHARS:
    959         DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status);
    960         break;
    961 
    962     default:
    963         *status = U_UNSUPPORTED_ERROR;
    964         break;
    965 
    966     }
    967 }
    968 
    969 U_CAPI const char* U_EXPORT2
    970 udat_getLocaleByType(const UDateFormat *fmt,
    971                      ULocDataLocaleType type,
    972                      UErrorCode* status)
    973 {
    974     if (fmt == NULL) {
    975         if (U_SUCCESS(*status)) {
    976             *status = U_ILLEGAL_ARGUMENT_ERROR;
    977         }
    978         return NULL;
    979     }
    980     return ((Format*)fmt)->getLocaleID(type, *status);
    981 }
    982 
    983 
    984 U_CAPI void U_EXPORT2
    985 udat_setContext(UDateFormat* fmt, UDisplayContext value, UErrorCode* status)
    986 {
    987     verifyIsSimpleDateFormat(fmt, status);
    988     if (U_FAILURE(*status)) {
    989         return;
    990     }
    991     ((SimpleDateFormat*)fmt)->setContext(value, *status);
    992 }
    993 
    994 U_CAPI UDisplayContext U_EXPORT2
    995 udat_getContext(UDateFormat* fmt, UDisplayContextType type, UErrorCode* status)
    996 {
    997     verifyIsSimpleDateFormat(fmt, status);
    998     if (U_FAILURE(*status)) {
    999         return (UDisplayContext)0;
   1000     }
   1001     return ((SimpleDateFormat*)fmt)->getContext(type, *status);
   1002 }
   1003 
   1004 
   1005 /**
   1006  * Verify that fmt is a RelativeDateFormat. Invalid error if not.
   1007  * @param fmt the UDateFormat, definitely a DateFormat, maybe something else
   1008  * @param status error code, will be set to failure if there is a familure or the fmt is NULL.
   1009  */
   1010 static void verifyIsRelativeDateFormat(const UDateFormat* fmt, UErrorCode *status) {
   1011    if(U_SUCCESS(*status) &&
   1012        dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) {
   1013        *status = U_ILLEGAL_ARGUMENT_ERROR;
   1014    }
   1015 }
   1016 
   1017 
   1018 U_CAPI int32_t U_EXPORT2
   1019 udat_toPatternRelativeDate(const UDateFormat *fmt,
   1020                            UChar             *result,
   1021                            int32_t           resultLength,
   1022                            UErrorCode        *status)
   1023 {
   1024     verifyIsRelativeDateFormat(fmt, status);
   1025     if(U_FAILURE(*status)) return -1;
   1026 
   1027     UnicodeString datePattern;
   1028     if(!(result==NULL && resultLength==0)) {
   1029         // NULL destination for pure preflighting: empty dummy string
   1030         // otherwise, alias the destination buffer
   1031         datePattern.setTo(result, 0, resultLength);
   1032     }
   1033     ((RelativeDateFormat*)fmt)->toPatternDate(datePattern, *status);
   1034     return datePattern.extract(result, resultLength, *status);
   1035 }
   1036 
   1037 U_CAPI int32_t U_EXPORT2
   1038 udat_toPatternRelativeTime(const UDateFormat *fmt,
   1039                            UChar             *result,
   1040                            int32_t           resultLength,
   1041                            UErrorCode        *status)
   1042 {
   1043     verifyIsRelativeDateFormat(fmt, status);
   1044     if(U_FAILURE(*status)) return -1;
   1045 
   1046     UnicodeString timePattern;
   1047     if(!(result==NULL && resultLength==0)) {
   1048         // NULL destination for pure preflighting: empty dummy string
   1049         // otherwise, alias the destination buffer
   1050         timePattern.setTo(result, 0, resultLength);
   1051     }
   1052     ((RelativeDateFormat*)fmt)->toPatternTime(timePattern, *status);
   1053     return timePattern.extract(result, resultLength, *status);
   1054 }
   1055 
   1056 U_CAPI void U_EXPORT2
   1057 udat_applyPatternRelative(UDateFormat *format,
   1058                           const UChar *datePattern,
   1059                           int32_t     datePatternLength,
   1060                           const UChar *timePattern,
   1061                           int32_t     timePatternLength,
   1062                           UErrorCode  *status)
   1063 {
   1064     verifyIsRelativeDateFormat(format, status);
   1065     if(U_FAILURE(*status)) return;
   1066     const UnicodeString datePat((UBool)(datePatternLength == -1), datePattern, datePatternLength);
   1067     const UnicodeString timePat((UBool)(timePatternLength == -1), timePattern, timePatternLength);
   1068     ((RelativeDateFormat*)format)->applyPatterns(datePat, timePat, *status);
   1069 }
   1070 
   1071 #endif /* #if !UCONFIG_NO_FORMATTING */
   1072