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