X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/73c04bcfe1096173b00431f0cdc742894b15eef0..ba6d6ed23dec08b1cd5700a128c0752491c10ac9:/icuSources/i18n/udat.cpp diff --git a/icuSources/i18n/udat.cpp b/icuSources/i18n/udat.cpp index 7834b4cb..16d52e4d 100644 --- a/icuSources/i18n/udat.cpp +++ b/icuSources/i18n/udat.cpp @@ -1,6 +1,6 @@ /* ******************************************************************************* -* Copyright (C) 1996-2006, International Business Machines +* Copyright (C) 1996-2012, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************* */ @@ -22,9 +22,102 @@ #include "unicode/dtfmtsym.h" #include "unicode/ustring.h" #include "cpputils.h" +#include "reldtfmt.h" +#include "umutex.h" U_NAMESPACE_USE +/** + * Verify that fmt is a SimpleDateFormat. Invalid error if not. + * @param fmt the UDateFormat, definitely a DateFormat, maybe something else + * @param status error code, will be set to failure if there is a familure or the fmt is NULL. + */ +static void verifyIsSimpleDateFormat(const UDateFormat* fmt, UErrorCode *status) { + if(U_SUCCESS(*status) && + dynamic_cast(reinterpret_cast(fmt))==NULL) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + } +} + +// This mirrors the correspondence between the +// SimpleDateFormat::fgPatternIndexToDateFormatField and +// SimpleDateFormat::fgPatternIndexToCalendarField arrays. +static UCalendarDateFields gDateFieldMapping[] = { + UCAL_ERA, // UDAT_ERA_FIELD = 0 + UCAL_YEAR, // UDAT_YEAR_FIELD = 1 + UCAL_MONTH, // UDAT_MONTH_FIELD = 2 + UCAL_DATE, // UDAT_DATE_FIELD = 3 + UCAL_HOUR_OF_DAY, // UDAT_HOUR_OF_DAY1_FIELD = 4 + UCAL_HOUR_OF_DAY, // UDAT_HOUR_OF_DAY0_FIELD = 5 + UCAL_MINUTE, // UDAT_MINUTE_FIELD = 6 + UCAL_SECOND, // UDAT_SECOND_FIELD = 7 + UCAL_MILLISECOND, // UDAT_FRACTIONAL_SECOND_FIELD = 8 + UCAL_DAY_OF_WEEK, // UDAT_DAY_OF_WEEK_FIELD = 9 + UCAL_DAY_OF_YEAR, // UDAT_DAY_OF_YEAR_FIELD = 10 + UCAL_DAY_OF_WEEK_IN_MONTH, // UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11 + UCAL_WEEK_OF_YEAR, // UDAT_WEEK_OF_YEAR_FIELD = 12 + UCAL_WEEK_OF_MONTH, // UDAT_WEEK_OF_MONTH_FIELD = 13 + UCAL_AM_PM, // UDAT_AM_PM_FIELD = 14 + UCAL_HOUR, // UDAT_HOUR1_FIELD = 15 + UCAL_HOUR, // UDAT_HOUR0_FIELD = 16 + UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_FIELD = 17 + UCAL_YEAR_WOY, // UDAT_YEAR_WOY_FIELD = 18 + UCAL_DOW_LOCAL, // UDAT_DOW_LOCAL_FIELD = 19 + UCAL_EXTENDED_YEAR, // UDAT_EXTENDED_YEAR_FIELD = 20 + UCAL_JULIAN_DAY, // UDAT_JULIAN_DAY_FIELD = 21 + UCAL_MILLISECONDS_IN_DAY, // UDAT_MILLISECONDS_IN_DAY_FIELD = 22 + UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_RFC_FIELD = 23 + // UCAL_DST_OFFSET also + UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_GENERIC_FIELD = 24 + UCAL_DOW_LOCAL, // UDAT_STANDALONE_DAY_FIELD = 25 + UCAL_MONTH, // UDAT_STANDALONE_MONTH_FIELD = 26 + UCAL_MONTH, // UDAT_QUARTER_FIELD = 27 + UCAL_MONTH, // UDAT_STANDALONE_QUARTER_FIELD = 28 + UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_SPECIAL_FIELD = 29 + UCAL_YEAR, // UDAT_YEAR_NAME_FIELD = 30 + UCAL_FIELD_COUNT, // UDAT_FIELD_COUNT = 31 + // UCAL_IS_LEAP_MONTH is not the target of a mapping +}; + +U_CAPI UCalendarDateFields U_EXPORT2 +udat_toCalendarDateField(UDateFormatField field) { + return gDateFieldMapping[field]; +} + +/* For now- one opener. */ +static UDateFormatOpener gOpener = NULL; + +U_INTERNAL void U_EXPORT2 +udat_registerOpener(UDateFormatOpener opener, UErrorCode *status) +{ + if(U_FAILURE(*status)) return; + umtx_lock(NULL); + if(gOpener==NULL) { + gOpener = opener; + } else { + *status = U_ILLEGAL_ARGUMENT_ERROR; + } + umtx_unlock(NULL); +} + +U_INTERNAL UDateFormatOpener U_EXPORT2 +udat_unregisterOpener(UDateFormatOpener opener, UErrorCode *status) +{ + if(U_FAILURE(*status)) return NULL; + UDateFormatOpener oldOpener = NULL; + umtx_lock(NULL); + if(gOpener==NULL || gOpener!=opener) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + } else { + oldOpener=gOpener; + gOpener=NULL; + } + umtx_unlock(NULL); + return oldOpener; +} + + + U_CAPI UDateFormat* U_EXPORT2 udat_open(UDateFormatStyle timeStyle, UDateFormatStyle dateStyle, @@ -39,6 +132,12 @@ udat_open(UDateFormatStyle timeStyle, if(U_FAILURE(*status)) { return 0; } + if(gOpener!=NULL) { // if it's registered + fmt = (DateFormat*) (*gOpener)(timeStyle,dateStyle,locale,tzID,tzIDLength,pattern,patternLength,status); + if(fmt!=NULL) { + return (UDateFormat*)fmt; + } // else fall through. + } if(timeStyle != UDAT_IGNORE) { if(locale == 0) { fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle, @@ -92,7 +191,7 @@ udat_clone(const UDateFormat *fmt, { if(U_FAILURE(*status)) return 0; - Format *res = ((SimpleDateFormat*)fmt)->clone(); + Format *res = ((DateFormat*)fmt)->clone(); if(res == 0) { *status = U_MEMORY_ALLOCATION_ERROR; @@ -249,6 +348,7 @@ U_CAPI UDate U_EXPORT2 udat_get2DigitYearStart( const UDateFormat *fmt, UErrorCode *status) { + verifyIsSimpleDateFormat(fmt, status); if(U_FAILURE(*status)) return (UDate)0; return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status); } @@ -258,6 +358,7 @@ udat_set2DigitYearStart( UDateFormat *fmt, UDate d, UErrorCode *status) { + verifyIsSimpleDateFormat(fmt, status); if(U_FAILURE(*status)) return; ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status); } @@ -278,15 +379,26 @@ udat_toPattern( const UDateFormat *fmt, res.setTo(result, 0, resultLength); } - if(localized) - ((SimpleDateFormat*)fmt)->toLocalizedPattern(res, *status); - else - ((SimpleDateFormat*)fmt)->toPattern(res); + const DateFormat *df=reinterpret_cast(fmt); + const SimpleDateFormat *sdtfmt=dynamic_cast(df); + const RelativeDateFormat *reldtfmt; + if (sdtfmt!=NULL) { + if(localized) + sdtfmt->toLocalizedPattern(res, *status); + else + sdtfmt->toPattern(res); + } else if (!localized && (reldtfmt=dynamic_cast(df))!=NULL) { + reldtfmt->toPattern(res, *status); + } else { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return -1; + } return res.extract(result, resultLength, *status); } -// TBD: should this take an UErrorCode? +// TODO: should this take an UErrorCode? +// A: Yes. Of course. U_CAPI void U_EXPORT2 udat_applyPattern( UDateFormat *format, UBool localized, @@ -296,6 +408,11 @@ udat_applyPattern( UDateFormat *format, const UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength); UErrorCode status = U_ZERO_ERROR; + verifyIsSimpleDateFormat(format, &status); + if(U_FAILURE(status)) { + return; + } + if(localized) ((SimpleDateFormat*)format)->applyLocalizedPattern(pat, status); else @@ -310,10 +427,16 @@ udat_getSymbols(const UDateFormat *fmt, int32_t resultLength, UErrorCode *status) { - if(U_FAILURE(*status)) return -1; - - const DateFormatSymbols *syms = - ((SimpleDateFormat*)fmt)->getDateFormatSymbols(); + const DateFormatSymbols *syms; + const SimpleDateFormat* sdtfmt; + const RelativeDateFormat* rdtfmt; + if ((sdtfmt = dynamic_cast(reinterpret_cast(fmt))) != NULL) { + syms = sdtfmt->getDateFormatSymbols(); + } else if ((rdtfmt = dynamic_cast(reinterpret_cast(fmt))) != NULL) { + syms = rdtfmt->getDateFormatSymbols(); + } else { + return -1; + } int32_t count; const UnicodeString *res = NULL; @@ -414,12 +537,21 @@ udat_getSymbols(const UDateFormat *fmt, return 0; } +// TODO: also needs an errorCode. U_CAPI int32_t U_EXPORT2 udat_countSymbols( const UDateFormat *fmt, UDateFormatSymbolType type) { - const DateFormatSymbols *syms = - ((SimpleDateFormat*)fmt)->getDateFormatSymbols(); + const DateFormatSymbols *syms; + const SimpleDateFormat* sdtfmt; + const RelativeDateFormat* rdtfmt; + if ((sdtfmt = dynamic_cast(reinterpret_cast(fmt))) != NULL) { + syms = sdtfmt->getDateFormatSymbols(); + } else if ((rdtfmt = dynamic_cast(reinterpret_cast(fmt))) != NULL) { + syms = rdtfmt->getDateFormatSymbols(); + } else { + return 0; + } int32_t count = 0; switch(type) { @@ -702,7 +834,7 @@ udat_setSymbols( UDateFormat *format, int32_t valueLength, UErrorCode *status) { - + verifyIsSimpleDateFormat(format, status); if(U_FAILURE(*status)) return; DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols(); @@ -808,4 +940,97 @@ udat_getLocaleByType(const UDateFormat *fmt, } return ((Format*)fmt)->getLocaleID(type, *status); } + + +U_CAPI void U_EXPORT2 +udat_setDefaultContext(UDateFormat* fmt, + UDateFormatContextType type, UDateFormatContextValue value, + UErrorCode* status) +{ + verifyIsSimpleDateFormat(fmt, status); + if (U_FAILURE(*status)) { + return; + } + ((SimpleDateFormat*)fmt)->setDefaultContext(type, value, *status); +} + +U_CAPI int32_t U_EXPORT2 +udat_getDefaultContext(UDateFormat* fmt, + UDateFormatContextType type, + UErrorCode* status) +{ + verifyIsSimpleDateFormat(fmt, status); + if (U_FAILURE(*status)) { + return 0; + } + return ((SimpleDateFormat*)fmt)->getDefaultContext(type, *status); +} + + +/** + * Verify that fmt is a RelativeDateFormat. Invalid error if not. + * @param fmt the UDateFormat, definitely a DateFormat, maybe something else + * @param status error code, will be set to failure if there is a familure or the fmt is NULL. + */ +static void verifyIsRelativeDateFormat(const UDateFormat* fmt, UErrorCode *status) { + if(U_SUCCESS(*status) && + dynamic_cast(reinterpret_cast(fmt))==NULL) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + } +} + + +U_CAPI int32_t U_EXPORT2 +udat_toPatternRelativeDate(const UDateFormat *fmt, + UChar *result, + int32_t resultLength, + UErrorCode *status) +{ + verifyIsRelativeDateFormat(fmt, status); + if(U_FAILURE(*status)) return -1; + + UnicodeString datePattern; + if(!(result==NULL && resultLength==0)) { + // NULL destination for pure preflighting: empty dummy string + // otherwise, alias the destination buffer + datePattern.setTo(result, 0, resultLength); + } + ((RelativeDateFormat*)fmt)->toPatternDate(datePattern, *status); + return datePattern.extract(result, resultLength, *status); +} + +U_CAPI int32_t U_EXPORT2 +udat_toPatternRelativeTime(const UDateFormat *fmt, + UChar *result, + int32_t resultLength, + UErrorCode *status) +{ + verifyIsRelativeDateFormat(fmt, status); + if(U_FAILURE(*status)) return -1; + + UnicodeString timePattern; + if(!(result==NULL && resultLength==0)) { + // NULL destination for pure preflighting: empty dummy string + // otherwise, alias the destination buffer + timePattern.setTo(result, 0, resultLength); + } + ((RelativeDateFormat*)fmt)->toPatternTime(timePattern, *status); + return timePattern.extract(result, resultLength, *status); +} + +U_CAPI void U_EXPORT2 +udat_applyPatternRelative(UDateFormat *format, + const UChar *datePattern, + int32_t datePatternLength, + const UChar *timePattern, + int32_t timePatternLength, + UErrorCode *status) +{ + verifyIsRelativeDateFormat(format, status); + if(U_FAILURE(*status)) return; + const UnicodeString datePat((UBool)(datePatternLength == -1), datePattern, datePatternLength); + const UnicodeString timePat((UBool)(timePatternLength == -1), timePattern, timePatternLength); + ((RelativeDateFormat*)format)->applyPatterns(datePat, timePat, *status); +} + #endif /* #if !UCONFIG_NO_FORMATTING */