• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 *******************************************************************************
3 *   Copyright (C) 1996-2012, 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 "cpputils.h"
26 #include "reldtfmt.h"
27 #include "umutex.h"
28 
29 U_NAMESPACE_USE
30 
31 /**
32  * Verify that fmt is a SimpleDateFormat. Invalid error if not.
33  * @param fmt the UDateFormat, definitely a DateFormat, maybe something else
34  * @param status error code, will be set to failure if there is a familure or the fmt is NULL.
35  */
verifyIsSimpleDateFormat(const UDateFormat * fmt,UErrorCode * status)36 static void verifyIsSimpleDateFormat(const UDateFormat* fmt, UErrorCode *status) {
37    if(U_SUCCESS(*status) &&
38        dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) {
39        *status = U_ILLEGAL_ARGUMENT_ERROR;
40    }
41 }
42 
43 // This mirrors the correspondence between the
44 // SimpleDateFormat::fgPatternIndexToDateFormatField and
45 // SimpleDateFormat::fgPatternIndexToCalendarField arrays.
46 static UCalendarDateFields gDateFieldMapping[] = {
47     UCAL_ERA,                  // UDAT_ERA_FIELD = 0
48     UCAL_YEAR,                 // UDAT_YEAR_FIELD = 1
49     UCAL_MONTH,                // UDAT_MONTH_FIELD = 2
50     UCAL_DATE,                 // UDAT_DATE_FIELD = 3
51     UCAL_HOUR_OF_DAY,          // UDAT_HOUR_OF_DAY1_FIELD = 4
52     UCAL_HOUR_OF_DAY,          // UDAT_HOUR_OF_DAY0_FIELD = 5
53     UCAL_MINUTE,               // UDAT_MINUTE_FIELD = 6
54     UCAL_SECOND,               // UDAT_SECOND_FIELD = 7
55     UCAL_MILLISECOND,          // UDAT_FRACTIONAL_SECOND_FIELD = 8
56     UCAL_DAY_OF_WEEK,          // UDAT_DAY_OF_WEEK_FIELD = 9
57     UCAL_DAY_OF_YEAR,          // UDAT_DAY_OF_YEAR_FIELD = 10
58     UCAL_DAY_OF_WEEK_IN_MONTH, // UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11
59     UCAL_WEEK_OF_YEAR,         // UDAT_WEEK_OF_YEAR_FIELD = 12
60     UCAL_WEEK_OF_MONTH,        // UDAT_WEEK_OF_MONTH_FIELD = 13
61     UCAL_AM_PM,                // UDAT_AM_PM_FIELD = 14
62     UCAL_HOUR,                 // UDAT_HOUR1_FIELD = 15
63     UCAL_HOUR,                 // UDAT_HOUR0_FIELD = 16
64     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_FIELD = 17
65     UCAL_YEAR_WOY,             // UDAT_YEAR_WOY_FIELD = 18
66     UCAL_DOW_LOCAL,            // UDAT_DOW_LOCAL_FIELD = 19
67     UCAL_EXTENDED_YEAR,        // UDAT_EXTENDED_YEAR_FIELD = 20
68     UCAL_JULIAN_DAY,           // UDAT_JULIAN_DAY_FIELD = 21
69     UCAL_MILLISECONDS_IN_DAY,  // UDAT_MILLISECONDS_IN_DAY_FIELD = 22
70     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_RFC_FIELD = 23
71     // UCAL_DST_OFFSET also
72     UCAL_ZONE_OFFSET,          // UDAT_TIMEZONE_GENERIC_FIELD = 24
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
78     UCAL_YEAR,                 // UDAT_YEAR_NAME_FIELD = 30
79     UCAL_FIELD_COUNT,          // UDAT_FIELD_COUNT = 31
80     // UCAL_IS_LEAP_MONTH is not the target of a mapping
81 };
82 
83 U_CAPI UCalendarDateFields U_EXPORT2
udat_toCalendarDateField(UDateFormatField field)84 udat_toCalendarDateField(UDateFormatField field) {
85   return gDateFieldMapping[field];
86 }
87 
88 /* For now- one opener. */
89 static UDateFormatOpener gOpener = NULL;
90 
91 U_INTERNAL void U_EXPORT2
udat_registerOpener(UDateFormatOpener opener,UErrorCode * status)92 udat_registerOpener(UDateFormatOpener opener, UErrorCode *status)
93 {
94   if(U_FAILURE(*status)) return;
95   umtx_lock(NULL);
96   if(gOpener==NULL) {
97     gOpener = opener;
98   } else {
99     *status = U_ILLEGAL_ARGUMENT_ERROR;
100   }
101   umtx_unlock(NULL);
102 }
103 
104 U_INTERNAL UDateFormatOpener U_EXPORT2
udat_unregisterOpener(UDateFormatOpener opener,UErrorCode * status)105 udat_unregisterOpener(UDateFormatOpener opener, UErrorCode *status)
106 {
107   if(U_FAILURE(*status)) return NULL;
108   UDateFormatOpener oldOpener = NULL;
109   umtx_lock(NULL);
110   if(gOpener==NULL || gOpener!=opener) {
111     *status = U_ILLEGAL_ARGUMENT_ERROR;
112   } else {
113     oldOpener=gOpener;
114     gOpener=NULL;
115   }
116   umtx_unlock(NULL);
117   return oldOpener;
118 }
119 
120 
121 
122 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)123 udat_open(UDateFormatStyle  timeStyle,
124           UDateFormatStyle  dateStyle,
125           const char        *locale,
126           const UChar       *tzID,
127           int32_t           tzIDLength,
128           const UChar       *pattern,
129           int32_t           patternLength,
130           UErrorCode        *status)
131 {
132     DateFormat *fmt;
133     if(U_FAILURE(*status)) {
134         return 0;
135     }
136     if(gOpener!=NULL) { // if it's registered
137       fmt = (DateFormat*) (*gOpener)(timeStyle,dateStyle,locale,tzID,tzIDLength,pattern,patternLength,status);
138       if(fmt!=NULL) {
139         return (UDateFormat*)fmt;
140       } // else fall through.
141     }
142     if(timeStyle != UDAT_PATTERN) {
143         if(locale == 0) {
144             fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
145                 (DateFormat::EStyle)timeStyle);
146         }
147         else {
148             fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
149                 (DateFormat::EStyle)timeStyle,
150                 Locale(locale));
151         }
152     }
153     else {
154         UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength);
155 
156         if(locale == 0) {
157             fmt = new SimpleDateFormat(pat, *status);
158         }
159         else {
160             fmt = new SimpleDateFormat(pat, Locale(locale), *status);
161         }
162     }
163 
164     if(fmt == 0) {
165         *status = U_MEMORY_ALLOCATION_ERROR;
166         return 0;
167     }
168 
169     if(tzID != 0) {
170         TimeZone *zone = TimeZone::createTimeZone(UnicodeString((UBool)(tzIDLength == -1), tzID, tzIDLength));
171         if(zone == 0) {
172             *status = U_MEMORY_ALLOCATION_ERROR;
173             delete fmt;
174             return 0;
175         }
176         fmt->adoptTimeZone(zone);
177     }
178 
179     return (UDateFormat*)fmt;
180 }
181 
182 
183 U_CAPI void U_EXPORT2
udat_close(UDateFormat * format)184 udat_close(UDateFormat* format)
185 {
186     delete (DateFormat*)format;
187 }
188 
189 U_CAPI UDateFormat* U_EXPORT2
udat_clone(const UDateFormat * fmt,UErrorCode * status)190 udat_clone(const UDateFormat *fmt,
191        UErrorCode *status)
192 {
193     if(U_FAILURE(*status)) return 0;
194 
195     Format *res = ((DateFormat*)fmt)->clone();
196 
197     if(res == 0) {
198         *status = U_MEMORY_ALLOCATION_ERROR;
199         return 0;
200     }
201 
202     return (UDateFormat*) res;
203 }
204 
205 U_CAPI int32_t U_EXPORT2
udat_format(const UDateFormat * format,UDate dateToFormat,UChar * result,int32_t resultLength,UFieldPosition * position,UErrorCode * status)206 udat_format(    const    UDateFormat*    format,
207         UDate           dateToFormat,
208         UChar*          result,
209         int32_t         resultLength,
210         UFieldPosition* position,
211         UErrorCode*     status)
212 {
213     if(U_FAILURE(*status)) return -1;
214 
215     UnicodeString res;
216     if(!(result==NULL && resultLength==0)) {
217         // NULL destination for pure preflighting: empty dummy string
218         // otherwise, alias the destination buffer
219         res.setTo(result, 0, resultLength);
220     }
221 
222     FieldPosition fp;
223 
224     if(position != 0)
225         fp.setField(position->field);
226 
227     ((DateFormat*)format)->format(dateToFormat, res, fp);
228 
229     if(position != 0) {
230         position->beginIndex = fp.getBeginIndex();
231         position->endIndex = fp.getEndIndex();
232     }
233 
234     return res.extract(result, resultLength, *status);
235 }
236 
237 U_CAPI UDate U_EXPORT2
udat_parse(const UDateFormat * format,const UChar * text,int32_t textLength,int32_t * parsePos,UErrorCode * status)238 udat_parse(    const    UDateFormat*        format,
239         const    UChar*          text,
240         int32_t         textLength,
241         int32_t         *parsePos,
242         UErrorCode      *status)
243 {
244     if(U_FAILURE(*status)) return (UDate)0;
245 
246     const UnicodeString src((UBool)(textLength == -1), text, textLength);
247     ParsePosition pp;
248     int32_t stackParsePos = 0;
249     UDate res;
250 
251     if(parsePos == NULL) {
252         parsePos = &stackParsePos;
253     }
254 
255     pp.setIndex(*parsePos);
256 
257     res = ((DateFormat*)format)->parse(src, pp);
258 
259     if(pp.getErrorIndex() == -1)
260         *parsePos = pp.getIndex();
261     else {
262         *parsePos = pp.getErrorIndex();
263         *status = U_PARSE_ERROR;
264     }
265 
266     return res;
267 }
268 
269 U_CAPI void U_EXPORT2
udat_parseCalendar(const UDateFormat * format,UCalendar * calendar,const UChar * text,int32_t textLength,int32_t * parsePos,UErrorCode * status)270 udat_parseCalendar(const    UDateFormat*    format,
271                             UCalendar*      calendar,
272                    const    UChar*          text,
273                             int32_t         textLength,
274                             int32_t         *parsePos,
275                             UErrorCode      *status)
276 {
277     if(U_FAILURE(*status)) return;
278 
279     const UnicodeString src((UBool)(textLength == -1), text, textLength);
280     ParsePosition pp;
281 
282     if(parsePos != 0)
283         pp.setIndex(*parsePos);
284 
285     ((DateFormat*)format)->parse(src, *(Calendar*)calendar, pp);
286 
287     if(parsePos != 0) {
288         if(pp.getErrorIndex() == -1)
289             *parsePos = pp.getIndex();
290         else {
291             *parsePos = pp.getErrorIndex();
292             *status = U_PARSE_ERROR;
293         }
294     }
295 }
296 
297 U_CAPI UBool U_EXPORT2
udat_isLenient(const UDateFormat * fmt)298 udat_isLenient(const UDateFormat* fmt)
299 {
300     return ((DateFormat*)fmt)->isLenient();
301 }
302 
303 U_CAPI void U_EXPORT2
udat_setLenient(UDateFormat * fmt,UBool isLenient)304 udat_setLenient(    UDateFormat*    fmt,
305             UBool          isLenient)
306 {
307     ((DateFormat*)fmt)->setLenient(isLenient);
308 }
309 
310 U_CAPI const UCalendar* U_EXPORT2
udat_getCalendar(const UDateFormat * fmt)311 udat_getCalendar(const UDateFormat* fmt)
312 {
313     return (const UCalendar*) ((DateFormat*)fmt)->getCalendar();
314 }
315 
316 U_CAPI void U_EXPORT2
udat_setCalendar(UDateFormat * fmt,const UCalendar * calendarToSet)317 udat_setCalendar(UDateFormat*    fmt,
318                  const   UCalendar*      calendarToSet)
319 {
320     ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet));
321 }
322 
323 U_CAPI const UNumberFormat* U_EXPORT2
udat_getNumberFormat(const UDateFormat * fmt)324 udat_getNumberFormat(const UDateFormat* fmt)
325 {
326     return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat();
327 }
328 
329 U_CAPI void U_EXPORT2
udat_setNumberFormat(UDateFormat * fmt,const UNumberFormat * numberFormatToSet)330 udat_setNumberFormat(UDateFormat*    fmt,
331                      const   UNumberFormat*  numberFormatToSet)
332 {
333     ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet));
334 }
335 
336 U_CAPI const char* U_EXPORT2
udat_getAvailable(int32_t index)337 udat_getAvailable(int32_t index)
338 {
339     return uloc_getAvailable(index);
340 }
341 
342 U_CAPI int32_t U_EXPORT2
udat_countAvailable()343 udat_countAvailable()
344 {
345     return uloc_countAvailable();
346 }
347 
348 U_CAPI UDate U_EXPORT2
udat_get2DigitYearStart(const UDateFormat * fmt,UErrorCode * status)349 udat_get2DigitYearStart(    const   UDateFormat     *fmt,
350                         UErrorCode      *status)
351 {
352     verifyIsSimpleDateFormat(fmt, status);
353     if(U_FAILURE(*status)) return (UDate)0;
354     return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status);
355 }
356 
357 U_CAPI void U_EXPORT2
udat_set2DigitYearStart(UDateFormat * fmt,UDate d,UErrorCode * status)358 udat_set2DigitYearStart(    UDateFormat     *fmt,
359                         UDate           d,
360                         UErrorCode      *status)
361 {
362     verifyIsSimpleDateFormat(fmt, status);
363     if(U_FAILURE(*status)) return;
364     ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status);
365 }
366 
367 U_CAPI int32_t U_EXPORT2
udat_toPattern(const UDateFormat * fmt,UBool localized,UChar * result,int32_t resultLength,UErrorCode * status)368 udat_toPattern(    const   UDateFormat     *fmt,
369         UBool          localized,
370         UChar           *result,
371         int32_t         resultLength,
372         UErrorCode      *status)
373 {
374     if(U_FAILURE(*status)) return -1;
375 
376     UnicodeString res;
377     if(!(result==NULL && resultLength==0)) {
378         // NULL destination for pure preflighting: empty dummy string
379         // otherwise, alias the destination buffer
380         res.setTo(result, 0, resultLength);
381     }
382 
383     const DateFormat *df=reinterpret_cast<const DateFormat *>(fmt);
384     const SimpleDateFormat *sdtfmt=dynamic_cast<const SimpleDateFormat *>(df);
385     const RelativeDateFormat *reldtfmt;
386     if (sdtfmt!=NULL) {
387         if(localized)
388             sdtfmt->toLocalizedPattern(res, *status);
389         else
390             sdtfmt->toPattern(res);
391     } else if (!localized && (reldtfmt=dynamic_cast<const RelativeDateFormat *>(df))!=NULL) {
392         reldtfmt->toPattern(res, *status);
393     } else {
394         *status = U_ILLEGAL_ARGUMENT_ERROR;
395         return -1;
396     }
397 
398     return res.extract(result, resultLength, *status);
399 }
400 
401 // TODO: should this take an UErrorCode?
402 // A: Yes. Of course.
403 U_CAPI void U_EXPORT2
udat_applyPattern(UDateFormat * format,UBool localized,const UChar * pattern,int32_t patternLength)404 udat_applyPattern(  UDateFormat     *format,
405                     UBool          localized,
406                     const   UChar           *pattern,
407                     int32_t         patternLength)
408 {
409     const UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength);
410     UErrorCode status = U_ZERO_ERROR;
411 
412     verifyIsSimpleDateFormat(format, &status);
413     if(U_FAILURE(status)) {
414         return;
415     }
416 
417     if(localized)
418         ((SimpleDateFormat*)format)->applyLocalizedPattern(pat, status);
419     else
420         ((SimpleDateFormat*)format)->applyPattern(pat);
421 }
422 
423 U_CAPI int32_t U_EXPORT2
udat_getSymbols(const UDateFormat * fmt,UDateFormatSymbolType type,int32_t index,UChar * result,int32_t resultLength,UErrorCode * status)424 udat_getSymbols(const   UDateFormat     *fmt,
425                 UDateFormatSymbolType   type,
426                 int32_t                 index,
427                 UChar                   *result,
428                 int32_t                 resultLength,
429                 UErrorCode              *status)
430 {
431     const DateFormatSymbols *syms;
432     const SimpleDateFormat* sdtfmt;
433     const RelativeDateFormat* rdtfmt;
434     if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
435     	syms = sdtfmt->getDateFormatSymbols();
436     } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
437     	syms = rdtfmt->getDateFormatSymbols();
438     } else {
439         return -1;
440     }
441     int32_t count;
442     const UnicodeString *res = NULL;
443 
444     switch(type) {
445     case UDAT_ERAS:
446         res = syms->getEras(count);
447         break;
448 
449     case UDAT_ERA_NAMES:
450         res = syms->getEraNames(count);
451         break;
452 
453     case UDAT_MONTHS:
454         res = syms->getMonths(count);
455         break;
456 
457     case UDAT_SHORT_MONTHS:
458         res = syms->getShortMonths(count);
459         break;
460 
461     case UDAT_WEEKDAYS:
462         res = syms->getWeekdays(count);
463         break;
464 
465     case UDAT_SHORT_WEEKDAYS:
466         res = syms->getShortWeekdays(count);
467         break;
468 
469     case UDAT_AM_PMS:
470         res = syms->getAmPmStrings(count);
471         break;
472 
473     case UDAT_LOCALIZED_CHARS:
474         {
475             UnicodeString res1;
476             if(!(result==NULL && resultLength==0)) {
477                 // NULL destination for pure preflighting: empty dummy string
478                 // otherwise, alias the destination buffer
479                 res1.setTo(result, 0, resultLength);
480             }
481             syms->getLocalPatternChars(res1);
482             return res1.extract(result, resultLength, *status);
483         }
484 
485     case UDAT_NARROW_MONTHS:
486         res = syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
487         break;
488 
489     case UDAT_NARROW_WEEKDAYS:
490         res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
491         break;
492 
493     case UDAT_STANDALONE_MONTHS:
494         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
495         break;
496 
497     case UDAT_STANDALONE_SHORT_MONTHS:
498         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
499         break;
500 
501     case UDAT_STANDALONE_NARROW_MONTHS:
502         res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
503         break;
504 
505     case UDAT_STANDALONE_WEEKDAYS:
506         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
507         break;
508 
509     case UDAT_STANDALONE_SHORT_WEEKDAYS:
510         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
511         break;
512 
513     case UDAT_STANDALONE_NARROW_WEEKDAYS:
514         res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
515         break;
516 
517     case UDAT_QUARTERS:
518         res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
519         break;
520 
521     case UDAT_SHORT_QUARTERS:
522         res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
523         break;
524 
525     case UDAT_STANDALONE_QUARTERS:
526         res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
527         break;
528 
529     case UDAT_STANDALONE_SHORT_QUARTERS:
530         res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
531         break;
532 
533     }
534 
535     if(index < count) {
536         return res[index].extract(result, resultLength, *status);
537     }
538     return 0;
539 }
540 
541 // TODO: also needs an errorCode.
542 U_CAPI int32_t U_EXPORT2
udat_countSymbols(const UDateFormat * fmt,UDateFormatSymbolType type)543 udat_countSymbols(    const    UDateFormat                *fmt,
544             UDateFormatSymbolType    type)
545 {
546     const DateFormatSymbols *syms;
547     const SimpleDateFormat* sdtfmt;
548     const RelativeDateFormat* rdtfmt;
549     if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
550     	syms = sdtfmt->getDateFormatSymbols();
551     } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) {
552     	syms = rdtfmt->getDateFormatSymbols();
553     } else {
554         return 0;
555     }
556     int32_t count = 0;
557 
558     switch(type) {
559     case UDAT_ERAS:
560         syms->getEras(count);
561         break;
562 
563     case UDAT_MONTHS:
564         syms->getMonths(count);
565         break;
566 
567     case UDAT_SHORT_MONTHS:
568         syms->getShortMonths(count);
569         break;
570 
571     case UDAT_WEEKDAYS:
572         syms->getWeekdays(count);
573         break;
574 
575     case UDAT_SHORT_WEEKDAYS:
576         syms->getShortWeekdays(count);
577         break;
578 
579     case UDAT_AM_PMS:
580         syms->getAmPmStrings(count);
581         break;
582 
583     case UDAT_LOCALIZED_CHARS:
584         count = 1;
585         break;
586 
587     case UDAT_ERA_NAMES:
588         syms->getEraNames(count);
589         break;
590 
591     case UDAT_NARROW_MONTHS:
592         syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
593         break;
594 
595     case UDAT_NARROW_WEEKDAYS:
596         syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW);
597         break;
598 
599     case UDAT_STANDALONE_MONTHS:
600         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
601         break;
602 
603     case UDAT_STANDALONE_SHORT_MONTHS:
604         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
605         break;
606 
607     case UDAT_STANDALONE_NARROW_MONTHS:
608         syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
609         break;
610 
611     case UDAT_STANDALONE_WEEKDAYS:
612         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
613         break;
614 
615     case UDAT_STANDALONE_SHORT_WEEKDAYS:
616         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
617         break;
618 
619     case UDAT_STANDALONE_NARROW_WEEKDAYS:
620         syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW);
621         break;
622 
623     case UDAT_QUARTERS:
624         syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE);
625         break;
626 
627     case UDAT_SHORT_QUARTERS:
628         syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED);
629         break;
630 
631     case UDAT_STANDALONE_QUARTERS:
632         syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE);
633         break;
634 
635     case UDAT_STANDALONE_SHORT_QUARTERS:
636         syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED);
637         break;
638 
639     }
640 
641     return count;
642 }
643 
644 U_NAMESPACE_BEGIN
645 
646 /*
647  * This DateFormatSymbolsSingleSetter class is a friend of DateFormatSymbols
648  * solely for the purpose of avoiding to clone the array of strings
649  * just to modify one of them and then setting all of them back.
650  * For example, the old code looked like this:
651  *  case UDAT_MONTHS:
652  *    res = syms->getMonths(count);
653  *    array = new UnicodeString[count];
654  *    if(array == 0) {
655  *      *status = U_MEMORY_ALLOCATION_ERROR;
656  *      return;
657  *    }
658  *    uprv_arrayCopy(res, array, count);
659  *    if(index < count)
660  *      array[index] = val;
661  *    syms->setMonths(array, count);
662  *    break;
663  *
664  * Even worse, the old code actually cloned the entire DateFormatSymbols object,
665  * cloned one value array, changed one value, and then made the SimpleDateFormat
666  * replace its DateFormatSymbols object with the new one.
667  *
668  * markus 2002-oct-14
669  */
670 class DateFormatSymbolsSingleSetter /* not : public UObject because all methods are static */ {
671 public:
672     static void
setSymbol(UnicodeString * array,int32_t count,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)673         setSymbol(UnicodeString *array, int32_t count, int32_t index,
674         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
675     {
676         if(array!=NULL) {
677             if(index>=count) {
678                 errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
679             } else if(value==NULL) {
680                 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
681             } else {
682                 array[index].setTo(value, valueLength);
683             }
684         }
685     }
686 
687     static void
setEra(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)688         setEra(DateFormatSymbols *syms, int32_t index,
689         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
690     {
691         setSymbol(syms->fEras, syms->fErasCount, index, value, valueLength, errorCode);
692     }
693 
694     static void
setEraName(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)695         setEraName(DateFormatSymbols *syms, int32_t index,
696         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
697     {
698         setSymbol(syms->fEraNames, syms->fEraNamesCount, index, value, valueLength, errorCode);
699     }
700 
701     static void
setMonth(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)702         setMonth(DateFormatSymbols *syms, int32_t index,
703         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
704     {
705         setSymbol(syms->fMonths, syms->fMonthsCount, index, value, valueLength, errorCode);
706     }
707 
708     static void
setShortMonth(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)709         setShortMonth(DateFormatSymbols *syms, int32_t index,
710         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
711     {
712         setSymbol(syms->fShortMonths, syms->fShortMonthsCount, index, value, valueLength, errorCode);
713     }
714 
715     static void
setNarrowMonth(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)716         setNarrowMonth(DateFormatSymbols *syms, int32_t index,
717         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
718     {
719         setSymbol(syms->fNarrowMonths, syms->fNarrowMonthsCount, index, value, valueLength, errorCode);
720     }
721 
722     static void
setStandaloneMonth(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)723         setStandaloneMonth(DateFormatSymbols *syms, int32_t index,
724         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
725     {
726         setSymbol(syms->fStandaloneMonths, syms->fStandaloneMonthsCount, index, value, valueLength, errorCode);
727     }
728 
729     static void
setStandaloneShortMonth(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)730         setStandaloneShortMonth(DateFormatSymbols *syms, int32_t index,
731         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
732     {
733         setSymbol(syms->fStandaloneShortMonths, syms->fStandaloneShortMonthsCount, index, value, valueLength, errorCode);
734     }
735 
736     static void
setStandaloneNarrowMonth(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)737         setStandaloneNarrowMonth(DateFormatSymbols *syms, int32_t index,
738         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
739     {
740         setSymbol(syms->fStandaloneNarrowMonths, syms->fStandaloneNarrowMonthsCount, index, value, valueLength, errorCode);
741     }
742 
743     static void
setWeekday(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)744         setWeekday(DateFormatSymbols *syms, int32_t index,
745         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
746     {
747         setSymbol(syms->fWeekdays, syms->fWeekdaysCount, index, value, valueLength, errorCode);
748     }
749 
750     static void
setShortWeekday(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)751         setShortWeekday(DateFormatSymbols *syms, int32_t index,
752         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
753     {
754         setSymbol(syms->fShortWeekdays, syms->fShortWeekdaysCount, index, value, valueLength, errorCode);
755     }
756 
757     static void
setNarrowWeekday(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)758         setNarrowWeekday(DateFormatSymbols *syms, int32_t index,
759         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
760     {
761         setSymbol(syms->fNarrowWeekdays, syms->fNarrowWeekdaysCount, index, value, valueLength, errorCode);
762     }
763 
764     static void
setStandaloneWeekday(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)765         setStandaloneWeekday(DateFormatSymbols *syms, int32_t index,
766         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
767     {
768         setSymbol(syms->fStandaloneWeekdays, syms->fStandaloneWeekdaysCount, index, value, valueLength, errorCode);
769     }
770 
771     static void
setStandaloneShortWeekday(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)772         setStandaloneShortWeekday(DateFormatSymbols *syms, int32_t index,
773         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
774     {
775         setSymbol(syms->fStandaloneShortWeekdays, syms->fStandaloneShortWeekdaysCount, index, value, valueLength, errorCode);
776     }
777 
778     static void
setStandaloneNarrowWeekday(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)779         setStandaloneNarrowWeekday(DateFormatSymbols *syms, int32_t index,
780         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
781     {
782         setSymbol(syms->fStandaloneNarrowWeekdays, syms->fStandaloneNarrowWeekdaysCount, index, value, valueLength, errorCode);
783     }
784 
785     static void
setQuarter(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)786         setQuarter(DateFormatSymbols *syms, int32_t index,
787         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
788     {
789         setSymbol(syms->fQuarters, syms->fQuartersCount, index, value, valueLength, errorCode);
790     }
791 
792     static void
setShortQuarter(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)793         setShortQuarter(DateFormatSymbols *syms, int32_t index,
794         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
795     {
796         setSymbol(syms->fShortQuarters, syms->fShortQuartersCount, index, value, valueLength, errorCode);
797     }
798 
799     static void
setStandaloneQuarter(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)800         setStandaloneQuarter(DateFormatSymbols *syms, int32_t index,
801         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
802     {
803         setSymbol(syms->fStandaloneQuarters, syms->fStandaloneQuartersCount, index, value, valueLength, errorCode);
804     }
805 
806     static void
setStandaloneShortQuarter(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)807         setStandaloneShortQuarter(DateFormatSymbols *syms, int32_t index,
808         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
809     {
810         setSymbol(syms->fStandaloneShortQuarters, syms->fStandaloneShortQuartersCount, index, value, valueLength, errorCode);
811     }
812 
813     static void
setAmPm(DateFormatSymbols * syms,int32_t index,const UChar * value,int32_t valueLength,UErrorCode & errorCode)814         setAmPm(DateFormatSymbols *syms, int32_t index,
815         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
816     {
817         setSymbol(syms->fAmPms, syms->fAmPmsCount, index, value, valueLength, errorCode);
818     }
819 
820     static void
setLocalPatternChars(DateFormatSymbols * syms,const UChar * value,int32_t valueLength,UErrorCode & errorCode)821         setLocalPatternChars(DateFormatSymbols *syms,
822         const UChar *value, int32_t valueLength, UErrorCode &errorCode)
823     {
824         setSymbol(&syms->fLocalPatternChars, 1, 0, value, valueLength, errorCode);
825     }
826 };
827 
828 U_NAMESPACE_END
829 
830 U_CAPI void U_EXPORT2
udat_setSymbols(UDateFormat * format,UDateFormatSymbolType type,int32_t index,UChar * value,int32_t valueLength,UErrorCode * status)831 udat_setSymbols(    UDateFormat             *format,
832             UDateFormatSymbolType   type,
833             int32_t                 index,
834             UChar                   *value,
835             int32_t                 valueLength,
836             UErrorCode              *status)
837 {
838     verifyIsSimpleDateFormat(format, status);
839     if(U_FAILURE(*status)) return;
840 
841     DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols();
842 
843     switch(type) {
844     case UDAT_ERAS:
845         DateFormatSymbolsSingleSetter::setEra(syms, index, value, valueLength, *status);
846         break;
847 
848     case UDAT_ERA_NAMES:
849         DateFormatSymbolsSingleSetter::setEraName(syms, index, value, valueLength, *status);
850         break;
851 
852     case UDAT_MONTHS:
853         DateFormatSymbolsSingleSetter::setMonth(syms, index, value, valueLength, *status);
854         break;
855 
856     case UDAT_SHORT_MONTHS:
857         DateFormatSymbolsSingleSetter::setShortMonth(syms, index, value, valueLength, *status);
858         break;
859 
860     case UDAT_NARROW_MONTHS:
861         DateFormatSymbolsSingleSetter::setNarrowMonth(syms, index, value, valueLength, *status);
862         break;
863 
864     case UDAT_STANDALONE_MONTHS:
865         DateFormatSymbolsSingleSetter::setStandaloneMonth(syms, index, value, valueLength, *status);
866         break;
867 
868     case UDAT_STANDALONE_SHORT_MONTHS:
869         DateFormatSymbolsSingleSetter::setStandaloneShortMonth(syms, index, value, valueLength, *status);
870         break;
871 
872     case UDAT_STANDALONE_NARROW_MONTHS:
873         DateFormatSymbolsSingleSetter::setStandaloneNarrowMonth(syms, index, value, valueLength, *status);
874         break;
875 
876     case UDAT_WEEKDAYS:
877         DateFormatSymbolsSingleSetter::setWeekday(syms, index, value, valueLength, *status);
878         break;
879 
880     case UDAT_SHORT_WEEKDAYS:
881         DateFormatSymbolsSingleSetter::setShortWeekday(syms, index, value, valueLength, *status);
882         break;
883 
884     case UDAT_NARROW_WEEKDAYS:
885         DateFormatSymbolsSingleSetter::setNarrowWeekday(syms, index, value, valueLength, *status);
886         break;
887 
888     case UDAT_STANDALONE_WEEKDAYS:
889         DateFormatSymbolsSingleSetter::setStandaloneWeekday(syms, index, value, valueLength, *status);
890         break;
891 
892     case UDAT_STANDALONE_SHORT_WEEKDAYS:
893         DateFormatSymbolsSingleSetter::setStandaloneShortWeekday(syms, index, value, valueLength, *status);
894         break;
895 
896     case UDAT_STANDALONE_NARROW_WEEKDAYS:
897         DateFormatSymbolsSingleSetter::setStandaloneNarrowWeekday(syms, index, value, valueLength, *status);
898         break;
899 
900     case UDAT_QUARTERS:
901         DateFormatSymbolsSingleSetter::setQuarter(syms, index, value, valueLength, *status);
902         break;
903 
904     case UDAT_SHORT_QUARTERS:
905         DateFormatSymbolsSingleSetter::setShortQuarter(syms, index, value, valueLength, *status);
906         break;
907 
908     case UDAT_STANDALONE_QUARTERS:
909         DateFormatSymbolsSingleSetter::setStandaloneQuarter(syms, index, value, valueLength, *status);
910         break;
911 
912     case UDAT_STANDALONE_SHORT_QUARTERS:
913         DateFormatSymbolsSingleSetter::setStandaloneShortQuarter(syms, index, value, valueLength, *status);
914         break;
915 
916     case UDAT_AM_PMS:
917         DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status);
918         break;
919 
920     case UDAT_LOCALIZED_CHARS:
921         DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status);
922         break;
923 
924     default:
925         *status = U_UNSUPPORTED_ERROR;
926         break;
927 
928     }
929 }
930 
931 U_CAPI const char* U_EXPORT2
udat_getLocaleByType(const UDateFormat * fmt,ULocDataLocaleType type,UErrorCode * status)932 udat_getLocaleByType(const UDateFormat *fmt,
933                      ULocDataLocaleType type,
934                      UErrorCode* status)
935 {
936     if (fmt == NULL) {
937         if (U_SUCCESS(*status)) {
938             *status = U_ILLEGAL_ARGUMENT_ERROR;
939         }
940         return NULL;
941     }
942     return ((Format*)fmt)->getLocaleID(type, *status);
943 }
944 
945 
946 U_CAPI void U_EXPORT2
udat_setContext(UDateFormat * fmt,UDisplayContext value,UErrorCode * status)947 udat_setContext(UDateFormat* fmt, UDisplayContext value, UErrorCode* status)
948 {
949     verifyIsSimpleDateFormat(fmt, status);
950     if (U_FAILURE(*status)) {
951         return;
952     }
953     ((SimpleDateFormat*)fmt)->setContext(value, *status);
954 }
955 
956 U_CAPI UDisplayContext U_EXPORT2
udat_getContext(UDateFormat * fmt,UDisplayContextType type,UErrorCode * status)957 udat_getContext(UDateFormat* fmt, UDisplayContextType type, UErrorCode* status)
958 {
959     verifyIsSimpleDateFormat(fmt, status);
960     if (U_FAILURE(*status)) {
961         return (UDisplayContext)0;
962     }
963     return ((SimpleDateFormat*)fmt)->getContext(type, *status);
964 }
965 
966 
967 /**
968  * Verify that fmt is a RelativeDateFormat. Invalid error if not.
969  * @param fmt the UDateFormat, definitely a DateFormat, maybe something else
970  * @param status error code, will be set to failure if there is a familure or the fmt is NULL.
971  */
verifyIsRelativeDateFormat(const UDateFormat * fmt,UErrorCode * status)972 static void verifyIsRelativeDateFormat(const UDateFormat* fmt, UErrorCode *status) {
973    if(U_SUCCESS(*status) &&
974        dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) {
975        *status = U_ILLEGAL_ARGUMENT_ERROR;
976    }
977 }
978 
979 
980 U_CAPI int32_t U_EXPORT2
udat_toPatternRelativeDate(const UDateFormat * fmt,UChar * result,int32_t resultLength,UErrorCode * status)981 udat_toPatternRelativeDate(const UDateFormat *fmt,
982                            UChar             *result,
983                            int32_t           resultLength,
984                            UErrorCode        *status)
985 {
986     verifyIsRelativeDateFormat(fmt, status);
987     if(U_FAILURE(*status)) return -1;
988 
989     UnicodeString datePattern;
990     if(!(result==NULL && resultLength==0)) {
991         // NULL destination for pure preflighting: empty dummy string
992         // otherwise, alias the destination buffer
993         datePattern.setTo(result, 0, resultLength);
994     }
995     ((RelativeDateFormat*)fmt)->toPatternDate(datePattern, *status);
996     return datePattern.extract(result, resultLength, *status);
997 }
998 
999 U_CAPI int32_t U_EXPORT2
udat_toPatternRelativeTime(const UDateFormat * fmt,UChar * result,int32_t resultLength,UErrorCode * status)1000 udat_toPatternRelativeTime(const UDateFormat *fmt,
1001                            UChar             *result,
1002                            int32_t           resultLength,
1003                            UErrorCode        *status)
1004 {
1005     verifyIsRelativeDateFormat(fmt, status);
1006     if(U_FAILURE(*status)) return -1;
1007 
1008     UnicodeString timePattern;
1009     if(!(result==NULL && resultLength==0)) {
1010         // NULL destination for pure preflighting: empty dummy string
1011         // otherwise, alias the destination buffer
1012         timePattern.setTo(result, 0, resultLength);
1013     }
1014     ((RelativeDateFormat*)fmt)->toPatternTime(timePattern, *status);
1015     return timePattern.extract(result, resultLength, *status);
1016 }
1017 
1018 U_CAPI void U_EXPORT2
udat_applyPatternRelative(UDateFormat * format,const UChar * datePattern,int32_t datePatternLength,const UChar * timePattern,int32_t timePatternLength,UErrorCode * status)1019 udat_applyPatternRelative(UDateFormat *format,
1020                           const UChar *datePattern,
1021                           int32_t     datePatternLength,
1022                           const UChar *timePattern,
1023                           int32_t     timePatternLength,
1024                           UErrorCode  *status)
1025 {
1026     verifyIsRelativeDateFormat(format, status);
1027     if(U_FAILURE(*status)) return;
1028     const UnicodeString datePat((UBool)(datePatternLength == -1), datePattern, datePatternLength);
1029     const UnicodeString timePat((UBool)(timePatternLength == -1), timePattern, timePatternLength);
1030     ((RelativeDateFormat*)format)->applyPatterns(datePat, timePat, *status);
1031 }
1032 
1033 #endif /* #if !UCONFIG_NO_FORMATTING */
1034