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