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