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