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