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