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