michael@0: /* michael@0: ******************************************************************************* michael@0: * Copyright (C) 1996-2013, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: ******************************************************************************* michael@0: */ michael@0: michael@0: #include "unicode/utypes.h" michael@0: michael@0: #if !UCONFIG_NO_FORMATTING michael@0: michael@0: #include "unicode/udat.h" michael@0: michael@0: #include "unicode/uloc.h" michael@0: #include "unicode/datefmt.h" michael@0: #include "unicode/timezone.h" michael@0: #include "unicode/smpdtfmt.h" michael@0: #include "unicode/fieldpos.h" michael@0: #include "unicode/parsepos.h" michael@0: #include "unicode/calendar.h" michael@0: #include "unicode/numfmt.h" michael@0: #include "unicode/dtfmtsym.h" michael@0: #include "unicode/ustring.h" michael@0: #include "unicode/udisplaycontext.h" michael@0: #include "cpputils.h" michael@0: #include "reldtfmt.h" michael@0: #include "umutex.h" michael@0: michael@0: U_NAMESPACE_USE michael@0: michael@0: /** michael@0: * Verify that fmt is a SimpleDateFormat. Invalid error if not. michael@0: * @param fmt the UDateFormat, definitely a DateFormat, maybe something else michael@0: * @param status error code, will be set to failure if there is a familure or the fmt is NULL. michael@0: */ michael@0: static void verifyIsSimpleDateFormat(const UDateFormat* fmt, UErrorCode *status) { michael@0: if(U_SUCCESS(*status) && michael@0: dynamic_cast(reinterpret_cast(fmt))==NULL) { michael@0: *status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: } michael@0: } michael@0: michael@0: // This mirrors the correspondence between the michael@0: // SimpleDateFormat::fgPatternIndexToDateFormatField and michael@0: // SimpleDateFormat::fgPatternIndexToCalendarField arrays. michael@0: static UCalendarDateFields gDateFieldMapping[] = { michael@0: UCAL_ERA, // UDAT_ERA_FIELD = 0 michael@0: UCAL_YEAR, // UDAT_YEAR_FIELD = 1 michael@0: UCAL_MONTH, // UDAT_MONTH_FIELD = 2 michael@0: UCAL_DATE, // UDAT_DATE_FIELD = 3 michael@0: UCAL_HOUR_OF_DAY, // UDAT_HOUR_OF_DAY1_FIELD = 4 michael@0: UCAL_HOUR_OF_DAY, // UDAT_HOUR_OF_DAY0_FIELD = 5 michael@0: UCAL_MINUTE, // UDAT_MINUTE_FIELD = 6 michael@0: UCAL_SECOND, // UDAT_SECOND_FIELD = 7 michael@0: UCAL_MILLISECOND, // UDAT_FRACTIONAL_SECOND_FIELD = 8 michael@0: UCAL_DAY_OF_WEEK, // UDAT_DAY_OF_WEEK_FIELD = 9 michael@0: UCAL_DAY_OF_YEAR, // UDAT_DAY_OF_YEAR_FIELD = 10 michael@0: UCAL_DAY_OF_WEEK_IN_MONTH, // UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11 michael@0: UCAL_WEEK_OF_YEAR, // UDAT_WEEK_OF_YEAR_FIELD = 12 michael@0: UCAL_WEEK_OF_MONTH, // UDAT_WEEK_OF_MONTH_FIELD = 13 michael@0: UCAL_AM_PM, // UDAT_AM_PM_FIELD = 14 michael@0: UCAL_HOUR, // UDAT_HOUR1_FIELD = 15 michael@0: UCAL_HOUR, // UDAT_HOUR0_FIELD = 16 michael@0: UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_FIELD = 17 michael@0: UCAL_YEAR_WOY, // UDAT_YEAR_WOY_FIELD = 18 michael@0: UCAL_DOW_LOCAL, // UDAT_DOW_LOCAL_FIELD = 19 michael@0: UCAL_EXTENDED_YEAR, // UDAT_EXTENDED_YEAR_FIELD = 20 michael@0: UCAL_JULIAN_DAY, // UDAT_JULIAN_DAY_FIELD = 21 michael@0: UCAL_MILLISECONDS_IN_DAY, // UDAT_MILLISECONDS_IN_DAY_FIELD = 22 michael@0: UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_RFC_FIELD = 23 michael@0: // UCAL_DST_OFFSET also michael@0: UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_GENERIC_FIELD = 24 michael@0: UCAL_DOW_LOCAL, // UDAT_STANDALONE_DAY_FIELD = 25 michael@0: UCAL_MONTH, // UDAT_STANDALONE_MONTH_FIELD = 26 michael@0: UCAL_MONTH, // UDAT_QUARTER_FIELD = 27 michael@0: UCAL_MONTH, // UDAT_STANDALONE_QUARTER_FIELD = 28 michael@0: UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_SPECIAL_FIELD = 29 michael@0: UCAL_YEAR, // UDAT_YEAR_NAME_FIELD = 30 michael@0: UCAL_FIELD_COUNT, // UDAT_FIELD_COUNT = 31 michael@0: // UCAL_IS_LEAP_MONTH is not the target of a mapping michael@0: }; michael@0: michael@0: U_CAPI UCalendarDateFields U_EXPORT2 michael@0: udat_toCalendarDateField(UDateFormatField field) { michael@0: return gDateFieldMapping[field]; michael@0: } michael@0: michael@0: /* For now- one opener. */ michael@0: static UDateFormatOpener gOpener = NULL; michael@0: michael@0: U_INTERNAL void U_EXPORT2 michael@0: udat_registerOpener(UDateFormatOpener opener, UErrorCode *status) michael@0: { michael@0: if(U_FAILURE(*status)) return; michael@0: umtx_lock(NULL); michael@0: if(gOpener==NULL) { michael@0: gOpener = opener; michael@0: } else { michael@0: *status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: } michael@0: umtx_unlock(NULL); michael@0: } michael@0: michael@0: U_INTERNAL UDateFormatOpener U_EXPORT2 michael@0: udat_unregisterOpener(UDateFormatOpener opener, UErrorCode *status) michael@0: { michael@0: if(U_FAILURE(*status)) return NULL; michael@0: UDateFormatOpener oldOpener = NULL; michael@0: umtx_lock(NULL); michael@0: if(gOpener==NULL || gOpener!=opener) { michael@0: *status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: } else { michael@0: oldOpener=gOpener; michael@0: gOpener=NULL; michael@0: } michael@0: umtx_unlock(NULL); michael@0: return oldOpener; michael@0: } michael@0: michael@0: michael@0: michael@0: U_CAPI UDateFormat* U_EXPORT2 michael@0: udat_open(UDateFormatStyle timeStyle, michael@0: UDateFormatStyle dateStyle, michael@0: const char *locale, michael@0: const UChar *tzID, michael@0: int32_t tzIDLength, michael@0: const UChar *pattern, michael@0: int32_t patternLength, michael@0: UErrorCode *status) michael@0: { michael@0: DateFormat *fmt; michael@0: if(U_FAILURE(*status)) { michael@0: return 0; michael@0: } michael@0: if(gOpener!=NULL) { // if it's registered michael@0: fmt = (DateFormat*) (*gOpener)(timeStyle,dateStyle,locale,tzID,tzIDLength,pattern,patternLength,status); michael@0: if(fmt!=NULL) { michael@0: return (UDateFormat*)fmt; michael@0: } // else fall through. michael@0: } michael@0: if(timeStyle != UDAT_PATTERN) { michael@0: if(locale == 0) { michael@0: fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle, michael@0: (DateFormat::EStyle)timeStyle); michael@0: } michael@0: else { michael@0: fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle, michael@0: (DateFormat::EStyle)timeStyle, michael@0: Locale(locale)); michael@0: } michael@0: } michael@0: else { michael@0: UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength); michael@0: michael@0: if(locale == 0) { michael@0: fmt = new SimpleDateFormat(pat, *status); michael@0: } michael@0: else { michael@0: fmt = new SimpleDateFormat(pat, Locale(locale), *status); michael@0: } michael@0: } michael@0: michael@0: if(fmt == 0) { michael@0: *status = U_MEMORY_ALLOCATION_ERROR; michael@0: return 0; michael@0: } michael@0: michael@0: if(tzID != 0) { michael@0: TimeZone *zone = TimeZone::createTimeZone(UnicodeString((UBool)(tzIDLength == -1), tzID, tzIDLength)); michael@0: if(zone == 0) { michael@0: *status = U_MEMORY_ALLOCATION_ERROR; michael@0: delete fmt; michael@0: return 0; michael@0: } michael@0: fmt->adoptTimeZone(zone); michael@0: } michael@0: michael@0: return (UDateFormat*)fmt; michael@0: } michael@0: michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udat_close(UDateFormat* format) michael@0: { michael@0: delete (DateFormat*)format; michael@0: } michael@0: michael@0: U_CAPI UDateFormat* U_EXPORT2 michael@0: udat_clone(const UDateFormat *fmt, michael@0: UErrorCode *status) michael@0: { michael@0: if(U_FAILURE(*status)) return 0; michael@0: michael@0: Format *res = ((DateFormat*)fmt)->clone(); michael@0: michael@0: if(res == 0) { michael@0: *status = U_MEMORY_ALLOCATION_ERROR; michael@0: return 0; michael@0: } michael@0: michael@0: return (UDateFormat*) res; michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: udat_format( const UDateFormat* format, michael@0: UDate dateToFormat, michael@0: UChar* result, michael@0: int32_t resultLength, michael@0: UFieldPosition* position, michael@0: UErrorCode* status) michael@0: { michael@0: if(U_FAILURE(*status)) return -1; michael@0: michael@0: UnicodeString res; michael@0: if(!(result==NULL && resultLength==0)) { michael@0: // NULL destination for pure preflighting: empty dummy string michael@0: // otherwise, alias the destination buffer michael@0: res.setTo(result, 0, resultLength); michael@0: } michael@0: michael@0: FieldPosition fp; michael@0: michael@0: if(position != 0) michael@0: fp.setField(position->field); michael@0: michael@0: ((DateFormat*)format)->format(dateToFormat, res, fp); michael@0: michael@0: if(position != 0) { michael@0: position->beginIndex = fp.getBeginIndex(); michael@0: position->endIndex = fp.getEndIndex(); michael@0: } michael@0: michael@0: return res.extract(result, resultLength, *status); michael@0: } michael@0: michael@0: U_CAPI UDate U_EXPORT2 michael@0: udat_parse( const UDateFormat* format, michael@0: const UChar* text, michael@0: int32_t textLength, michael@0: int32_t *parsePos, michael@0: UErrorCode *status) michael@0: { michael@0: if(U_FAILURE(*status)) return (UDate)0; michael@0: michael@0: const UnicodeString src((UBool)(textLength == -1), text, textLength); michael@0: ParsePosition pp; michael@0: int32_t stackParsePos = 0; michael@0: UDate res; michael@0: michael@0: if(parsePos == NULL) { michael@0: parsePos = &stackParsePos; michael@0: } michael@0: michael@0: pp.setIndex(*parsePos); michael@0: michael@0: res = ((DateFormat*)format)->parse(src, pp); michael@0: michael@0: if(pp.getErrorIndex() == -1) michael@0: *parsePos = pp.getIndex(); michael@0: else { michael@0: *parsePos = pp.getErrorIndex(); michael@0: *status = U_PARSE_ERROR; michael@0: } michael@0: michael@0: return res; michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udat_parseCalendar(const UDateFormat* format, michael@0: UCalendar* calendar, michael@0: const UChar* text, michael@0: int32_t textLength, michael@0: int32_t *parsePos, michael@0: UErrorCode *status) michael@0: { michael@0: if(U_FAILURE(*status)) return; michael@0: michael@0: const UnicodeString src((UBool)(textLength == -1), text, textLength); michael@0: ParsePosition pp; michael@0: michael@0: if(parsePos != 0) michael@0: pp.setIndex(*parsePos); michael@0: michael@0: ((DateFormat*)format)->parse(src, *(Calendar*)calendar, pp); michael@0: michael@0: if(parsePos != 0) { michael@0: if(pp.getErrorIndex() == -1) michael@0: *parsePos = pp.getIndex(); michael@0: else { michael@0: *parsePos = pp.getErrorIndex(); michael@0: *status = U_PARSE_ERROR; michael@0: } michael@0: } michael@0: } michael@0: michael@0: U_CAPI UBool U_EXPORT2 michael@0: udat_isLenient(const UDateFormat* fmt) michael@0: { michael@0: return ((DateFormat*)fmt)->isLenient(); michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udat_setLenient( UDateFormat* fmt, michael@0: UBool isLenient) michael@0: { michael@0: ((DateFormat*)fmt)->setLenient(isLenient); michael@0: } michael@0: michael@0: U_CAPI const UCalendar* U_EXPORT2 michael@0: udat_getCalendar(const UDateFormat* fmt) michael@0: { michael@0: return (const UCalendar*) ((DateFormat*)fmt)->getCalendar(); michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udat_setCalendar(UDateFormat* fmt, michael@0: const UCalendar* calendarToSet) michael@0: { michael@0: ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet)); michael@0: } michael@0: michael@0: U_CAPI const UNumberFormat* U_EXPORT2 michael@0: udat_getNumberFormat(const UDateFormat* fmt) michael@0: { michael@0: return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat(); michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udat_setNumberFormat(UDateFormat* fmt, michael@0: const UNumberFormat* numberFormatToSet) michael@0: { michael@0: ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet)); michael@0: } michael@0: michael@0: U_CAPI const char* U_EXPORT2 michael@0: udat_getAvailable(int32_t index) michael@0: { michael@0: return uloc_getAvailable(index); michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: udat_countAvailable() michael@0: { michael@0: return uloc_countAvailable(); michael@0: } michael@0: michael@0: U_CAPI UDate U_EXPORT2 michael@0: udat_get2DigitYearStart( const UDateFormat *fmt, michael@0: UErrorCode *status) michael@0: { michael@0: verifyIsSimpleDateFormat(fmt, status); michael@0: if(U_FAILURE(*status)) return (UDate)0; michael@0: return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status); michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udat_set2DigitYearStart( UDateFormat *fmt, michael@0: UDate d, michael@0: UErrorCode *status) michael@0: { michael@0: verifyIsSimpleDateFormat(fmt, status); michael@0: if(U_FAILURE(*status)) return; michael@0: ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status); michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: udat_toPattern( const UDateFormat *fmt, michael@0: UBool localized, michael@0: UChar *result, michael@0: int32_t resultLength, michael@0: UErrorCode *status) michael@0: { michael@0: if(U_FAILURE(*status)) return -1; michael@0: michael@0: UnicodeString res; michael@0: if(!(result==NULL && resultLength==0)) { michael@0: // NULL destination for pure preflighting: empty dummy string michael@0: // otherwise, alias the destination buffer michael@0: res.setTo(result, 0, resultLength); michael@0: } michael@0: michael@0: const DateFormat *df=reinterpret_cast(fmt); michael@0: const SimpleDateFormat *sdtfmt=dynamic_cast(df); michael@0: const RelativeDateFormat *reldtfmt; michael@0: if (sdtfmt!=NULL) { michael@0: if(localized) michael@0: sdtfmt->toLocalizedPattern(res, *status); michael@0: else michael@0: sdtfmt->toPattern(res); michael@0: } else if (!localized && (reldtfmt=dynamic_cast(df))!=NULL) { michael@0: reldtfmt->toPattern(res, *status); michael@0: } else { michael@0: *status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: return -1; michael@0: } michael@0: michael@0: return res.extract(result, resultLength, *status); michael@0: } michael@0: michael@0: // TODO: should this take an UErrorCode? michael@0: // A: Yes. Of course. michael@0: U_CAPI void U_EXPORT2 michael@0: udat_applyPattern( UDateFormat *format, michael@0: UBool localized, michael@0: const UChar *pattern, michael@0: int32_t patternLength) michael@0: { michael@0: const UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength); michael@0: UErrorCode status = U_ZERO_ERROR; michael@0: michael@0: verifyIsSimpleDateFormat(format, &status); michael@0: if(U_FAILURE(status)) { michael@0: return; michael@0: } michael@0: michael@0: if(localized) michael@0: ((SimpleDateFormat*)format)->applyLocalizedPattern(pat, status); michael@0: else michael@0: ((SimpleDateFormat*)format)->applyPattern(pat); michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: udat_getSymbols(const UDateFormat *fmt, michael@0: UDateFormatSymbolType type, michael@0: int32_t index, michael@0: UChar *result, michael@0: int32_t resultLength, michael@0: UErrorCode *status) michael@0: { michael@0: const DateFormatSymbols *syms; michael@0: const SimpleDateFormat* sdtfmt; michael@0: const RelativeDateFormat* rdtfmt; michael@0: if ((sdtfmt = dynamic_cast(reinterpret_cast(fmt))) != NULL) { michael@0: syms = sdtfmt->getDateFormatSymbols(); michael@0: } else if ((rdtfmt = dynamic_cast(reinterpret_cast(fmt))) != NULL) { michael@0: syms = rdtfmt->getDateFormatSymbols(); michael@0: } else { michael@0: return -1; michael@0: } michael@0: int32_t count; michael@0: const UnicodeString *res = NULL; michael@0: michael@0: switch(type) { michael@0: case UDAT_ERAS: michael@0: res = syms->getEras(count); michael@0: break; michael@0: michael@0: case UDAT_ERA_NAMES: michael@0: res = syms->getEraNames(count); michael@0: break; michael@0: michael@0: case UDAT_MONTHS: michael@0: res = syms->getMonths(count); michael@0: break; michael@0: michael@0: case UDAT_SHORT_MONTHS: michael@0: res = syms->getShortMonths(count); michael@0: break; michael@0: michael@0: case UDAT_WEEKDAYS: michael@0: res = syms->getWeekdays(count); michael@0: break; michael@0: michael@0: case UDAT_SHORT_WEEKDAYS: michael@0: res = syms->getShortWeekdays(count); michael@0: break; michael@0: michael@0: case UDAT_AM_PMS: michael@0: res = syms->getAmPmStrings(count); michael@0: break; michael@0: michael@0: case UDAT_LOCALIZED_CHARS: michael@0: { michael@0: UnicodeString res1; michael@0: if(!(result==NULL && resultLength==0)) { michael@0: // NULL destination for pure preflighting: empty dummy string michael@0: // otherwise, alias the destination buffer michael@0: res1.setTo(result, 0, resultLength); michael@0: } michael@0: syms->getLocalPatternChars(res1); michael@0: return res1.extract(result, resultLength, *status); michael@0: } michael@0: michael@0: case UDAT_NARROW_MONTHS: michael@0: res = syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); michael@0: break; michael@0: michael@0: case UDAT_SHORTER_WEEKDAYS: michael@0: res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::SHORT); michael@0: break; michael@0: michael@0: case UDAT_NARROW_WEEKDAYS: michael@0: res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_MONTHS: michael@0: res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_SHORT_MONTHS: michael@0: res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_NARROW_MONTHS: michael@0: res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_WEEKDAYS: michael@0: res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_SHORT_WEEKDAYS: michael@0: res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_SHORTER_WEEKDAYS: michael@0: res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::SHORT); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_NARROW_WEEKDAYS: michael@0: res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); michael@0: break; michael@0: michael@0: case UDAT_QUARTERS: michael@0: res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); michael@0: break; michael@0: michael@0: case UDAT_SHORT_QUARTERS: michael@0: res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_QUARTERS: michael@0: res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_SHORT_QUARTERS: michael@0: res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); michael@0: break; michael@0: michael@0: } michael@0: michael@0: if(index < count) { michael@0: return res[index].extract(result, resultLength, *status); michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: // TODO: also needs an errorCode. michael@0: U_CAPI int32_t U_EXPORT2 michael@0: udat_countSymbols( const UDateFormat *fmt, michael@0: UDateFormatSymbolType type) michael@0: { michael@0: const DateFormatSymbols *syms; michael@0: const SimpleDateFormat* sdtfmt; michael@0: const RelativeDateFormat* rdtfmt; michael@0: if ((sdtfmt = dynamic_cast(reinterpret_cast(fmt))) != NULL) { michael@0: syms = sdtfmt->getDateFormatSymbols(); michael@0: } else if ((rdtfmt = dynamic_cast(reinterpret_cast(fmt))) != NULL) { michael@0: syms = rdtfmt->getDateFormatSymbols(); michael@0: } else { michael@0: return 0; michael@0: } michael@0: int32_t count = 0; michael@0: michael@0: switch(type) { michael@0: case UDAT_ERAS: michael@0: syms->getEras(count); michael@0: break; michael@0: michael@0: case UDAT_MONTHS: michael@0: syms->getMonths(count); michael@0: break; michael@0: michael@0: case UDAT_SHORT_MONTHS: michael@0: syms->getShortMonths(count); michael@0: break; michael@0: michael@0: case UDAT_WEEKDAYS: michael@0: syms->getWeekdays(count); michael@0: break; michael@0: michael@0: case UDAT_SHORT_WEEKDAYS: michael@0: syms->getShortWeekdays(count); michael@0: break; michael@0: michael@0: case UDAT_AM_PMS: michael@0: syms->getAmPmStrings(count); michael@0: break; michael@0: michael@0: case UDAT_LOCALIZED_CHARS: michael@0: count = 1; michael@0: break; michael@0: michael@0: case UDAT_ERA_NAMES: michael@0: syms->getEraNames(count); michael@0: break; michael@0: michael@0: case UDAT_NARROW_MONTHS: michael@0: syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); michael@0: break; michael@0: michael@0: case UDAT_SHORTER_WEEKDAYS: michael@0: syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::SHORT); michael@0: break; michael@0: michael@0: case UDAT_NARROW_WEEKDAYS: michael@0: syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_MONTHS: michael@0: syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_SHORT_MONTHS: michael@0: syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_NARROW_MONTHS: michael@0: syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_WEEKDAYS: michael@0: syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_SHORT_WEEKDAYS: michael@0: syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_SHORTER_WEEKDAYS: michael@0: syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::SHORT); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_NARROW_WEEKDAYS: michael@0: syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); michael@0: break; michael@0: michael@0: case UDAT_QUARTERS: michael@0: syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); michael@0: break; michael@0: michael@0: case UDAT_SHORT_QUARTERS: michael@0: syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_QUARTERS: michael@0: syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_SHORT_QUARTERS: michael@0: syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); michael@0: break; michael@0: michael@0: } michael@0: michael@0: return count; michael@0: } michael@0: michael@0: U_NAMESPACE_BEGIN michael@0: michael@0: /* michael@0: * This DateFormatSymbolsSingleSetter class is a friend of DateFormatSymbols michael@0: * solely for the purpose of avoiding to clone the array of strings michael@0: * just to modify one of them and then setting all of them back. michael@0: * For example, the old code looked like this: michael@0: * case UDAT_MONTHS: michael@0: * res = syms->getMonths(count); michael@0: * array = new UnicodeString[count]; michael@0: * if(array == 0) { michael@0: * *status = U_MEMORY_ALLOCATION_ERROR; michael@0: * return; michael@0: * } michael@0: * uprv_arrayCopy(res, array, count); michael@0: * if(index < count) michael@0: * array[index] = val; michael@0: * syms->setMonths(array, count); michael@0: * break; michael@0: * michael@0: * Even worse, the old code actually cloned the entire DateFormatSymbols object, michael@0: * cloned one value array, changed one value, and then made the SimpleDateFormat michael@0: * replace its DateFormatSymbols object with the new one. michael@0: * michael@0: * markus 2002-oct-14 michael@0: */ michael@0: class DateFormatSymbolsSingleSetter /* not : public UObject because all methods are static */ { michael@0: public: michael@0: static void michael@0: setSymbol(UnicodeString *array, int32_t count, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: if(array!=NULL) { michael@0: if(index>=count) { michael@0: errorCode=U_INDEX_OUTOFBOUNDS_ERROR; michael@0: } else if(value==NULL) { michael@0: errorCode=U_ILLEGAL_ARGUMENT_ERROR; michael@0: } else { michael@0: array[index].setTo(value, valueLength); michael@0: } michael@0: } michael@0: } michael@0: michael@0: static void michael@0: setEra(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fEras, syms->fErasCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setEraName(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fEraNames, syms->fEraNamesCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setMonth(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fMonths, syms->fMonthsCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setShortMonth(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fShortMonths, syms->fShortMonthsCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setNarrowMonth(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fNarrowMonths, syms->fNarrowMonthsCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setStandaloneMonth(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fStandaloneMonths, syms->fStandaloneMonthsCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setStandaloneShortMonth(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fStandaloneShortMonths, syms->fStandaloneShortMonthsCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setStandaloneNarrowMonth(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fStandaloneNarrowMonths, syms->fStandaloneNarrowMonthsCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setWeekday(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fWeekdays, syms->fWeekdaysCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setShortWeekday(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fShortWeekdays, syms->fShortWeekdaysCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setShorterWeekday(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fShorterWeekdays, syms->fShorterWeekdaysCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setNarrowWeekday(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fNarrowWeekdays, syms->fNarrowWeekdaysCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setStandaloneWeekday(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fStandaloneWeekdays, syms->fStandaloneWeekdaysCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setStandaloneShortWeekday(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fStandaloneShortWeekdays, syms->fStandaloneShortWeekdaysCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setStandaloneShorterWeekday(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fStandaloneShorterWeekdays, syms->fStandaloneShorterWeekdaysCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setStandaloneNarrowWeekday(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fStandaloneNarrowWeekdays, syms->fStandaloneNarrowWeekdaysCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setQuarter(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fQuarters, syms->fQuartersCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setShortQuarter(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fShortQuarters, syms->fShortQuartersCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setStandaloneQuarter(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fStandaloneQuarters, syms->fStandaloneQuartersCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setStandaloneShortQuarter(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fStandaloneShortQuarters, syms->fStandaloneShortQuartersCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setAmPm(DateFormatSymbols *syms, int32_t index, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(syms->fAmPms, syms->fAmPmsCount, index, value, valueLength, errorCode); michael@0: } michael@0: michael@0: static void michael@0: setLocalPatternChars(DateFormatSymbols *syms, michael@0: const UChar *value, int32_t valueLength, UErrorCode &errorCode) michael@0: { michael@0: setSymbol(&syms->fLocalPatternChars, 1, 0, value, valueLength, errorCode); michael@0: } michael@0: }; michael@0: michael@0: U_NAMESPACE_END michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udat_setSymbols( UDateFormat *format, michael@0: UDateFormatSymbolType type, michael@0: int32_t index, michael@0: UChar *value, michael@0: int32_t valueLength, michael@0: UErrorCode *status) michael@0: { michael@0: verifyIsSimpleDateFormat(format, status); michael@0: if(U_FAILURE(*status)) return; michael@0: michael@0: DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols(); michael@0: michael@0: switch(type) { michael@0: case UDAT_ERAS: michael@0: DateFormatSymbolsSingleSetter::setEra(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_ERA_NAMES: michael@0: DateFormatSymbolsSingleSetter::setEraName(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_MONTHS: michael@0: DateFormatSymbolsSingleSetter::setMonth(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_SHORT_MONTHS: michael@0: DateFormatSymbolsSingleSetter::setShortMonth(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_NARROW_MONTHS: michael@0: DateFormatSymbolsSingleSetter::setNarrowMonth(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_MONTHS: michael@0: DateFormatSymbolsSingleSetter::setStandaloneMonth(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_SHORT_MONTHS: michael@0: DateFormatSymbolsSingleSetter::setStandaloneShortMonth(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_NARROW_MONTHS: michael@0: DateFormatSymbolsSingleSetter::setStandaloneNarrowMonth(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_WEEKDAYS: michael@0: DateFormatSymbolsSingleSetter::setWeekday(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_SHORT_WEEKDAYS: michael@0: DateFormatSymbolsSingleSetter::setShortWeekday(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_SHORTER_WEEKDAYS: michael@0: DateFormatSymbolsSingleSetter::setShorterWeekday(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_NARROW_WEEKDAYS: michael@0: DateFormatSymbolsSingleSetter::setNarrowWeekday(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_WEEKDAYS: michael@0: DateFormatSymbolsSingleSetter::setStandaloneWeekday(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_SHORT_WEEKDAYS: michael@0: DateFormatSymbolsSingleSetter::setStandaloneShortWeekday(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_SHORTER_WEEKDAYS: michael@0: DateFormatSymbolsSingleSetter::setStandaloneShorterWeekday(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_NARROW_WEEKDAYS: michael@0: DateFormatSymbolsSingleSetter::setStandaloneNarrowWeekday(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_QUARTERS: michael@0: DateFormatSymbolsSingleSetter::setQuarter(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_SHORT_QUARTERS: michael@0: DateFormatSymbolsSingleSetter::setShortQuarter(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_QUARTERS: michael@0: DateFormatSymbolsSingleSetter::setStandaloneQuarter(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_STANDALONE_SHORT_QUARTERS: michael@0: DateFormatSymbolsSingleSetter::setStandaloneShortQuarter(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_AM_PMS: michael@0: DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status); michael@0: break; michael@0: michael@0: case UDAT_LOCALIZED_CHARS: michael@0: DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status); michael@0: break; michael@0: michael@0: default: michael@0: *status = U_UNSUPPORTED_ERROR; michael@0: break; michael@0: michael@0: } michael@0: } michael@0: michael@0: U_CAPI const char* U_EXPORT2 michael@0: udat_getLocaleByType(const UDateFormat *fmt, michael@0: ULocDataLocaleType type, michael@0: UErrorCode* status) michael@0: { michael@0: if (fmt == NULL) { michael@0: if (U_SUCCESS(*status)) { michael@0: *status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: } michael@0: return NULL; michael@0: } michael@0: return ((Format*)fmt)->getLocaleID(type, *status); michael@0: } michael@0: michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udat_setContext(UDateFormat* fmt, UDisplayContext value, UErrorCode* status) michael@0: { michael@0: verifyIsSimpleDateFormat(fmt, status); michael@0: if (U_FAILURE(*status)) { michael@0: return; michael@0: } michael@0: ((SimpleDateFormat*)fmt)->setContext(value, *status); michael@0: } michael@0: michael@0: U_CAPI UDisplayContext U_EXPORT2 michael@0: udat_getContext(UDateFormat* fmt, UDisplayContextType type, UErrorCode* status) michael@0: { michael@0: verifyIsSimpleDateFormat(fmt, status); michael@0: if (U_FAILURE(*status)) { michael@0: return (UDisplayContext)0; michael@0: } michael@0: return ((SimpleDateFormat*)fmt)->getContext(type, *status); michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Verify that fmt is a RelativeDateFormat. Invalid error if not. michael@0: * @param fmt the UDateFormat, definitely a DateFormat, maybe something else michael@0: * @param status error code, will be set to failure if there is a familure or the fmt is NULL. michael@0: */ michael@0: static void verifyIsRelativeDateFormat(const UDateFormat* fmt, UErrorCode *status) { michael@0: if(U_SUCCESS(*status) && michael@0: dynamic_cast(reinterpret_cast(fmt))==NULL) { michael@0: *status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: } michael@0: } michael@0: michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: udat_toPatternRelativeDate(const UDateFormat *fmt, michael@0: UChar *result, michael@0: int32_t resultLength, michael@0: UErrorCode *status) michael@0: { michael@0: verifyIsRelativeDateFormat(fmt, status); michael@0: if(U_FAILURE(*status)) return -1; michael@0: michael@0: UnicodeString datePattern; michael@0: if(!(result==NULL && resultLength==0)) { michael@0: // NULL destination for pure preflighting: empty dummy string michael@0: // otherwise, alias the destination buffer michael@0: datePattern.setTo(result, 0, resultLength); michael@0: } michael@0: ((RelativeDateFormat*)fmt)->toPatternDate(datePattern, *status); michael@0: return datePattern.extract(result, resultLength, *status); michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: udat_toPatternRelativeTime(const UDateFormat *fmt, michael@0: UChar *result, michael@0: int32_t resultLength, michael@0: UErrorCode *status) michael@0: { michael@0: verifyIsRelativeDateFormat(fmt, status); michael@0: if(U_FAILURE(*status)) return -1; michael@0: michael@0: UnicodeString timePattern; michael@0: if(!(result==NULL && resultLength==0)) { michael@0: // NULL destination for pure preflighting: empty dummy string michael@0: // otherwise, alias the destination buffer michael@0: timePattern.setTo(result, 0, resultLength); michael@0: } michael@0: ((RelativeDateFormat*)fmt)->toPatternTime(timePattern, *status); michael@0: return timePattern.extract(result, resultLength, *status); michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udat_applyPatternRelative(UDateFormat *format, michael@0: const UChar *datePattern, michael@0: int32_t datePatternLength, michael@0: const UChar *timePattern, michael@0: int32_t timePatternLength, michael@0: UErrorCode *status) michael@0: { michael@0: verifyIsRelativeDateFormat(format, status); michael@0: if(U_FAILURE(*status)) return; michael@0: const UnicodeString datePat((UBool)(datePatternLength == -1), datePattern, datePatternLength); michael@0: const UnicodeString timePat((UBool)(timePatternLength == -1), timePattern, timePatternLength); michael@0: ((RelativeDateFormat*)format)->applyPatterns(datePat, timePat, *status); michael@0: } michael@0: michael@0: #endif /* #if !UCONFIG_NO_FORMATTING */