Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(697)

Unified Diff: icu46/source/i18n/reldtfmt.cpp

Issue 5516007: Check in the pristine copy of ICU 4.6... (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party/
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « icu46/source/i18n/reldtfmt.h ('k') | icu46/source/i18n/rematch.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: icu46/source/i18n/reldtfmt.cpp
===================================================================
--- icu46/source/i18n/reldtfmt.cpp (revision 0)
+++ icu46/source/i18n/reldtfmt.cpp (revision 0)
@@ -0,0 +1,472 @@
+/*
+*******************************************************************************
+* Copyright (C) 2007-2010, International Business Machines Corporation and
+* others. All Rights Reserved.
+*******************************************************************************
+*/
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+//#define DEBUG_RELDTFMT
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "reldtfmt.h"
+#include "unicode/msgfmt.h"
+#include "unicode/smpdtfmt.h"
+
+#include "gregoimp.h" // for CalendarData
+#include "cmemory.h"
+
+U_NAMESPACE_BEGIN
+
+
+/**
+ * An array of URelativeString structs is used to store the resource data loaded out of the bundle.
+ */
+struct URelativeString {
+ int32_t offset; /** offset of this item, such as, the relative date **/
+ int32_t len; /** length of the string **/
+ 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), fDateFormat(NULL), fTimeFormat(NULL), fCombinedFormat(NULL),
+fDateStyle(other.fDateStyle), fTimeStyle(other.fTimeStyle), fLocale(other.fLocale),
+fDayMin(other.fDayMin), fDayMax(other.fDayMax),
+fDatesLen(other.fDatesLen), fDates(NULL)
+{
+ if(other.fDateFormat != NULL) {
+ fDateFormat = (DateFormat*)other.fDateFormat->clone();
+ } else {
+ fDateFormat = NULL;
+ }
+ if (fDatesLen > 0) {
+ fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);
+ uprv_memcpy(fDates, other.fDates, sizeof(fDates[0])*fDatesLen);
+ }
+ //fCalendar = other.fCalendar->clone();
+/*
+ if(other.fTimeFormat != NULL) {
+ fTimeFormat = (DateFormat*)other.fTimeFormat->clone();
+ } else {
+ fTimeFormat = NULL;
+ }
+*/
+}
+
+RelativeDateFormat::RelativeDateFormat( UDateFormatStyle timeStyle, UDateFormatStyle dateStyle, const Locale& locale, UErrorCode& status)
+ : DateFormat(), fDateFormat(NULL), fTimeFormat(NULL), fCombinedFormat(NULL),
+fDateStyle(dateStyle), fTimeStyle(timeStyle), fLocale(locale), fDatesLen(0), fDates(NULL)
+ {
+ if(U_FAILURE(status) ) {
+ return;
+ }
+
+ if(fDateStyle != UDAT_NONE) {
+ EStyle newStyle = (EStyle)(fDateStyle & ~UDAT_RELATIVE);
+ // Create a DateFormat in the non-relative style requested.
+ fDateFormat = createDateInstance(newStyle, locale);
+ }
+ if(fTimeStyle >= UDAT_FULL && fTimeStyle <= UDAT_SHORT) {
+ fTimeFormat = createTimeInstance((EStyle)fTimeStyle, locale);
+ } else if(fTimeStyle != UDAT_NONE) {
+ // don't support other time styles (e.g. relative styles), for now
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+
+ // Initialize the parent fCalendar, so that parse() works correctly.
+ initializeCalendar(NULL, locale, status);
+ loadDates(status);
+}
+
+RelativeDateFormat::~RelativeDateFormat() {
+ delete fDateFormat;
+ delete fTimeFormat;
+ delete fCombinedFormat;
+ uprv_free(fDates);
+}
+
+
+Format* RelativeDateFormat::clone(void) const {
+ return new RelativeDateFormat(*this);
+}
+
+UBool RelativeDateFormat::operator==(const Format& other) const {
+ if(DateFormat::operator==(other)) {
+ // DateFormat::operator== guarantees following cast is safe
+ RelativeDateFormat* that = (RelativeDateFormat*)&other;
+ return (fDateStyle==that->fDateStyle &&
+ fTimeStyle==that->fTimeStyle &&
+ fLocale==that->fLocale);
+ }
+ return FALSE;
+}
+
+UnicodeString& RelativeDateFormat::format( Calendar& cal,
+ UnicodeString& appendTo,
+ FieldPosition& pos) const {
+
+ UErrorCode status = U_ZERO_ERROR;
+ UChar emptyStr = 0;
+ UnicodeString dateString(&emptyStr);
+
+ // calculate the difference, in days, between 'cal' and now.
+ int dayDiff = dayDifference(cal, status);
+
+ // look up string
+ int32_t len = 0;
+ const UChar *theString = getStringForDay(dayDiff, len, status);
+ if(U_SUCCESS(status) && (theString!=NULL)) {
+ // found a relative string
+ dateString.setTo(theString, len);
+ }
+
+ if(fTimeFormat == NULL || fCombinedFormat == 0) {
+ if (dateString.length() > 0) {
+ appendTo.append(dateString);
+ } else if(fDateFormat != NULL) {
+ fDateFormat->format(cal,appendTo,pos);
+ }
+ } else {
+ if (dateString.length() == 0 && fDateFormat != NULL) {
+ fDateFormat->format(cal,dateString,pos);
+ }
+ UnicodeString timeString(&emptyStr);
+ FieldPosition timepos = pos;
+ fTimeFormat->format(cal,timeString,timepos);
+ Formattable timeDateStrings[] = { timeString, dateString };
+ fCombinedFormat->format(timeDateStrings, 2, appendTo, pos, status); // pos is ignored by this
+ int32_t offset;
+ if (pos.getEndIndex() > 0 && (offset = appendTo.indexOf(dateString)) >= 0) {
+ // pos.field was found in dateString, offset start & end based on final position of dateString
+ pos.setBeginIndex( pos.getBeginIndex() + offset );
+ pos.setEndIndex( pos.getEndIndex() + offset );
+ } else if (timepos.getEndIndex() > 0 && (offset = appendTo.indexOf(timeString)) >= 0) {
+ // pos.field was found in timeString, offset start & end based on final position of timeString
+ pos.setBeginIndex( timepos.getBeginIndex() + offset );
+ pos.setEndIndex( timepos.getEndIndex() + offset );
+ }
+ }
+
+ return appendTo;
+}
+
+
+
+UnicodeString&
+RelativeDateFormat::format(const Formattable& obj,
+ UnicodeString& appendTo,
+ FieldPosition& pos,
+ UErrorCode& status) const
+{
+ // this is just here to get around the hiding problem
+ // (the previous format() override would hide the version of
+ // format() on DateFormat that this function correspond to, so we
+ // have to redefine it here)
+ return DateFormat::format(obj, appendTo, pos, status);
+}
+
+
+void RelativeDateFormat::parse( const UnicodeString& text,
+ Calendar& cal,
+ ParsePosition& pos) const {
+
+ // Can the fDateFormat parse it?
+ if(fDateFormat != NULL) {
+ ParsePosition aPos(pos);
+ fDateFormat->parse(text,cal,aPos);
+ if((aPos.getIndex() != pos.getIndex()) &&
+ (aPos.getErrorIndex()==-1)) {
+ pos=aPos; // copy the sub parse
+ return; // parsed subfmt OK
+ }
+ }
+
+ // Linear search the relative strings
+ for(int n=0;n<fDatesLen;n++) {
+ if(fDates[n].string != NULL &&
+ (0==text.compare(pos.getIndex(),
+ fDates[n].len,
+ fDates[n].string))) {
+ UErrorCode status = U_ZERO_ERROR;
+
+ // Set the calendar to now+offset
+ cal.setTime(Calendar::getNow(),status);
+ cal.add(UCAL_DATE,fDates[n].offset, status);
+
+ if(U_FAILURE(status)) {
+ // failure in setting calendar fields
+ pos.setErrorIndex(pos.getIndex()+fDates[n].len);
+ } else {
+ pos.setIndex(pos.getIndex()+fDates[n].len);
+ }
+ return;
+ }
+ }
+
+ // parse failed
+}
+
+UDate
+RelativeDateFormat::parse( const UnicodeString& text,
+ ParsePosition& pos) const {
+ // redefined here because the other parse() function hides this function's
+ // cunterpart on DateFormat
+ return DateFormat::parse(text, pos);
+}
+
+UDate
+RelativeDateFormat::parse(const UnicodeString& text, UErrorCode& status) const
+{
+ // redefined here because the other parse() function hides this function's
+ // counterpart on DateFormat
+ return DateFormat::parse(text, status);
+}
+
+
+const UChar *RelativeDateFormat::getStringForDay(int32_t day, int32_t &len, UErrorCode &status) const {
+ 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) {
+ len = fDates[n].len;
+ return fDates[n].string;
+ }
+ }
+
+ return NULL; // not found.
+}
+
+UnicodeString&
+RelativeDateFormat::toPattern(UnicodeString& result, UErrorCode& status) const
+{
+ if (!U_FAILURE(status)) {
+ result.remove();
+ if (fTimeFormat == NULL || fCombinedFormat == 0) {
+ if (fDateFormat != NULL) {
+ UnicodeString datePattern;
+ this->toPatternDate(datePattern, status);
+ if (!U_FAILURE(status)) {
+ result.setTo(datePattern);
+ }
+ }
+ } else {
+ UnicodeString datePattern, timePattern;
+ this->toPatternDate(datePattern, status);
+ this->toPatternTime(timePattern, status);
+ if (!U_FAILURE(status)) {
+ Formattable timeDatePatterns[] = { timePattern, datePattern };
+ FieldPosition pos;
+ fCombinedFormat->format(timeDatePatterns, 2, result, pos, status);
+ }
+ }
+ }
+ return result;
+}
+
+UnicodeString&
+RelativeDateFormat::toPatternDate(UnicodeString& result, UErrorCode& status) const
+{
+ if (!U_FAILURE(status)) {
+ result.remove();
+ if ( fDateFormat ) {
+ SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(fDateFormat);
+ if (sdtfmt != NULL) {
+ sdtfmt->toPattern(result);
+ } else {
+ status = U_UNSUPPORTED_ERROR;
+ }
+ }
+ }
+ return result;
+}
+
+UnicodeString&
+RelativeDateFormat::toPatternTime(UnicodeString& result, UErrorCode& status) const
+{
+ if (!U_FAILURE(status)) {
+ result.remove();
+ if ( fTimeFormat ) {
+ SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(fTimeFormat);
+ if (sdtfmt != NULL) {
+ sdtfmt->toPattern(result);
+ } else {
+ status = U_UNSUPPORTED_ERROR;
+ }
+ }
+ }
+ return result;
+}
+
+void
+RelativeDateFormat::applyPatterns(const UnicodeString& datePattern, const UnicodeString& timePattern, UErrorCode &status)
+{
+ if (!U_FAILURE(status)) {
+ SimpleDateFormat* sdtfmt = NULL;
+ SimpleDateFormat* stmfmt = NULL;
+ if (fDateFormat && (sdtfmt = dynamic_cast<SimpleDateFormat*>(fDateFormat)) == NULL) {
+ status = U_UNSUPPORTED_ERROR;
+ return;
+ }
+ if (fTimeFormat && (stmfmt = dynamic_cast<SimpleDateFormat*>(fTimeFormat)) == NULL) {
+ status = U_UNSUPPORTED_ERROR;
+ return;
+ }
+ if ( fDateFormat ) {
+ sdtfmt->applyPattern(datePattern);
+ }
+ if ( fTimeFormat ) {
+ stmfmt->applyPattern(timePattern);
+ }
+ }
+}
+
+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);
+ 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;
+ }
+ }
+
+ const UChar *resStr = ures_getStringByIndex(dateTimePatterns, glueIndex, &resStrLen, &tempStatus);
+ fCombinedFormat = new MessageFormat(UnicodeString(TRUE, resStr, resStrLen), fLocale, tempStatus);
+ }
+ }
+
+ UResourceBundle *strings = calData.getByKey3("fields", "day", "relative", status);
+ // set up min/max
+ fDayMin=-1;
+ fDayMax=1;
+
+ if(U_FAILURE(status)) {
+ fDatesLen=0;
+ return;
+ }
+
+ fDatesLen = ures_getSize(strings);
+ fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);
+
+ // Load in each item into the array...
+ int n = 0;
+
+ UResourceBundle *subString = NULL;
+
+ while(ures_hasNext(strings) && U_SUCCESS(status)) { // iterate over items
+ subString = ures_getNextResource(strings, 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;
+
+ n++;
+ }
+ ures_close(subString);
+
+ // the fDates[] array could be sorted here, for direct access.
+}
+
+
+// this should to be in DateFormat, instead it was copied from SimpleDateFormat.
+
+Calendar*
+RelativeDateFormat::initializeCalendar(TimeZone* adoptZone, const Locale& locale, UErrorCode& status)
+{
+ if(!U_FAILURE(status)) {
+ fCalendar = Calendar::createInstance(adoptZone?adoptZone:TimeZone::createDefault(), locale, status);
+ }
+ if (U_SUCCESS(status) && fCalendar == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ }
+ return fCalendar;
+}
+
+int32_t RelativeDateFormat::dayDifference(Calendar &cal, UErrorCode &status) {
+ if(U_FAILURE(status)) {
+ return 0;
+ }
+ // TODO: Cache the nowCal to avoid heap allocs? Would be difficult, don't know the calendar type
+ Calendar *nowCal = cal.clone();
+ nowCal->setTime(Calendar::getNow(), status);
+
+ // For the day difference, we are interested in the difference in the (modified) julian day number
+ // which is midnight to midnight. Using fieldDifference() is NOT correct here, because
+ // 6pm Jan 4th to 10am Jan 5th should be considered "tomorrow".
+ int32_t dayDiff = cal.get(UCAL_JULIAN_DAY, status) - nowCal->get(UCAL_JULIAN_DAY, status);
+
+ delete nowCal;
+ return dayDiff;
+}
+
+U_NAMESPACE_END
+
+#endif
+
Property changes on: icu46/source/i18n/reldtfmt.cpp
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « icu46/source/i18n/reldtfmt.h ('k') | icu46/source/i18n/rematch.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698