| Index: source/i18n/reldtfmt.cpp
|
| diff --git a/source/i18n/reldtfmt.cpp b/source/i18n/reldtfmt.cpp
|
| index 81fb77749a594745c48d5daa863e6bad5705f899..00cafc84e4cd05e995bd30a1e14b6a80137c5983 100644
|
| --- a/source/i18n/reldtfmt.cpp
|
| +++ b/source/i18n/reldtfmt.cpp
|
| @@ -1,6 +1,8 @@
|
| +// Copyright (C) 2016 and later: Unicode, Inc. and others.
|
| +// License & terms of use: http://www.unicode.org/copyright.html
|
| /*
|
| *******************************************************************************
|
| -* Copyright (C) 2007-2014, International Business Machines Corporation and
|
| +* Copyright (C) 2007-2016, International Business Machines Corporation and
|
| * others. All Rights Reserved.
|
| *******************************************************************************
|
| */
|
| @@ -11,15 +13,15 @@
|
|
|
| #include <stdlib.h>
|
|
|
| -#include "reldtfmt.h"
|
| #include "unicode/datefmt.h"
|
| +#include "unicode/reldatefmt.h"
|
| +#include "unicode/simpleformatter.h"
|
| #include "unicode/smpdtfmt.h"
|
| -#include "unicode/msgfmt.h"
|
| #include "unicode/udisplaycontext.h"
|
| #include "unicode/uchar.h"
|
| #include "unicode/brkiter.h"
|
|
|
| -#include "gregoimp.h" // for CalendarData
|
| +#include "reldtfmt.h"
|
| #include "cmemory.h"
|
| #include "uresimp.h"
|
|
|
| @@ -35,16 +37,12 @@ struct URelativeString {
|
| const UChar* string; /** string, or NULL if not set **/
|
| };
|
|
|
| -static const char DT_DateTimePatternsTag[]="DateTimePatterns";
|
| -
|
| -
|
| UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RelativeDateFormat)
|
|
|
| RelativeDateFormat::RelativeDateFormat(const RelativeDateFormat& other) :
|
| DateFormat(other), fDateTimeFormatter(NULL), fDatePattern(other.fDatePattern),
|
| fTimePattern(other.fTimePattern), fCombinedFormat(NULL),
|
| fDateStyle(other.fDateStyle), fLocale(other.fLocale),
|
| - fDayMin(other.fDayMin), fDayMax(other.fDayMax),
|
| fDatesLen(other.fDatesLen), fDates(NULL),
|
| fCombinedHasDateAtStart(other.fCombinedHasDateAtStart),
|
| fCapitalizationInfoSet(other.fCapitalizationInfoSet),
|
| @@ -56,11 +54,11 @@ RelativeDateFormat::RelativeDateFormat(const RelativeDateFormat& other) :
|
| fDateTimeFormatter = (SimpleDateFormat*)other.fDateTimeFormatter->clone();
|
| }
|
| if(other.fCombinedFormat != NULL) {
|
| - fCombinedFormat = (MessageFormat*)other.fCombinedFormat->clone();
|
| + fCombinedFormat = new SimpleFormatter(*other.fCombinedFormat);
|
| }
|
| if (fDatesLen > 0) {
|
| - fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);
|
| - uprv_memcpy(fDates, other.fDates, sizeof(fDates[0])*fDatesLen);
|
| + fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*(size_t)fDatesLen);
|
| + uprv_memcpy(fDates, other.fDates, sizeof(fDates[0])*(size_t)fDatesLen);
|
| }
|
| #if !UCONFIG_NO_BREAK_ITERATION
|
| if (other.fCapitalizationBrkIter != NULL) {
|
| @@ -72,7 +70,7 @@ RelativeDateFormat::RelativeDateFormat(const RelativeDateFormat& other) :
|
| RelativeDateFormat::RelativeDateFormat( UDateFormatStyle timeStyle, UDateFormatStyle dateStyle,
|
| const Locale& locale, UErrorCode& status) :
|
| DateFormat(), fDateTimeFormatter(NULL), fDatePattern(), fTimePattern(), fCombinedFormat(NULL),
|
| - fDateStyle(dateStyle), fLocale(locale), fDayMin(0), fDayMax(0), fDatesLen(0), fDates(NULL),
|
| + fDateStyle(dateStyle), fLocale(locale), fDatesLen(0), fDates(NULL),
|
| fCombinedHasDateAtStart(FALSE), fCapitalizationInfoSet(FALSE),
|
| fCapitalizationOfRelativeUnitsForUIListMenu(FALSE), fCapitalizationOfRelativeUnitsForStandAlone(FALSE),
|
| fCapitalizationBrkIter(NULL)
|
| @@ -80,7 +78,7 @@ RelativeDateFormat::RelativeDateFormat( UDateFormatStyle timeStyle, UDateFormatS
|
| if(U_FAILURE(status) ) {
|
| return;
|
| }
|
| -
|
| +
|
| if (timeStyle < UDAT_NONE || timeStyle > UDAT_SHORT) {
|
| // don't support other time styles (e.g. relative styles), for now
|
| status = U_ILLEGAL_ARGUMENT_ERROR;
|
| @@ -112,11 +110,12 @@ RelativeDateFormat::RelativeDateFormat( UDateFormatStyle timeStyle, UDateFormatS
|
| fDateTimeFormatter=dynamic_cast<SimpleDateFormat *>(df);
|
| if (fDateTimeFormatter == NULL) {
|
| status = U_UNSUPPORTED_ERROR;
|
| + delete df;
|
| return;
|
| }
|
| fDateTimeFormatter->toPattern(fTimePattern);
|
| }
|
| -
|
| +
|
| // Initialize the parent fCalendar, so that parse() works correctly.
|
| initializeCalendar(NULL, locale, status);
|
| loadDates(status);
|
| @@ -211,12 +210,11 @@ UnicodeString& RelativeDateFormat::format( Calendar& cal,
|
| datePattern.setTo(fDatePattern);
|
| }
|
| UnicodeString combinedPattern;
|
| - Formattable timeDatePatterns[] = { fTimePattern, datePattern };
|
| - fCombinedFormat->format(timeDatePatterns, 2, combinedPattern, pos, status); // pos is ignored by this
|
| + fCombinedFormat->format(fTimePattern, datePattern, combinedPattern, status);
|
| fDateTimeFormatter->applyPattern(combinedPattern);
|
| fDateTimeFormatter->format(cal,appendTo,pos);
|
| }
|
| -
|
| +
|
| return appendTo;
|
| }
|
|
|
| @@ -308,8 +306,7 @@ void RelativeDateFormat::parse( const UnicodeString& text,
|
| }
|
| }
|
| UnicodeString combinedPattern;
|
| - Formattable timeDatePatterns[] = { fTimePattern, fDatePattern };
|
| - fCombinedFormat->format(timeDatePatterns, 2, combinedPattern, fPos, status); // pos is ignored by this
|
| + fCombinedFormat->format(fTimePattern, fDatePattern, combinedPattern, status);
|
| fDateTimeFormatter->applyPattern(combinedPattern);
|
| fDateTimeFormatter->parse(modifiedText,cal,pos);
|
|
|
| @@ -354,20 +351,15 @@ const UChar *RelativeDateFormat::getStringForDay(int32_t day, int32_t &len, UErr
|
| if(U_FAILURE(status)) {
|
| return NULL;
|
| }
|
| -
|
| - // Is it outside the resource bundle's range?
|
| - if(day < fDayMin || day > fDayMax) {
|
| - return NULL; // don't have it.
|
| - }
|
| -
|
| - // Linear search the held strings
|
| - for(int n=0;n<fDatesLen;n++) {
|
| - if(fDates[n].offset == day) {
|
| +
|
| + // Is it inside the resource bundle's range?
|
| + int n = day + UDAT_DIRECTION_THIS;
|
| + if (n >= 0 && n < fDatesLen) {
|
| + if (fDates[n].offset == day && fDates[n].string != NULL) {
|
| len = fDates[n].len;
|
| return fDates[n].string;
|
| }
|
| }
|
| -
|
| return NULL; // not found.
|
| }
|
|
|
| @@ -381,9 +373,7 @@ RelativeDateFormat::toPattern(UnicodeString& result, UErrorCode& status) const
|
| } else if (fTimePattern.isEmpty() || fCombinedFormat == NULL) {
|
| result.setTo(fDatePattern);
|
| } else {
|
| - Formattable timeDatePatterns[] = { fTimePattern, fDatePattern };
|
| - FieldPosition pos;
|
| - fCombinedFormat->format(timeDatePatterns, 2, result, pos, status);
|
| + fCombinedFormat->format(fTimePattern, fDatePattern, result, status);
|
| }
|
| }
|
| return result;
|
| @@ -457,125 +447,114 @@ RelativeDateFormat::initCapitalizationContextInfo(const Locale& thelocale)
|
| #if !UCONFIG_NO_BREAK_ITERATION
|
| const char * localeID = (thelocale != NULL)? thelocale.getBaseName(): NULL;
|
| UErrorCode status = U_ZERO_ERROR;
|
| - UResourceBundle *rb = ures_open(NULL, localeID, &status);
|
| - rb = ures_getByKeyWithFallback(rb, "contextTransforms", rb, &status);
|
| - rb = ures_getByKeyWithFallback(rb, "relative", rb, &status);
|
| + LocalUResourceBundlePointer rb(ures_open(NULL, localeID, &status));
|
| + ures_getByKeyWithFallback(rb.getAlias(),
|
| + "contextTransforms/relative",
|
| + rb.getAlias(), &status);
|
| if (U_SUCCESS(status) && rb != NULL) {
|
| int32_t len = 0;
|
| - const int32_t * intVector = ures_getIntVector(rb, &len, &status);
|
| + const int32_t * intVector = ures_getIntVector(rb.getAlias(),
|
| + &len, &status);
|
| if (U_SUCCESS(status) && intVector != NULL && len >= 2) {
|
| fCapitalizationOfRelativeUnitsForUIListMenu = intVector[0];
|
| fCapitalizationOfRelativeUnitsForStandAlone = intVector[1];
|
| }
|
| }
|
| - ures_close(rb);
|
| #endif
|
| }
|
|
|
| +namespace {
|
| +
|
| +/**
|
| + * Sink for getting data from fields/day/relative data.
|
| + * For loading relative day names, e.g., "yesterday", "today".
|
| + */
|
| +
|
| +struct RelDateFmtDataSink : public ResourceSink {
|
| + URelativeString *fDatesPtr;
|
| + int32_t fDatesLen;
|
| +
|
| + RelDateFmtDataSink(URelativeString* fDates, int32_t len) : fDatesPtr(fDates), fDatesLen(len) {
|
| + for (int32_t i = 0; i < fDatesLen; ++i) {
|
| + fDatesPtr[i].offset = 0;
|
| + fDatesPtr[i].string = NULL;
|
| + fDatesPtr[i].len = -1;
|
| + }
|
| + }
|
| +
|
| + virtual ~RelDateFmtDataSink();
|
| +
|
| + virtual void put(const char *key, ResourceValue &value,
|
| + UBool /*noFallback*/, UErrorCode &errorCode) {
|
| + ResourceTable relDayTable = value.getTable(errorCode);
|
| + int32_t n = 0;
|
| + int32_t len = 0;
|
| + for (int32_t i = 0; relDayTable.getKeyAndValue(i, key, value); ++i) {
|
| + // Find the relative offset.
|
| + int32_t offset = atoi(key);
|
| +
|
| + // Put in the proper spot, but don't override existing data.
|
| + n = offset + UDAT_DIRECTION_THIS; // Converts to index in UDAT_R
|
| + if (n < fDatesLen && fDatesPtr[n].string == NULL) {
|
| + // Not found and n is an empty slot.
|
| + fDatesPtr[n].offset = offset;
|
| + fDatesPtr[n].string = value.getString(len, errorCode);
|
| + fDatesPtr[n].len = len;
|
| + }
|
| + }
|
| + }
|
| +};
|
| +
|
| +
|
| +// Virtual destructors must be defined out of line.
|
| +RelDateFmtDataSink::~RelDateFmtDataSink() {}
|
| +
|
| +} // Namespace
|
| +
|
| +
|
| static const UChar patItem1[] = {0x7B,0x31,0x7D}; // "{1}"
|
| static const int32_t patItem1Len = 3;
|
|
|
| void RelativeDateFormat::loadDates(UErrorCode &status) {
|
| - CalendarData calData(fLocale, "gregorian", status);
|
| -
|
| - UErrorCode tempStatus = status;
|
| - UResourceBundle *dateTimePatterns = calData.getByKey(DT_DateTimePatternsTag, tempStatus);
|
| - if(U_SUCCESS(tempStatus)) {
|
| - int32_t patternsSize = ures_getSize(dateTimePatterns);
|
| + UResourceBundle *rb = ures_open(NULL, fLocale.getBaseName(), &status);
|
| + LocalUResourceBundlePointer dateTimePatterns(
|
| + ures_getByKeyWithFallback(rb,
|
| + "calendar/gregorian/DateTimePatterns",
|
| + (UResourceBundle*)NULL, &status));
|
| + if(U_SUCCESS(status)) {
|
| + int32_t patternsSize = ures_getSize(dateTimePatterns.getAlias());
|
| if (patternsSize > kDateTime) {
|
| int32_t resStrLen = 0;
|
| -
|
| int32_t glueIndex = kDateTime;
|
| - if (patternsSize >= (DateFormat::kDateTimeOffset + DateFormat::kShort + 1)) {
|
| - // Get proper date time format
|
| - switch (fDateStyle) {
|
| - case kFullRelative:
|
| - case kFull:
|
| - glueIndex = kDateTimeOffset + kFull;
|
| - break;
|
| - case kLongRelative:
|
| - case kLong:
|
| - glueIndex = kDateTimeOffset + kLong;
|
| - break;
|
| - case kMediumRelative:
|
| - case kMedium:
|
| - glueIndex = kDateTimeOffset + kMedium;
|
| - break;
|
| - case kShortRelative:
|
| - case kShort:
|
| - glueIndex = kDateTimeOffset + kShort;
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| + if (patternsSize >= (kDateTimeOffset + kShort + 1)) {
|
| + int32_t offsetIncrement = (fDateStyle & ~kRelative); // Remove relative bit.
|
| + if (offsetIncrement >= (int32_t)kFull &&
|
| + offsetIncrement <= (int32_t)kShortRelative) {
|
| + glueIndex = kDateTimeOffset + offsetIncrement;
|
| + }
|
| }
|
|
|
| - const UChar *resStr = ures_getStringByIndex(dateTimePatterns, glueIndex, &resStrLen, &tempStatus);
|
| - if (U_SUCCESS(tempStatus) && resStrLen >= patItem1Len && u_strncmp(resStr,patItem1,patItem1Len)==0) {
|
| + const UChar *resStr = ures_getStringByIndex(dateTimePatterns.getAlias(), glueIndex, &resStrLen, &status);
|
| + if (U_SUCCESS(status) && resStrLen >= patItem1Len && u_strncmp(resStr,patItem1,patItem1Len)==0) {
|
| fCombinedHasDateAtStart = TRUE;
|
| }
|
| - fCombinedFormat = new MessageFormat(UnicodeString(TRUE, resStr, resStrLen), fLocale, tempStatus);
|
| + fCombinedFormat = new SimpleFormatter(UnicodeString(TRUE, resStr, resStrLen), 2, 2, status);
|
| }
|
| }
|
|
|
| - UResourceBundle *rb = ures_open(NULL, fLocale.getBaseName(), &status);
|
| - rb = ures_getByKeyWithFallback(rb, "fields", rb, &status);
|
| - rb = ures_getByKeyWithFallback(rb, "day", rb, &status);
|
| - rb = ures_getByKeyWithFallback(rb, "relative", rb, &status);
|
| - // set up min/max
|
| - fDayMin=-1;
|
| - fDayMax=1;
|
| -
|
| - if(U_FAILURE(status)) {
|
| - fDatesLen=0;
|
| - ures_close(rb);
|
| - return;
|
| - }
|
| -
|
| - fDatesLen = ures_getSize(rb);
|
| + // Data loading for relative names, e.g., "yesterday", "today", "tomorrow".
|
| + fDatesLen = UDAT_DIRECTION_COUNT; // Maximum defined by data.
|
| fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);
|
|
|
| - // Load in each item into the array...
|
| - int n = 0;
|
| + RelDateFmtDataSink sink(fDates, fDatesLen);
|
| + ures_getAllItemsWithFallback(rb, "fields/day/relative", sink, status);
|
|
|
| - UResourceBundle *subString = NULL;
|
| -
|
| - while(ures_hasNext(rb) && U_SUCCESS(status)) { // iterate over items
|
| - subString = ures_getNextResource(rb, subString, &status);
|
| -
|
| - if(U_FAILURE(status) || (subString==NULL)) break;
|
| -
|
| - // key = offset #
|
| - const char *key = ures_getKey(subString);
|
| -
|
| - // load the string and length
|
| - int32_t aLen;
|
| - const UChar* aString = ures_getString(subString, &aLen, &status);
|
| -
|
| - if(U_FAILURE(status) || aString == NULL) break;
|
| -
|
| - // calculate the offset
|
| - int32_t offset = atoi(key);
|
| -
|
| - // set min/max
|
| - if(offset < fDayMin) {
|
| - fDayMin = offset;
|
| - }
|
| - if(offset > fDayMax) {
|
| - fDayMax = offset;
|
| - }
|
| -
|
| - // copy the string pointer
|
| - fDates[n].offset = offset;
|
| - fDates[n].string = aString;
|
| - fDates[n].len = aLen;
|
| + ures_close(rb);
|
|
|
| - n++;
|
| + if(U_FAILURE(status)) {
|
| + fDatesLen=0;
|
| + return;
|
| }
|
| - ures_close(subString);
|
| - ures_close(rb);
|
| -
|
| - // the fDates[] array could be sorted here, for direct access.
|
| }
|
|
|
| //----------------------------------------------------------------------
|
| @@ -613,5 +592,4 @@ int32_t RelativeDateFormat::dayDifference(Calendar &cal, UErrorCode &status) {
|
|
|
| U_NAMESPACE_END
|
|
|
| -#endif
|
| -
|
| +#endif /* !UCONFIG_NO_FORMATTING */
|
|
|