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