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