tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

udat.cpp (46718B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 *******************************************************************************
      5 *   Copyright (C) 1996-2015, International Business Machines
      6 *   Corporation and others.  All Rights Reserved.
      7 *******************************************************************************
      8 */
      9 
     10 #include "unicode/utypes.h"
     11 
     12 #if !UCONFIG_NO_FORMATTING
     13 
     14 #include "unicode/udat.h"
     15 
     16 #include "unicode/uloc.h"
     17 #include "unicode/datefmt.h"
     18 #include "unicode/timezone.h"
     19 #include "unicode/smpdtfmt.h"
     20 #include "unicode/fieldpos.h"
     21 #include "unicode/parsepos.h"
     22 #include "unicode/calendar.h"
     23 #include "unicode/numfmt.h"
     24 #include "unicode/dtfmtsym.h"
     25 #include "unicode/ustring.h"
     26 #include "unicode/udisplaycontext.h"
     27 #include "unicode/ufieldpositer.h"
     28 #include "cpputils.h"
     29 #include "reldtfmt.h"
     30 #include "umutex.h"
     31 
     32 U_NAMESPACE_USE
     33 
     34 /**
     35 * Verify that fmt is a SimpleDateFormat. Invalid error if not.
     36 * @param fmt the UDateFormat, definitely a DateFormat, maybe something else
     37 * @param status error code, will be set to failure if there is a failure or the fmt is nullptr.
     38 */
     39 static void verifyIsSimpleDateFormat(const UDateFormat* fmt, UErrorCode *status) {
     40   if(U_SUCCESS(*status) &&
     41       dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==nullptr) {
     42       *status = U_ILLEGAL_ARGUMENT_ERROR;
     43   }
     44 }
     45 
     46 // This mirrors the correspondence between the
     47 // SimpleDateFormat::fgPatternIndexToDateFormatField and
     48 // SimpleDateFormat::fgPatternIndexToCalendarField arrays.
     49 static UCalendarDateFields gDateFieldMapping[] = {
     50    UCAL_ERA,                  // UDAT_ERA_FIELD = 0
     51    UCAL_YEAR,                 // UDAT_YEAR_FIELD = 1
     52    UCAL_MONTH,                // UDAT_MONTH_FIELD = 2
     53    UCAL_DATE,                 // UDAT_DATE_FIELD = 3
     54    UCAL_HOUR_OF_DAY,          // UDAT_HOUR_OF_DAY1_FIELD = 4
     55    UCAL_HOUR_OF_DAY,          // UDAT_HOUR_OF_DAY0_FIELD = 5
     56    UCAL_MINUTE,               // UDAT_MINUTE_FIELD = 6
     57    UCAL_SECOND,               // UDAT_SECOND_FIELD = 7
     58    UCAL_MILLISECOND,          // UDAT_FRACTIONAL_SECOND_FIELD = 8
     59    UCAL_DAY_OF_WEEK,          // UDAT_DAY_OF_WEEK_FIELD = 9
     60    UCAL_DAY_OF_YEAR,          // UDAT_DAY_OF_YEAR_FIELD = 10
     61    UCAL_DAY_OF_WEEK_IN_MONTH, // UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11
     62    UCAL_WEEK_OF_YEAR,         // UDAT_WEEK_OF_YEAR_FIELD = 12
     63    UCAL_WEEK_OF_MONTH,        // UDAT_WEEK_OF_MONTH_FIELD = 13
     64    UCAL_AM_PM,                // UDAT_AM_PM_FIELD = 14
     65    UCAL_HOUR,                 // UDAT_HOUR1_FIELD = 15
     66    UCAL_HOUR,                 // UDAT_HOUR0_FIELD = 16
     67    UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_FIELD = 17
     68    UCAL_YEAR_WOY,             // UDAT_YEAR_WOY_FIELD = 18
     69    UCAL_DOW_LOCAL,            // UDAT_DOW_LOCAL_FIELD = 19
     70    UCAL_EXTENDED_YEAR,        // UDAT_EXTENDED_YEAR_FIELD = 20
     71    UCAL_JULIAN_DAY,           // UDAT_JULIAN_DAY_FIELD = 21
     72    UCAL_MILLISECONDS_IN_DAY,  // UDAT_MILLISECONDS_IN_DAY_FIELD = 22
     73    UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_RFC_FIELD = 23 (also UCAL_DST_OFFSET)
     74    UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_GENERIC_FIELD = 24 (also UCAL_DST_OFFSET)
     75    UCAL_DOW_LOCAL,            // UDAT_STANDALONE_DAY_FIELD = 25
     76    UCAL_MONTH,                // UDAT_STANDALONE_MONTH_FIELD = 26
     77    UCAL_MONTH,                // UDAT_QUARTER_FIELD = 27
     78    UCAL_MONTH,                // UDAT_STANDALONE_QUARTER_FIELD = 28
     79    UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_SPECIAL_FIELD = 29 (also UCAL_DST_OFFSET)
     80    UCAL_YEAR,                 // UDAT_YEAR_NAME_FIELD = 30
     81    UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD = 31 (also UCAL_DST_OFFSET)
     82    UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_ISO_FIELD = 32 (also UCAL_DST_OFFSET)
     83    UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_ISO_LOCAL_FIELD = 33 (also UCAL_DST_OFFSET)
     84    UCAL_EXTENDED_YEAR,        // UDAT_RELATED_YEAR_FIELD = 34 (not an exact match)
     85    UCAL_FIELD_COUNT,          // UDAT_AM_PM_MIDNIGHT_NOON_FIELD=35 (no match)
     86    UCAL_FIELD_COUNT,          // UDAT_FLEXIBLE_DAY_PERIOD_FIELD=36 (no match)
     87    UCAL_FIELD_COUNT,          // UDAT_TIME_SEPARATOR_FIELD = 37 (no match)
     88                               // UDAT_FIELD_COUNT = 38 as of ICU 67
     89    // UCAL_IS_LEAP_MONTH is not the target of a mapping
     90 };
     91 
     92 U_CAPI UCalendarDateFields U_EXPORT2
     93 udat_toCalendarDateField(UDateFormatField field) UPRV_NO_SANITIZE_UNDEFINED {
     94  static_assert(UDAT_FIELD_COUNT == UPRV_LENGTHOF(gDateFieldMapping),
     95    "UDateFormatField and gDateFieldMapping should have the same number of entries and be kept in sync.");
     96  return (field >= UDAT_ERA_FIELD && field < UPRV_LENGTHOF(gDateFieldMapping))? gDateFieldMapping[field]: UCAL_FIELD_COUNT;
     97 }
     98 
     99 /* For now- one opener. */
    100 static UDateFormatOpener gOpener = nullptr;
    101 
    102 U_CAPI void U_EXPORT2
    103 udat_registerOpener(UDateFormatOpener opener, UErrorCode *status)
    104 {
    105  if(U_FAILURE(*status)) return;
    106  umtx_lock(nullptr);
    107  if(gOpener==nullptr) {
    108    gOpener = opener;
    109  } else {
    110    *status = U_ILLEGAL_ARGUMENT_ERROR;
    111  }
    112  umtx_unlock(nullptr);
    113 }
    114 
    115 U_CAPI UDateFormatOpener U_EXPORT2
    116 udat_unregisterOpener(UDateFormatOpener opener, UErrorCode *status)
    117 {
    118  if(U_FAILURE(*status)) return nullptr;
    119  UDateFormatOpener oldOpener = nullptr;
    120  umtx_lock(nullptr);
    121  if(gOpener==nullptr || gOpener!=opener) {
    122    *status = U_ILLEGAL_ARGUMENT_ERROR;
    123  } else {
    124    oldOpener=gOpener;
    125    gOpener=nullptr;
    126  }
    127  umtx_unlock(nullptr);
    128  return oldOpener;
    129 }
    130 
    131 
    132 
    133 U_CAPI UDateFormat* U_EXPORT2
    134 udat_open(UDateFormatStyle  timeStyle,
    135          UDateFormatStyle  dateStyle,
    136          const char        *locale,
    137          const char16_t    *tzID,
    138          int32_t           tzIDLength,
    139          const char16_t    *pattern,
    140          int32_t           patternLength,
    141          UErrorCode        *status)
    142 {
    143    DateFormat *fmt;
    144    if(U_FAILURE(*status)) {
    145        return nullptr;
    146    }
    147    if(gOpener!=nullptr) { // if it's registered
    148      fmt = (DateFormat*) (*gOpener)(timeStyle,dateStyle,locale,tzID,tzIDLength,pattern,patternLength,status);
    149      if(fmt!=nullptr) {
    150        return (UDateFormat*)fmt;
    151      } // else fall through.
    152    }
    153    if(timeStyle != UDAT_PATTERN) {
    154        if (locale == nullptr) {
    155            fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
    156                (DateFormat::EStyle)timeStyle);
    157        }
    158        else {
    159            fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
    160                (DateFormat::EStyle)timeStyle,
    161                Locale(locale));
    162        }
    163    }
    164    else {
    165        UnicodeString pat(patternLength == -1, pattern, patternLength);
    166 
    167        if (locale == nullptr) {
    168            fmt = new SimpleDateFormat(pat, *status);
    169        }
    170        else {
    171            fmt = new SimpleDateFormat(pat, Locale(locale), *status);
    172        }
    173    }
    174 
    175    if(fmt == nullptr) {
    176        *status = U_MEMORY_ALLOCATION_ERROR;
    177        return nullptr;
    178    }
    179    if (U_FAILURE(*status)) {
    180        delete fmt;
    181        return nullptr;
    182    }
    183 
    184    if (tzID != nullptr) {
    185        TimeZone* zone = TimeZone::createTimeZone(UnicodeString(tzIDLength == -1, tzID, tzIDLength));
    186        if (zone == nullptr) {
    187            *status = U_MEMORY_ALLOCATION_ERROR;
    188            delete fmt;
    189            return nullptr;
    190        }
    191        fmt->adoptTimeZone(zone);
    192    }
    193 
    194    return (UDateFormat*)fmt;
    195 }
    196 
    197 
    198 U_CAPI void U_EXPORT2
    199 udat_close(UDateFormat* format)
    200 {
    201    if (format == nullptr) return;
    202    delete (DateFormat*)format;
    203 }
    204 
    205 U_CAPI UDateFormat* U_EXPORT2
    206 udat_clone(const UDateFormat *fmt,
    207       UErrorCode *status)
    208 {
    209    if (U_FAILURE(*status)) return nullptr;
    210 
    211    Format *res = ((DateFormat*)fmt)->clone();
    212 
    213    if (res == nullptr) {
    214        *status = U_MEMORY_ALLOCATION_ERROR;
    215        return nullptr;
    216    }
    217 
    218    return (UDateFormat*) res;
    219 }
    220 
    221 U_CAPI int32_t U_EXPORT2
    222 udat_format(    const    UDateFormat*    format,
    223        UDate           dateToFormat,
    224        char16_t*          result,
    225        int32_t         resultLength,
    226        UFieldPosition* position,
    227        UErrorCode*     status)
    228 {
    229    if(U_FAILURE(*status)) {
    230        return -1;
    231    }
    232    if (result == nullptr ? resultLength != 0 : resultLength < 0) {
    233        *status = U_ILLEGAL_ARGUMENT_ERROR;
    234        return -1;
    235    }
    236 
    237    UnicodeString res;
    238    if (result != nullptr) {
    239        // nullptr destination for pure preflighting: empty dummy string
    240        // otherwise, alias the destination buffer
    241        res.setTo(result, 0, resultLength);
    242    }
    243 
    244    FieldPosition fp;
    245 
    246    if (position != nullptr)
    247        fp.setField(position->field);
    248 
    249    ((DateFormat*)format)->format(dateToFormat, res, fp);
    250 
    251    if (position != nullptr) {
    252        position->beginIndex = fp.getBeginIndex();
    253        position->endIndex = fp.getEndIndex();
    254    }
    255 
    256    return res.extract(result, resultLength, *status);
    257 }
    258 
    259 U_CAPI int32_t U_EXPORT2
    260 udat_formatCalendar(const UDateFormat*  format,
    261        UCalendar*      calendar,
    262        char16_t*          result,
    263        int32_t         resultLength,
    264        UFieldPosition* position,
    265        UErrorCode*     status)
    266 {
    267    if(U_FAILURE(*status)) {
    268        return -1;
    269    }
    270    if (result == nullptr ? resultLength != 0 : resultLength < 0) {
    271        *status = U_ILLEGAL_ARGUMENT_ERROR;
    272        return -1;
    273    }
    274 
    275    UnicodeString res;
    276    if (result != nullptr) {
    277        // nullptr destination for pure preflighting: empty dummy string
    278        // otherwise, alias the destination buffer
    279        res.setTo(result, 0, resultLength);
    280    }
    281 
    282    FieldPosition fp;
    283 
    284    if (position != nullptr)
    285        fp.setField(position->field);
    286 
    287    ((DateFormat*)format)->format(*(Calendar*)calendar, res, fp);
    288 
    289    if (position != nullptr) {
    290        position->beginIndex = fp.getBeginIndex();
    291        position->endIndex = fp.getEndIndex();
    292    }
    293 
    294    return res.extract(result, resultLength, *status);
    295 }
    296 
    297 U_CAPI int32_t U_EXPORT2
    298 udat_formatForFields(    const    UDateFormat*    format,
    299        UDate           dateToFormat,
    300        char16_t*          result,
    301        int32_t         resultLength,
    302        UFieldPositionIterator* fpositer,
    303        UErrorCode*     status)
    304 {
    305    if(U_FAILURE(*status)) {
    306        return -1;
    307    }
    308    if (result == nullptr ? resultLength != 0 : resultLength < 0) {
    309        *status = U_ILLEGAL_ARGUMENT_ERROR;
    310        return -1;
    311    }
    312 
    313    UnicodeString res;
    314    if (result != nullptr) {
    315        // nullptr destination for pure preflighting: empty dummy string
    316        // otherwise, alias the destination buffer
    317        res.setTo(result, 0, resultLength);
    318    }
    319 
    320    ((DateFormat*)format)->format(dateToFormat, res, (FieldPositionIterator*)fpositer, *status);
    321 
    322    return res.extract(result, resultLength, *status);
    323 }
    324 
    325 U_CAPI int32_t U_EXPORT2
    326 udat_formatCalendarForFields(const UDateFormat*  format,
    327        UCalendar*      calendar,
    328        char16_t*          result,
    329        int32_t         resultLength,
    330        UFieldPositionIterator* fpositer,
    331        UErrorCode*     status)
    332 {
    333    if(U_FAILURE(*status)) {
    334        return -1;
    335    }
    336    if (result == nullptr ? resultLength != 0 : resultLength < 0) {
    337        *status = U_ILLEGAL_ARGUMENT_ERROR;
    338        return -1;
    339    }
    340 
    341    UnicodeString res;
    342    if (result != nullptr) {
    343        // nullptr destination for pure preflighting: empty dummy string
    344        // otherwise, alias the destination buffer
    345        res.setTo(result, 0, resultLength);
    346    }
    347 
    348    ((DateFormat*)format)->format(*(Calendar*)calendar, res, (FieldPositionIterator*)fpositer, *status);
    349 
    350    return res.extract(result, resultLength, *status);
    351 }
    352 
    353 U_CAPI UDate U_EXPORT2
    354 udat_parse(    const    UDateFormat*        format,
    355        const    char16_t*          text,
    356        int32_t         textLength,
    357        int32_t         *parsePos,
    358        UErrorCode      *status)
    359 {
    360    if(U_FAILURE(*status)) return (UDate)0;
    361 
    362    const UnicodeString src(textLength == -1, text, textLength);
    363    ParsePosition pp;
    364    int32_t stackParsePos = 0;
    365    UDate res;
    366 
    367    if(parsePos == nullptr) {
    368        parsePos = &stackParsePos;
    369    }
    370 
    371    pp.setIndex(*parsePos);
    372 
    373    res = ((DateFormat*)format)->parse(src, pp);
    374 
    375    if(pp.getErrorIndex() == -1)
    376        *parsePos = pp.getIndex();
    377    else {
    378        *parsePos = pp.getErrorIndex();
    379        *status = U_PARSE_ERROR;
    380    }
    381 
    382    return res;
    383 }
    384 
    385 U_CAPI void U_EXPORT2
    386 udat_parseCalendar(const    UDateFormat*    format,
    387                            UCalendar*      calendar,
    388                   const    char16_t*          text,
    389                            int32_t         textLength,
    390                            int32_t         *parsePos,
    391                            UErrorCode      *status)
    392 {
    393    if(U_FAILURE(*status)) return;
    394 
    395    const UnicodeString src(textLength == -1, text, textLength);
    396    ParsePosition pp;
    397    int32_t stackParsePos = 0;
    398 
    399    if(parsePos == nullptr) {
    400        parsePos = &stackParsePos;
    401    }
    402 
    403    pp.setIndex(*parsePos);
    404 
    405    ((DateFormat*)format)->parse(src, *(Calendar*)calendar, pp);
    406 
    407    if(pp.getErrorIndex() == -1)
    408        *parsePos = pp.getIndex();
    409    else {
    410        *parsePos = pp.getErrorIndex();
    411        *status = U_PARSE_ERROR;
    412    }
    413 }
    414 
    415 U_CAPI UBool U_EXPORT2
    416 udat_isLenient(const UDateFormat* fmt)
    417 {
    418    return ((DateFormat*)fmt)->isLenient();
    419 }
    420 
    421 U_CAPI void U_EXPORT2
    422 udat_setLenient(    UDateFormat*    fmt,
    423            UBool          isLenient)
    424 {
    425    ((DateFormat*)fmt)->setLenient(isLenient);
    426 }
    427 
    428 U_CAPI UBool U_EXPORT2
    429 udat_getBooleanAttribute(const UDateFormat* fmt, 
    430                         UDateFormatBooleanAttribute attr, 
    431                         UErrorCode* status)
    432 {
    433    if(U_FAILURE(*status)) return false;
    434    return ((DateFormat*)fmt)->getBooleanAttribute(attr, *status);
    435    //return false;
    436 }
    437 
    438 U_CAPI void U_EXPORT2
    439 udat_setBooleanAttribute(UDateFormat *fmt, 
    440                         UDateFormatBooleanAttribute attr, 
    441                         UBool newValue, 
    442                         UErrorCode* status)
    443 {
    444    if(U_FAILURE(*status)) return;
    445    ((DateFormat*)fmt)->setBooleanAttribute(attr, newValue, *status);
    446 }
    447 
    448 U_CAPI const UCalendar* U_EXPORT2
    449 udat_getCalendar(const UDateFormat* fmt)
    450 {
    451    return (const UCalendar*) ((DateFormat*)fmt)->getCalendar();
    452 }
    453 
    454 U_CAPI void U_EXPORT2
    455 udat_setCalendar(UDateFormat*    fmt,
    456                 const   UCalendar*      calendarToSet)
    457 {
    458    ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet));
    459 }
    460 
    461 U_CAPI const UNumberFormat* U_EXPORT2 
    462 udat_getNumberFormatForField(const UDateFormat* fmt, char16_t field)
    463 {
    464    UErrorCode status = U_ZERO_ERROR;
    465    verifyIsSimpleDateFormat(fmt, &status);
    466    if (U_FAILURE(status)) return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat();
    467    return (const UNumberFormat*) ((SimpleDateFormat*)fmt)->getNumberFormatForField(field);
    468 }
    469 
    470 U_CAPI const UNumberFormat* U_EXPORT2
    471 udat_getNumberFormat(const UDateFormat* fmt)
    472 {
    473    return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat();
    474 }
    475 
    476 U_CAPI void U_EXPORT2 
    477 udat_adoptNumberFormatForFields(           UDateFormat*    fmt,
    478                                    const  char16_t*          fields,
    479                                           UNumberFormat*  numberFormatToSet,
    480                                           UErrorCode*     status)
    481 {
    482    verifyIsSimpleDateFormat(fmt, status);
    483    if (U_FAILURE(*status)) return;
    484    
    485    if (fields!=nullptr) {
    486        UnicodeString overrideFields(fields);
    487        ((SimpleDateFormat*)fmt)->adoptNumberFormat(overrideFields, (NumberFormat*)numberFormatToSet, *status);
    488    }
    489 }
    490 
    491 U_CAPI void U_EXPORT2
    492 udat_setNumberFormat(UDateFormat*    fmt,
    493                     const   UNumberFormat*  numberFormatToSet)
    494 {
    495    ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet));
    496 }
    497 
    498 U_CAPI void U_EXPORT2
    499 udat_adoptNumberFormat(      UDateFormat*    fmt,
    500                             UNumberFormat*  numberFormatToAdopt)
    501 {
    502    ((DateFormat*)fmt)->adoptNumberFormat((NumberFormat*)numberFormatToAdopt);
    503 }
    504 
    505 U_CAPI const char* U_EXPORT2
    506 udat_getAvailable(int32_t index)
    507 {
    508    return uloc_getAvailable(index);
    509 }
    510 
    511 U_CAPI int32_t U_EXPORT2
    512 udat_countAvailable()
    513 {
    514    return uloc_countAvailable();
    515 }
    516 
    517 U_CAPI UDate U_EXPORT2
    518 udat_get2DigitYearStart(    const   UDateFormat     *fmt,
    519                        UErrorCode      *status)
    520 {
    521    verifyIsSimpleDateFormat(fmt, status);
    522    if(U_FAILURE(*status)) return (UDate)0;
    523    return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status);
    524 }
    525 
    526 U_CAPI void U_EXPORT2
    527 udat_set2DigitYearStart(    UDateFormat     *fmt,
    528                        UDate           d,
    529                        UErrorCode      *status)
    530 {
    531    verifyIsSimpleDateFormat(fmt, status);
    532    if(U_FAILURE(*status)) return;
    533    ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status);
    534 }
    535 
    536 U_CAPI int32_t U_EXPORT2
    537 udat_toPattern(    const   UDateFormat     *fmt,
    538        UBool          localized,
    539        char16_t        *result,
    540        int32_t         resultLength,
    541        UErrorCode      *status)
    542 {
    543    if(U_FAILURE(*status)) {
    544        return -1;
    545    }
    546    if (result == nullptr ? resultLength != 0 : resultLength < 0) {
    547        *status = U_ILLEGAL_ARGUMENT_ERROR;
    548        return -1;
    549    }
    550 
    551    UnicodeString res;
    552    if (result != nullptr) {
    553        // nullptr destination for pure preflighting: empty dummy string
    554        // otherwise, alias the destination buffer
    555        res.setTo(result, 0, resultLength);
    556    }
    557 
    558    const DateFormat *df=reinterpret_cast<const DateFormat *>(fmt);
    559    const SimpleDateFormat *sdtfmt=dynamic_cast<const SimpleDateFormat *>(df);
    560    const RelativeDateFormat *reldtfmt;
    561    if (sdtfmt!=nullptr) {
    562        if(localized)
    563            sdtfmt->toLocalizedPattern(res, *status);
    564        else
    565            sdtfmt->toPattern(res);
    566    } else if (!localized && (reldtfmt=dynamic_cast<const RelativeDateFormat *>(df))!=nullptr) {
    567        reldtfmt->toPattern(res, *status);
    568    } else {
    569        *status = U_ILLEGAL_ARGUMENT_ERROR;
    570        return -1;
    571    }
    572 
    573    return res.extract(result, resultLength, *status);
    574 }
    575 
    576 // TODO: should this take an UErrorCode?
    577 // A: Yes. Of course.
    578 U_CAPI void U_EXPORT2
    579 udat_applyPattern(  UDateFormat     *format,
    580                    UBool          localized,
    581                    const   char16_t        *pattern,
    582                    int32_t         patternLength)
    583 {
    584    const UnicodeString pat(patternLength == -1, pattern, patternLength);
    585    UErrorCode status = U_ZERO_ERROR;
    586 
    587    verifyIsSimpleDateFormat(format, &status);
    588    if(U_FAILURE(status)) {
    589        return;
    590    }
    591    
    592    if(localized)
    593        ((SimpleDateFormat*)format)->applyLocalizedPattern(pat, status);
    594    else
    595        ((SimpleDateFormat*)format)->applyPattern(pat);
    596 }
    597 
    598 U_CAPI int32_t U_EXPORT2
    599 udat_getSymbols(const   UDateFormat     *fmt,
    600                UDateFormatSymbolType   type,
    601                int32_t                 index,
    602                char16_t                *result,
    603                int32_t                 resultLength,
    604                UErrorCode              *status)
    605 {
    606    const DateFormatSymbols *syms;
    607    const SimpleDateFormat* sdtfmt;
    608    const RelativeDateFormat* rdtfmt;
    609    if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != nullptr) {
    610        syms = sdtfmt->getDateFormatSymbols();
    611    } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != nullptr) {
    612        syms = rdtfmt->getDateFormatSymbols();
    613    } else {
    614        return -1;
    615    }
    616    int32_t count = 0;
    617    const UnicodeString *res = nullptr;
    618 
    619    switch(type) {
    620    case UDAT_ERAS:
    621        res = syms->getEras(count);
    622        break;
    623 
    624    case UDAT_ERA_NAMES:
    625        res = syms->getEraNames(count);
    626        break;
    627 
    628    case UDAT_MONTHS:
    629        res = syms->getMonths(count);
    630        break;
    631 
    632    case UDAT_SHORT_MONTHS:
    633        res = syms->getShortMonths(count);
    634        break;
    635 
    636    case UDAT_WEEKDAYS:
    637        res = syms->getWeekdays(count);
    638        break;
    639 
    640    case UDAT_SHORT_WEEKDAYS:
    641        res = syms->getShortWeekdays(count);
    642        break;
    643 
    644    case UDAT_AM_PMS:
    645        res = syms->getAmPmStrings(count);
    646        break;
    647 
    648    case UDAT_AM_PMS_NARROW:
    649        res = syms->getAmPmStrings(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    650        break;
    651 
    652    case UDAT_AM_PMS_WIDE:
    653        res = syms->getAmPmStrings(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    654        break;
    655 
    656    case UDAT_LOCALIZED_CHARS:
    657        {
    658            UnicodeString res1;
    659            if(!(result==nullptr && resultLength==0)) {
    660                // nullptr destination for pure preflighting: empty dummy string
    661                // otherwise, alias the destination buffer
    662                res1.setTo(result, 0, resultLength);
    663            }
    664            syms->getLocalPatternChars(res1);
    665            return res1.extract(result, resultLength, *status);
    666        }
    667 
    668    case UDAT_NARROW_MONTHS:
    669        res = syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    670        break;
    671 
    672    case UDAT_SHORTER_WEEKDAYS:
    673        res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::SHORT);
    674        break;
    675 
    676    case UDAT_NARROW_WEEKDAYS:
    677        res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    678        break;
    679 
    680    case UDAT_STANDALONE_MONTHS:
    681        res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    682        break;
    683 
    684    case UDAT_STANDALONE_SHORT_MONTHS:
    685        res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    686        break;
    687 
    688    case UDAT_STANDALONE_NARROW_MONTHS:
    689        res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    690        break;
    691 
    692    case UDAT_STANDALONE_WEEKDAYS:
    693        res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    694        break;
    695 
    696    case UDAT_STANDALONE_SHORT_WEEKDAYS:
    697        res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    698        break;
    699 
    700    case UDAT_STANDALONE_SHORTER_WEEKDAYS:
    701        res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::SHORT);
    702        break;
    703 
    704    case UDAT_STANDALONE_NARROW_WEEKDAYS:
    705        res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    706        break;
    707 
    708    case UDAT_QUARTERS:
    709        res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    710        break;
    711 
    712    case UDAT_SHORT_QUARTERS:
    713        res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
    714        break;
    715 
    716    case UDAT_NARROW_QUARTERS:
    717        res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    718        break;
    719        
    720    case UDAT_STANDALONE_QUARTERS:
    721        res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    722        break;
    723 
    724    case UDAT_STANDALONE_SHORT_QUARTERS:
    725        res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    726        break;
    727 
    728    case UDAT_STANDALONE_NARROW_QUARTERS:
    729        res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    730        break;
    731        
    732    case UDAT_CYCLIC_YEARS_WIDE:
    733        res = syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    734        break;
    735 
    736    case UDAT_CYCLIC_YEARS_ABBREVIATED:
    737        res = syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
    738        break;
    739 
    740    case UDAT_CYCLIC_YEARS_NARROW:
    741        res = syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    742        break;
    743 
    744    case UDAT_ZODIAC_NAMES_WIDE:
    745        res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    746        break;
    747 
    748    case UDAT_ZODIAC_NAMES_ABBREVIATED:
    749        res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
    750        break;
    751 
    752    case UDAT_ZODIAC_NAMES_NARROW:
    753        res = syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    754        break;
    755 
    756    }
    757 
    758    if(index < count) {
    759        return res[index].extract(result, resultLength, *status);
    760    }
    761    return 0;
    762 }
    763 
    764 // TODO: also needs an errorCode.
    765 U_CAPI int32_t U_EXPORT2
    766 udat_countSymbols(    const    UDateFormat                *fmt,
    767            UDateFormatSymbolType    type)
    768 {
    769    const DateFormatSymbols *syms;
    770    const SimpleDateFormat* sdtfmt;
    771    const RelativeDateFormat* rdtfmt;
    772    if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != nullptr) {
    773        syms = sdtfmt->getDateFormatSymbols();
    774    } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != nullptr) {
    775        syms = rdtfmt->getDateFormatSymbols();
    776    } else {
    777        return 0;
    778    }
    779    int32_t count = 0;
    780 
    781    switch(type) {
    782    case UDAT_ERAS:
    783        syms->getEras(count);
    784        break;
    785 
    786    case UDAT_MONTHS:
    787        syms->getMonths(count);
    788        break;
    789 
    790    case UDAT_SHORT_MONTHS:
    791        syms->getShortMonths(count);
    792        break;
    793 
    794    case UDAT_WEEKDAYS:
    795        syms->getWeekdays(count);
    796        break;
    797 
    798    case UDAT_SHORT_WEEKDAYS:
    799        syms->getShortWeekdays(count);
    800        break;
    801 
    802    case UDAT_AM_PMS:
    803        syms->getAmPmStrings(count);
    804        break;
    805 
    806    case UDAT_AM_PMS_NARROW:
    807        syms->getAmPmStrings(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    808        break;
    809 
    810    case UDAT_AM_PMS_WIDE:
    811        syms->getAmPmStrings(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    812        break;
    813 
    814    case UDAT_LOCALIZED_CHARS:
    815        count = 1;
    816        break;
    817 
    818    case UDAT_ERA_NAMES:
    819        syms->getEraNames(count);
    820        break;
    821 
    822    case UDAT_NARROW_MONTHS:
    823        syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    824        break;
    825 
    826    case UDAT_SHORTER_WEEKDAYS:
    827        syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::SHORT);
    828        break;
    829 
    830    case UDAT_NARROW_WEEKDAYS:
    831        syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    832        break;
    833 
    834    case UDAT_STANDALONE_MONTHS:
    835        syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    836        break;
    837 
    838    case UDAT_STANDALONE_SHORT_MONTHS:
    839        syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    840        break;
    841 
    842    case UDAT_STANDALONE_NARROW_MONTHS:
    843        syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    844        break;
    845 
    846    case UDAT_STANDALONE_WEEKDAYS:
    847        syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    848        break;
    849 
    850    case UDAT_STANDALONE_SHORT_WEEKDAYS:
    851        syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    852        break;
    853 
    854    case UDAT_STANDALONE_SHORTER_WEEKDAYS:
    855        syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::SHORT);
    856        break;
    857 
    858    case UDAT_STANDALONE_NARROW_WEEKDAYS:
    859        syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    860        break;
    861 
    862    case UDAT_QUARTERS:
    863        syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    864        break;
    865 
    866    case UDAT_SHORT_QUARTERS:
    867        syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
    868        break;
    869 
    870    case UDAT_NARROW_QUARTERS:
    871        syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    872        break;
    873        
    874    case UDAT_STANDALONE_QUARTERS:
    875        syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
    876        break;
    877 
    878    case UDAT_STANDALONE_SHORT_QUARTERS:
    879        syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
    880        break;
    881 
    882    case UDAT_STANDALONE_NARROW_QUARTERS:
    883        syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
    884        break;
    885        
    886    case UDAT_CYCLIC_YEARS_WIDE:
    887        syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    888        break;
    889 
    890    case UDAT_CYCLIC_YEARS_ABBREVIATED:
    891        syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
    892        break;
    893 
    894    case UDAT_CYCLIC_YEARS_NARROW:
    895        syms->getYearNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    896        break;
    897 
    898    case UDAT_ZODIAC_NAMES_WIDE:
    899        syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
    900        break;
    901 
    902    case UDAT_ZODIAC_NAMES_ABBREVIATED:
    903        syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
    904        break;
    905 
    906    case UDAT_ZODIAC_NAMES_NARROW:
    907        syms->getZodiacNames(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
    908        break;
    909 
    910    }
    911 
    912    return count;
    913 }
    914 
    915 U_NAMESPACE_BEGIN
    916 
    917 /*
    918 * This DateFormatSymbolsSingleSetter class is a friend of DateFormatSymbols
    919 * solely for the purpose of avoiding to clone the array of strings
    920 * just to modify one of them and then setting all of them back.
    921 * For example, the old code looked like this:
    922 *  case UDAT_MONTHS:
    923 *    res = syms->getMonths(count);
    924 *    array = new UnicodeString[count];
    925 *    if(array == 0) {
    926 *      *status = U_MEMORY_ALLOCATION_ERROR;
    927 *      return;
    928 *    }
    929 *    uprv_arrayCopy(res, array, count);
    930 *    if(index < count)
    931 *      array[index] = val;
    932 *    syms->setMonths(array, count);
    933 *    break;
    934 *
    935 * Even worse, the old code actually cloned the entire DateFormatSymbols object,
    936 * cloned one value array, changed one value, and then made the SimpleDateFormat
    937 * replace its DateFormatSymbols object with the new one.
    938 *
    939 * markus 2002-oct-14
    940 */
    941 class DateFormatSymbolsSingleSetter /* not : public UObject because all methods are static */ {
    942 public:
    943    static void
    944        setSymbol(UnicodeString *array, int32_t count, int32_t index,
    945        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
    946    {
    947        if(array!=nullptr) {
    948            if(index>=count) {
    949                errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
    950            } else if(value==nullptr) {
    951                errorCode=U_ILLEGAL_ARGUMENT_ERROR;
    952            } else {
    953                array[index].setTo(value, valueLength);
    954            }
    955        }
    956    }
    957 
    958    static void
    959        setEra(DateFormatSymbols *syms, int32_t index,
    960        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
    961    {
    962        setSymbol(syms->fEras, syms->fErasCount, index, value, valueLength, errorCode);
    963    }
    964 
    965    static void
    966        setEraName(DateFormatSymbols *syms, int32_t index,
    967        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
    968    {
    969        setSymbol(syms->fEraNames, syms->fEraNamesCount, index, value, valueLength, errorCode);
    970    }
    971 
    972    static void
    973        setMonth(DateFormatSymbols *syms, int32_t index,
    974        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
    975    {
    976        setSymbol(syms->fMonths, syms->fMonthsCount, index, value, valueLength, errorCode);
    977    }
    978 
    979    static void
    980        setShortMonth(DateFormatSymbols *syms, int32_t index,
    981        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
    982    {
    983        setSymbol(syms->fShortMonths, syms->fShortMonthsCount, index, value, valueLength, errorCode);
    984    }
    985 
    986    static void
    987        setNarrowMonth(DateFormatSymbols *syms, int32_t index,
    988        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
    989    {
    990        setSymbol(syms->fNarrowMonths, syms->fNarrowMonthsCount, index, value, valueLength, errorCode);
    991    }
    992 
    993    static void
    994        setStandaloneMonth(DateFormatSymbols *syms, int32_t index,
    995        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
    996    {
    997        setSymbol(syms->fStandaloneMonths, syms->fStandaloneMonthsCount, index, value, valueLength, errorCode);
    998    }
    999 
   1000    static void
   1001        setStandaloneShortMonth(DateFormatSymbols *syms, int32_t index,
   1002        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1003    {
   1004        setSymbol(syms->fStandaloneShortMonths, syms->fStandaloneShortMonthsCount, index, value, valueLength, errorCode);
   1005    }
   1006 
   1007    static void
   1008        setStandaloneNarrowMonth(DateFormatSymbols *syms, int32_t index,
   1009        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1010    {
   1011        setSymbol(syms->fStandaloneNarrowMonths, syms->fStandaloneNarrowMonthsCount, index, value, valueLength, errorCode);
   1012    }
   1013 
   1014    static void
   1015        setWeekday(DateFormatSymbols *syms, int32_t index,
   1016        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1017    {
   1018        setSymbol(syms->fWeekdays, syms->fWeekdaysCount, index, value, valueLength, errorCode);
   1019    }
   1020 
   1021    static void
   1022        setShortWeekday(DateFormatSymbols *syms, int32_t index,
   1023        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1024    {
   1025        setSymbol(syms->fShortWeekdays, syms->fShortWeekdaysCount, index, value, valueLength, errorCode);
   1026    }
   1027 
   1028    static void
   1029        setShorterWeekday(DateFormatSymbols *syms, int32_t index,
   1030        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1031    {
   1032        setSymbol(syms->fShorterWeekdays, syms->fShorterWeekdaysCount, index, value, valueLength, errorCode);
   1033    }
   1034 
   1035    static void
   1036        setNarrowWeekday(DateFormatSymbols *syms, int32_t index,
   1037        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1038    {
   1039        setSymbol(syms->fNarrowWeekdays, syms->fNarrowWeekdaysCount, index, value, valueLength, errorCode);
   1040    }
   1041 
   1042    static void
   1043        setStandaloneWeekday(DateFormatSymbols *syms, int32_t index,
   1044        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1045    {
   1046        setSymbol(syms->fStandaloneWeekdays, syms->fStandaloneWeekdaysCount, index, value, valueLength, errorCode);
   1047    }
   1048 
   1049    static void
   1050        setStandaloneShortWeekday(DateFormatSymbols *syms, int32_t index,
   1051        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1052    {
   1053        setSymbol(syms->fStandaloneShortWeekdays, syms->fStandaloneShortWeekdaysCount, index, value, valueLength, errorCode);
   1054    }
   1055 
   1056    static void
   1057        setStandaloneShorterWeekday(DateFormatSymbols *syms, int32_t index,
   1058        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1059    {
   1060        setSymbol(syms->fStandaloneShorterWeekdays, syms->fStandaloneShorterWeekdaysCount, index, value, valueLength, errorCode);
   1061    }
   1062 
   1063    static void
   1064        setStandaloneNarrowWeekday(DateFormatSymbols *syms, int32_t index,
   1065        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1066    {
   1067        setSymbol(syms->fStandaloneNarrowWeekdays, syms->fStandaloneNarrowWeekdaysCount, index, value, valueLength, errorCode);
   1068    }
   1069 
   1070    static void
   1071        setQuarter(DateFormatSymbols *syms, int32_t index,
   1072        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1073    {
   1074        setSymbol(syms->fQuarters, syms->fQuartersCount, index, value, valueLength, errorCode);
   1075    }
   1076 
   1077    static void
   1078        setShortQuarter(DateFormatSymbols *syms, int32_t index,
   1079        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1080    {
   1081        setSymbol(syms->fShortQuarters, syms->fShortQuartersCount, index, value, valueLength, errorCode);
   1082    }
   1083 
   1084    static void
   1085        setNarrowQuarter(DateFormatSymbols *syms, int32_t index,
   1086        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1087    {
   1088        setSymbol(syms->fNarrowQuarters, syms->fNarrowQuartersCount, index, value, valueLength, errorCode);
   1089    }
   1090    
   1091    static void
   1092        setStandaloneQuarter(DateFormatSymbols *syms, int32_t index,
   1093        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1094    {
   1095        setSymbol(syms->fStandaloneQuarters, syms->fStandaloneQuartersCount, index, value, valueLength, errorCode);
   1096    }
   1097 
   1098    static void
   1099        setStandaloneShortQuarter(DateFormatSymbols *syms, int32_t index,
   1100        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1101    {
   1102        setSymbol(syms->fStandaloneShortQuarters, syms->fStandaloneShortQuartersCount, index, value, valueLength, errorCode);
   1103    }
   1104 
   1105    static void
   1106        setStandaloneNarrowQuarter(DateFormatSymbols *syms, int32_t index,
   1107        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1108    {
   1109        setSymbol(syms->fStandaloneNarrowQuarters, syms->fStandaloneNarrowQuartersCount, index, value, valueLength, errorCode);
   1110    }
   1111    
   1112    static void
   1113        setShortYearNames(DateFormatSymbols *syms, int32_t index,
   1114        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1115    {
   1116        setSymbol(syms->fShortYearNames, syms->fShortYearNamesCount, index, value, valueLength, errorCode);
   1117    }
   1118 
   1119    static void
   1120        setShortZodiacNames(DateFormatSymbols *syms, int32_t index,
   1121        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1122    {
   1123        setSymbol(syms->fShortZodiacNames, syms->fShortZodiacNamesCount, index, value, valueLength, errorCode);
   1124    }
   1125 
   1126    static void
   1127        setAmPm(DateFormatSymbols *syms, int32_t index,
   1128        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1129    {
   1130        setSymbol(syms->fAmPms, syms->fAmPmsCount, index, value, valueLength, errorCode);
   1131    }
   1132 
   1133    static void
   1134        setAmPmNarrow(DateFormatSymbols *syms, int32_t index,
   1135        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1136    {
   1137        setSymbol(syms->fNarrowAmPms, syms->fNarrowAmPmsCount, index, value, valueLength, errorCode);
   1138    }
   1139 
   1140    static void
   1141        setAmPmWide(DateFormatSymbols *syms, int32_t index,
   1142        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1143    {
   1144        setSymbol(syms->fWideAmPms, syms->fWideAmPmsCount, index, value, valueLength, errorCode);
   1145    }
   1146 
   1147    static void
   1148        setLocalPatternChars(DateFormatSymbols *syms,
   1149        const char16_t *value, int32_t valueLength, UErrorCode &errorCode)
   1150    {
   1151        setSymbol(&syms->fLocalPatternChars, 1, 0, value, valueLength, errorCode);
   1152    }
   1153 };
   1154 
   1155 U_NAMESPACE_END
   1156 
   1157 U_CAPI void U_EXPORT2
   1158 udat_setSymbols(    UDateFormat             *format,
   1159            UDateFormatSymbolType   type,
   1160            int32_t                 index,
   1161            char16_t                *value,
   1162            int32_t                 valueLength,
   1163            UErrorCode              *status)
   1164 {
   1165    verifyIsSimpleDateFormat(format, status);
   1166    if(U_FAILURE(*status)) return;
   1167 
   1168    DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols();
   1169 
   1170    switch(type) {
   1171    case UDAT_ERAS:
   1172        DateFormatSymbolsSingleSetter::setEra(syms, index, value, valueLength, *status);
   1173        break;
   1174 
   1175    case UDAT_ERA_NAMES:
   1176        DateFormatSymbolsSingleSetter::setEraName(syms, index, value, valueLength, *status);
   1177        break;
   1178 
   1179    case UDAT_MONTHS:
   1180        DateFormatSymbolsSingleSetter::setMonth(syms, index, value, valueLength, *status);
   1181        break;
   1182 
   1183    case UDAT_SHORT_MONTHS:
   1184        DateFormatSymbolsSingleSetter::setShortMonth(syms, index, value, valueLength, *status);
   1185        break;
   1186 
   1187    case UDAT_NARROW_MONTHS:
   1188        DateFormatSymbolsSingleSetter::setNarrowMonth(syms, index, value, valueLength, *status);
   1189        break;
   1190 
   1191    case UDAT_STANDALONE_MONTHS:
   1192        DateFormatSymbolsSingleSetter::setStandaloneMonth(syms, index, value, valueLength, *status);
   1193        break;
   1194 
   1195    case UDAT_STANDALONE_SHORT_MONTHS:
   1196        DateFormatSymbolsSingleSetter::setStandaloneShortMonth(syms, index, value, valueLength, *status);
   1197        break;
   1198 
   1199    case UDAT_STANDALONE_NARROW_MONTHS:
   1200        DateFormatSymbolsSingleSetter::setStandaloneNarrowMonth(syms, index, value, valueLength, *status);
   1201        break;
   1202 
   1203    case UDAT_WEEKDAYS:
   1204        DateFormatSymbolsSingleSetter::setWeekday(syms, index, value, valueLength, *status);
   1205        break;
   1206 
   1207    case UDAT_SHORT_WEEKDAYS:
   1208        DateFormatSymbolsSingleSetter::setShortWeekday(syms, index, value, valueLength, *status);
   1209        break;
   1210 
   1211    case UDAT_SHORTER_WEEKDAYS:
   1212        DateFormatSymbolsSingleSetter::setShorterWeekday(syms, index, value, valueLength, *status);
   1213        break;
   1214 
   1215    case UDAT_NARROW_WEEKDAYS:
   1216        DateFormatSymbolsSingleSetter::setNarrowWeekday(syms, index, value, valueLength, *status);
   1217        break;
   1218 
   1219    case UDAT_STANDALONE_WEEKDAYS:
   1220        DateFormatSymbolsSingleSetter::setStandaloneWeekday(syms, index, value, valueLength, *status);
   1221        break;
   1222 
   1223    case UDAT_STANDALONE_SHORT_WEEKDAYS:
   1224        DateFormatSymbolsSingleSetter::setStandaloneShortWeekday(syms, index, value, valueLength, *status);
   1225        break;
   1226 
   1227    case UDAT_STANDALONE_SHORTER_WEEKDAYS:
   1228        DateFormatSymbolsSingleSetter::setStandaloneShorterWeekday(syms, index, value, valueLength, *status);
   1229        break;
   1230 
   1231    case UDAT_STANDALONE_NARROW_WEEKDAYS:
   1232        DateFormatSymbolsSingleSetter::setStandaloneNarrowWeekday(syms, index, value, valueLength, *status);
   1233        break;
   1234 
   1235    case UDAT_QUARTERS:
   1236        DateFormatSymbolsSingleSetter::setQuarter(syms, index, value, valueLength, *status);
   1237        break;
   1238 
   1239    case UDAT_SHORT_QUARTERS:
   1240        DateFormatSymbolsSingleSetter::setShortQuarter(syms, index, value, valueLength, *status);
   1241        break;
   1242 
   1243    case UDAT_NARROW_QUARTERS:
   1244        DateFormatSymbolsSingleSetter::setNarrowQuarter(syms, index, value, valueLength, *status);
   1245        break;
   1246        
   1247    case UDAT_STANDALONE_QUARTERS:
   1248        DateFormatSymbolsSingleSetter::setStandaloneQuarter(syms, index, value, valueLength, *status);
   1249        break;
   1250 
   1251    case UDAT_STANDALONE_SHORT_QUARTERS:
   1252        DateFormatSymbolsSingleSetter::setStandaloneShortQuarter(syms, index, value, valueLength, *status);
   1253        break;
   1254 
   1255    case UDAT_STANDALONE_NARROW_QUARTERS:
   1256        DateFormatSymbolsSingleSetter::setStandaloneNarrowQuarter(syms, index, value, valueLength, *status);
   1257        break;
   1258        
   1259    case UDAT_CYCLIC_YEARS_ABBREVIATED:
   1260        DateFormatSymbolsSingleSetter::setShortYearNames(syms, index, value, valueLength, *status);
   1261        break;
   1262 
   1263    case UDAT_ZODIAC_NAMES_ABBREVIATED:
   1264        DateFormatSymbolsSingleSetter::setShortZodiacNames(syms, index, value, valueLength, *status);
   1265        break;
   1266 
   1267    case UDAT_AM_PMS:
   1268        DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status);
   1269        break;
   1270 
   1271    case UDAT_AM_PMS_NARROW:
   1272        DateFormatSymbolsSingleSetter::setAmPmNarrow(syms, index, value, valueLength, *status);
   1273        break;
   1274 
   1275    case UDAT_AM_PMS_WIDE:
   1276        DateFormatSymbolsSingleSetter::setAmPmWide(syms, index, value, valueLength, *status);
   1277        break;
   1278 
   1279    case UDAT_LOCALIZED_CHARS:
   1280        DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status);
   1281        break;
   1282 
   1283    default:
   1284        *status = U_UNSUPPORTED_ERROR;
   1285        break;
   1286        
   1287    }
   1288 }
   1289 
   1290 U_CAPI const char* U_EXPORT2
   1291 udat_getLocaleByType(const UDateFormat *fmt,
   1292                     ULocDataLocaleType type,
   1293                     UErrorCode* status)
   1294 {
   1295    if (fmt == nullptr) {
   1296        if (U_SUCCESS(*status)) {
   1297            *status = U_ILLEGAL_ARGUMENT_ERROR;
   1298        }
   1299        return nullptr;
   1300    }
   1301    return ((Format*)fmt)->getLocaleID(type, *status);
   1302 }
   1303 
   1304 U_CAPI void U_EXPORT2
   1305 udat_setContext(UDateFormat* fmt, UDisplayContext value, UErrorCode* status)
   1306 {
   1307    if (U_FAILURE(*status)) {
   1308        return;
   1309    }
   1310    ((DateFormat*)fmt)->setContext(value, *status);
   1311 }
   1312 
   1313 U_CAPI UDisplayContext U_EXPORT2
   1314 udat_getContext(const UDateFormat* fmt, UDisplayContextType type, UErrorCode* status)
   1315 {
   1316    if (U_FAILURE(*status)) {
   1317        return (UDisplayContext)0;
   1318    }
   1319    return ((const DateFormat*)fmt)->getContext(type, *status);
   1320 }
   1321 
   1322 
   1323 /**
   1324 * Verify that fmt is a RelativeDateFormat. Invalid error if not.
   1325 * @param fmt the UDateFormat, definitely a DateFormat, maybe something else
   1326 * @param status error code, will be set to failure if there is a failure or the fmt is nullptr.
   1327 */
   1328 static void verifyIsRelativeDateFormat(const UDateFormat* fmt, UErrorCode *status) {
   1329   if(U_SUCCESS(*status) &&
   1330       dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==nullptr) {
   1331       *status = U_ILLEGAL_ARGUMENT_ERROR;
   1332   }
   1333 }
   1334 
   1335 
   1336 U_CAPI int32_t U_EXPORT2 
   1337 udat_toPatternRelativeDate(const UDateFormat *fmt,
   1338                           char16_t          *result,
   1339                           int32_t           resultLength,
   1340                           UErrorCode        *status)
   1341 {
   1342    verifyIsRelativeDateFormat(fmt, status);
   1343    if(U_FAILURE(*status)) {
   1344        return -1;
   1345    }
   1346    if (result == nullptr ? resultLength != 0 : resultLength < 0) {
   1347        *status = U_ILLEGAL_ARGUMENT_ERROR;
   1348        return -1;
   1349    }
   1350 
   1351    UnicodeString datePattern;
   1352    if (result != nullptr) {
   1353        // nullptr destination for pure preflighting: empty dummy string
   1354        // otherwise, alias the destination buffer
   1355        datePattern.setTo(result, 0, resultLength);
   1356    }
   1357    ((RelativeDateFormat*)fmt)->toPatternDate(datePattern, *status);
   1358    return datePattern.extract(result, resultLength, *status);
   1359 }
   1360 
   1361 U_CAPI int32_t U_EXPORT2 
   1362 udat_toPatternRelativeTime(const UDateFormat *fmt,
   1363                           char16_t          *result,
   1364                           int32_t           resultLength,
   1365                           UErrorCode        *status)
   1366 {
   1367    verifyIsRelativeDateFormat(fmt, status);
   1368    if(U_FAILURE(*status)) {
   1369        return -1;
   1370    }
   1371    if (result == nullptr ? resultLength != 0 : resultLength < 0) {
   1372        *status = U_ILLEGAL_ARGUMENT_ERROR;
   1373        return -1;
   1374    }
   1375 
   1376    UnicodeString timePattern;
   1377    if (result != nullptr) {
   1378        // nullptr destination for pure preflighting: empty dummy string
   1379        // otherwise, alias the destination buffer
   1380        timePattern.setTo(result, 0, resultLength);
   1381    }
   1382    ((RelativeDateFormat*)fmt)->toPatternTime(timePattern, *status);
   1383    return timePattern.extract(result, resultLength, *status);
   1384 }
   1385 
   1386 U_CAPI void U_EXPORT2 
   1387 udat_applyPatternRelative(UDateFormat *format,
   1388                          const char16_t *datePattern,
   1389                          int32_t     datePatternLength,
   1390                          const char16_t *timePattern,
   1391                          int32_t     timePatternLength,
   1392                          UErrorCode  *status)
   1393 {
   1394    verifyIsRelativeDateFormat(format, status);
   1395    if(U_FAILURE(*status)) return;
   1396    const UnicodeString datePat(datePatternLength == -1, datePattern, datePatternLength);
   1397    const UnicodeString timePat(timePatternLength == -1, timePattern, timePatternLength);
   1398    ((RelativeDateFormat*)format)->applyPatterns(datePat, timePat, *status);
   1399 }
   1400 
   1401 #endif /* #if !UCONFIG_NO_FORMATTING */