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