icu4c/source/extra/uconv/uconv.vcxproj.filters -text
icu4c/source/i18n/i18n.vcxproj -text
icu4c/source/i18n/i18n.vcxproj.filters -text
+icu4c/source/i18n/shareddatefmt.h -text
+icu4c/source/i18n/shareddatetimepatterngenerator.h -text
icu4c/source/io/io.vcxproj -text
icu4c/source/io/io.vcxproj.filters -text
icu4c/source/layout/layout.vcxproj -text
#include "unicode/dtptngen.h"
#include "unicode/udisplaycontext.h"
#include "reldtfmt.h"
+#include "shareddatefmt.h"
+#include "shareddatetimepatterngenerator.h"
+#include "unifiedcache.h"
#include "cstring.h"
#include "windtfmt.h"
U_NAMESPACE_BEGIN
+SharedDateFormat::~SharedDateFormat() {
+ delete ptr;
+}
+
+// We must fully define LocaleCacheKey<SharedDateFormat>
+template<> U_I18N_API
+const SharedDateFormat *LocaleCacheKey<SharedDateFormat>::createObject(
+ const void * /*creationContext*/, UErrorCode &status) const {
+ status = U_UNSUPPORTED_ERROR;
+ return NULL;
+}
+
+class U_I18N_API DateFmtKeyByStyle : public LocaleCacheKey<SharedDateFormat> {
+ private:
+ DateFormat::EStyle fDateStyle;
+ DateFormat::EStyle fTimeStyle;
+ public:
+ DateFmtKeyByStyle(
+ const Locale &loc,
+ DateFormat::EStyle dateStyle,
+ DateFormat::EStyle timeStyle)
+ : LocaleCacheKey<SharedDateFormat>(loc),
+ fDateStyle(dateStyle),
+ fTimeStyle(timeStyle) { }
+ DateFmtKeyByStyle(const DateFmtKeyByStyle &other) :
+ LocaleCacheKey<SharedDateFormat>(other),
+ fDateStyle(other.fDateStyle),
+ fTimeStyle(other.fTimeStyle) { }
+ virtual ~DateFmtKeyByStyle();
+ virtual int32_t hashCode() const {
+ int32_t hash = 37 * LocaleCacheKey<SharedDateFormat>::hashCode() + fDateStyle;
+ hash = 37 * hash + fTimeStyle;
+ return hash;
+ }
+ virtual UBool operator==(const CacheKeyBase &other) const {
+ // reflexive
+ if (this == &other) {
+ return TRUE;
+ }
+ if (!LocaleCacheKey<SharedDateFormat>::operator==(other)) {
+ return FALSE;
+ }
+ // We know that this an other are of same class if we get this far.
+ const DateFmtKeyByStyle *realOther =
+ static_cast<const DateFmtKeyByStyle *>(&other);
+ return (realOther->fDateStyle == fDateStyle &&
+ realOther->fTimeStyle == fTimeStyle);
+ }
+ virtual CacheKeyBase *clone() const {
+ return new DateFmtKeyByStyle(*this);
+ }
+ virtual const SharedDateFormat *createObject(
+ const void * /*creationContext*/, UErrorCode &status) const {
+ DateFormat::EStyle dateStyle = fDateStyle;
+ if(dateStyle != DateFormat::kNone)
+ {
+ dateStyle = (DateFormat::EStyle) (dateStyle + DateFormat::kDateOffset);
+ }
+ DateFormat *fmt = DateFormat::create(fTimeStyle, dateStyle, fLoc);
+ if (fmt == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+ SharedDateFormat *result = new SharedDateFormat(fmt);
+ if (result == NULL) {
+ delete fmt;
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+ result->addRef();
+ return result;
+ }
+};
+
+DateFmtKeyByStyle::~DateFmtKeyByStyle() {
+}
+
+class U_I18N_API DateFmtKeyBySkeleton : public LocaleCacheKey<SharedDateFormat> {
+ private:
+ UnicodeString fSkeleton;
+ public:
+ DateFmtKeyBySkeleton(const Locale &loc, const UnicodeString &skeleton) :
+ LocaleCacheKey<SharedDateFormat>(loc),
+ fSkeleton(skeleton) { }
+ DateFmtKeyBySkeleton(const DateFmtKeyBySkeleton &other) :
+ LocaleCacheKey<SharedDateFormat>(other),
+ fSkeleton(other.fSkeleton) { }
+ virtual ~DateFmtKeyBySkeleton();
+ virtual int32_t hashCode() const {
+ return 37 * LocaleCacheKey<SharedDateFormat>::hashCode() + fSkeleton.hashCode();
+ }
+ virtual UBool operator==(const CacheKeyBase &other) const {
+ // reflexive
+ if (this == &other) {
+ return TRUE;
+ }
+ if (!LocaleCacheKey<SharedDateFormat>::operator==(other)) {
+ return FALSE;
+ }
+ // We know that this an other are of same class if we get this far.
+ const DateFmtKeyBySkeleton *realOther =
+ static_cast<const DateFmtKeyBySkeleton *>(&other);
+ return (realOther->fSkeleton == fSkeleton);
+ }
+ virtual CacheKeyBase *clone() const {
+ return new DateFmtKeyBySkeleton(*this);
+ }
+ virtual const SharedDateFormat *createObject(
+ const void *creationContext, UErrorCode &status) const {
+ void *mutableCreationContext = const_cast<void *>(creationContext);
+ DateTimePatternGenerator *ownedDtpg = NULL;
+ DateTimePatternGenerator *dtpg =
+ static_cast<DateTimePatternGenerator *>(mutableCreationContext);
+ if (dtpg == NULL) {
+ ownedDtpg = DateTimePatternGenerator::createInstance(fLoc, status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ dtpg = ownedDtpg;
+ }
+ DateFormat *fmt = new SimpleDateFormat(
+ dtpg->getBestPattern(fSkeleton, status),
+ fLoc,
+ status);
+ delete ownedDtpg;
+ if (fmt == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+ if (U_FAILURE(status)) {
+ delete fmt;
+ return NULL;
+ }
+ SharedDateFormat *result = new SharedDateFormat(fmt);
+ if (result == NULL) {
+ delete fmt;
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+ result->addRef();
+ return result;
+ }
+};
+
+DateFmtKeyBySkeleton::~DateFmtKeyBySkeleton() {
+}
+
+static DateFormat *createFromCache(
+ const CacheKey<SharedDateFormat> &key,
+ const void *context,
+ UErrorCode &status) {
+ const UnifiedCache *cache = UnifiedCache::getInstance(status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ const SharedDateFormat *ptr = NULL;
+ cache->get(key, context, ptr, status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ DateFormat *result = static_cast<DateFormat *>((*ptr)->clone());
+ ptr->removeRef();
+ if (result == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ }
+ return result;
+}
+
DateFormat::DateFormat()
: fCalendar(0),
fNumberFormat(0),
DateFormat::createTimeInstance(DateFormat::EStyle style,
const Locale& aLocale)
{
- return create(style, kNone, aLocale);
+ DateFmtKeyByStyle key(aLocale, kNone, style);
+ UErrorCode status = U_ZERO_ERROR;
+ return createFromCache(key, NULL, status);
}
//----------------------------------------------------------------------
DateFormat::createDateInstance(DateFormat::EStyle style,
const Locale& aLocale)
{
- // +4 to set the correct index for getting data out of
- // LocaleElements.
- if(style != kNone)
- {
- style = (EStyle) (style + kDateOffset);
- }
- return create(kNone, (EStyle) (style), aLocale);
+ DateFmtKeyByStyle key(aLocale, style, kNone);
+ UErrorCode status = U_ZERO_ERROR;
+ return createFromCache(key, NULL, status);
}
//----------------------------------------------------------------------
EStyle timeStyle,
const Locale& aLocale)
{
- if(dateStyle != kNone)
- {
- dateStyle = (EStyle) (dateStyle + kDateOffset);
- }
- return create(timeStyle, dateStyle, aLocale);
+ DateFmtKeyByStyle key(aLocale, dateStyle, timeStyle);
+ UErrorCode status = U_ZERO_ERROR;
+ return createFromCache(key, NULL, status);
}
//----------------------------------------------------------------------
DateFormat* U_EXPORT2
DateFormat::createInstance()
{
- return create(kShort, (EStyle) (kShort + kDateOffset), Locale::getDefault());
+ DateFmtKeyByStyle key(Locale::getDefault(), kShort, kShort);
+ UErrorCode status = U_ZERO_ERROR;
+ return createFromCache(key, NULL, status);
+}
+
+//----------------------------------------------------------------------
+
+DateFormat* U_EXPORT2
+DateFormat::createInstanceForSkeleton(
+ Calendar *calendarToAdopt,
+ const UnicodeString& skeleton,
+ const Locale &locale,
+ UErrorCode &status) {
+ LocalPointer<Calendar> calendar(calendarToAdopt);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ if (calendar.isNull()) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return NULL;
+ }
+ DateFmtKeyBySkeleton key(locale, skeleton);
+ DateFormat *result = createFromCache(key, NULL, status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ result->adoptCalendar(calendar.orphan());
+ return result;
+}
+
+DateFormat* U_EXPORT2
+DateFormat::createInstanceForSkeleton(
+ const UnicodeString& skeleton,
+ const Locale &locale,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ DateFmtKeyBySkeleton key(locale, skeleton);
+ return createFromCache(key, NULL, status);
+}
+
+DateFormat* U_EXPORT2
+DateFormat::createInstanceForSkeleton(
+ const UnicodeString& skeleton,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ DateFmtKeyBySkeleton key(Locale::getDefault(), skeleton);
+ return createFromCache(key, NULL, status);
+}
+
+DateFormat* U_EXPORT2
+DateFormat::internalCreateInstanceForSkeleton(
+ const UnicodeString& skeleton,
+ const Locale &locale,
+ DateTimePatternGenerator &gen,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ DateFmtKeyBySkeleton key(locale, skeleton);
+ return createFromCache(key, &gen, status);
}
//----------------------------------------------------------------------
*/
void
DateFormatSymbols::copyData(const DateFormatSymbols& other) {
+ UErrorCode status = U_ZERO_ERROR;
+ U_LOCALE_BASED(locBased, *this);
+ locBased.setLocaleIDs(
+ other.getLocale(ULOC_VALID_LOCALE, status),
+ other.getLocale(ULOC_ACTUAL_LOCALE, status));
assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
DateTimePatternGenerator* dtpng,
UErrorCode& status)
{
- if ( U_FAILURE(status) ) {
- return NULL;
- }
-
- const UnicodeString pattern = dtpng->getBestPattern(skeleton, status);
- if ( U_FAILURE(status) ) {
- return NULL;
- }
- SimpleDateFormat* dtfmt = new SimpleDateFormat(pattern, locale, status);
- if ( U_FAILURE(status) ) {
- delete dtfmt;
- return NULL;
- }
- return dtfmt;
+ DateFormat *df = DateFormat::internalCreateInstanceForSkeleton(
+ skeleton, locale, *dtpng, status);
+ return static_cast<SimpleDateFormat *>(df);
}
#include "hash.h"
#include "uresimp.h"
#include "dtptngen_impl.h"
+#include "shareddatetimepatterngenerator.h"
+#include "unifiedcache.h"
#if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
/**
U_NAMESPACE_BEGIN
+SharedDateTimePatternGenerator::~SharedDateTimePatternGenerator() {
+ delete ptr;
+}
+
+template<> U_I18N_API
+const SharedDateTimePatternGenerator *LocaleCacheKey<SharedDateTimePatternGenerator>::createObject(
+ const void * /*creationContext*/, UErrorCode &status) const {
+ DateTimePatternGenerator *fmt = DateTimePatternGenerator::internalMakeInstance(fLoc, status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ SharedDateTimePatternGenerator *result = new SharedDateTimePatternGenerator(fmt);
+ if (result == NULL) {
+ delete fmt;
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+ result->addRef();
+ return result;
+}
+
// *****************************************************************************
// class DateTimePatternGenerator
DateTimePatternGenerator* U_EXPORT2
DateTimePatternGenerator::createInstance(const Locale& locale, UErrorCode& status) {
+ const SharedDateTimePatternGenerator *shared = NULL;
+ UnifiedCache::getByLocale(locale, shared, status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ DateTimePatternGenerator *result = new DateTimePatternGenerator(**shared);
+ shared->removeRef();
+ if (result == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ }
+ return result;
+}
+
+
+DateTimePatternGenerator* U_EXPORT2
+DateTimePatternGenerator::internalMakeInstance(const Locale& locale, UErrorCode& status) {
DateTimePatternGenerator *result = new DateTimePatternGenerator(locale, status);
if (result == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
}
if (U_FAILURE(status)) {
delete result;
- result = NULL;
+ return NULL;
}
return result;
}
DateTimePatternGenerator&
DateTimePatternGenerator::operator=(const DateTimePatternGenerator& other) {
+ // reflexive case
+ if (&other == this) {
+ return *this;
+ }
pLocale = other.pLocale;
fDefaultHourFormatChar = other.fDefaultHourFormatChar;
*fp = *(other.fp);
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
-
+ curElem->skeletonWasSpecified = otherElem->skeletonWasSpecified;
if (prevElem!=NULL) {
prevElem->next=curElem;
}
<ClInclude Include="plurrule_impl.h" />\r
<ClInclude Include="quantityformatter.h" />\r
<ClInclude Include="sharedbreakiterator.h" />\r
+ <ClInclude Include="shareddatefmt.h" />\r
+ <ClInclude Include="shareddatetimepatterngenerator.h" />\r
<ClInclude Include="sharednumberformat.h" />\r
<ClInclude Include="sharedpluralrules.h" />\r
<CustomBuild Include="unicode\rbnf.h">\r
<ClInclude Include="sharedbreakiterator.h">\r
<Filter>formatting</Filter>\r
</ClInclude>\r
+ <ClInclude Include="shareddatefmt.h">\r
+ <Filter>formatting</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="shareddatetimepatterngenerator.h">\r
+ <Filter>formatting</Filter>\r
+ </ClInclude>\r
<ClInclude Include="sharednumberformat.h">\r
<Filter>formatting</Filter>\r
</ClInclude>\r
--- /dev/null
+/*
+******************************************************************************
+* Copyright (C) 2014, International Business Machines
+* Corporation and others. All Rights Reserved.
+******************************************************************************
+* shareddateformat.h
+*/
+
+#ifndef __SHARED_DATEFORMAT_H__
+#define __SHARED_DATEFORMAT_H__
+
+#include "unicode/utypes.h"
+#include "sharedobject.h"
+
+U_NAMESPACE_BEGIN
+
+class DateFormat;
+
+class U_I18N_API SharedDateFormat : public SharedObject {
+public:
+ SharedDateFormat(DateFormat *dfToAdopt) : ptr(dfToAdopt) { }
+ virtual ~SharedDateFormat();
+ const DateFormat *get() const { return ptr; }
+ const DateFormat *operator->() const { return ptr; }
+ const DateFormat &operator*() const { return *ptr; }
+private:
+ DateFormat *ptr;
+ SharedDateFormat(const SharedDateFormat &);
+ SharedDateFormat &operator=(const SharedDateFormat &);
+};
+
+U_NAMESPACE_END
+
+#endif
--- /dev/null
+/*
+******************************************************************************
+* Copyright (C) 2014, International Business Machines
+* Corporation and others. All Rights Reserved.
+******************************************************************************
+* shareddateformat.h
+*/
+
+#ifndef __SHARED_DATETIMEPATTERNGENERATOR_H__
+#define __SHARED_DATETIMEPATTERNGENERATOR_H__
+
+#include "unicode/utypes.h"
+#include "sharedobject.h"
+
+U_NAMESPACE_BEGIN
+
+class DateTimePatternGenerator;
+
+class U_I18N_API SharedDateTimePatternGenerator : public SharedObject {
+public:
+ SharedDateTimePatternGenerator(DateTimePatternGenerator *dtpgToAdopt) : ptr(dtpgToAdopt) { }
+ virtual ~SharedDateTimePatternGenerator();
+ const DateTimePatternGenerator *get() const { return ptr; }
+ const DateTimePatternGenerator *operator->() const { return ptr; }
+ const DateTimePatternGenerator &operator*() const { return *ptr; }
+private:
+ DateTimePatternGenerator *ptr;
+ SharedDateTimePatternGenerator(const SharedDateTimePatternGenerator &);
+ SharedDateTimePatternGenerator &operator=(const SharedDateTimePatternGenerator &);
+};
+
+U_NAMESPACE_END
+
+#endif
#include "umutex.h"
#include <float.h>
#include "smpdtfst.h"
+#include "sharednumberformat.h"
#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
#include <stdio.h>
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat)
+SimpleDateFormat::NSOverride::~NSOverride() {
+ if (snf != NULL) {
+ snf->removeRef();
+ }
+}
+
+
+void SimpleDateFormat::NSOverride::free() {
+ NSOverride *cur = this;
+ while (cur) {
+ NSOverride *next = cur->next;
+ delete cur;
+ cur = next;
+ }
+}
+
+// no matter what the locale's default number format looked like, we want
+// to modify it so that it doesn't use thousands separators, doesn't always
+// show the decimal point, and recognizes integers only when parsing
+static void fixNumberFormatForDates(NumberFormat &nf) {
+ nf.setGroupingUsed(FALSE);
+ DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(&nf);
+ if (decfmt != NULL) {
+ decfmt->setDecimalSeparatorAlwaysShown(FALSE);
+ }
+ nf.setParseIntegerOnly(TRUE);
+ nf.setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
+}
+
+static const SharedNumberFormat *createSharedNumberFormat(
+ NumberFormat *nfToAdopt) {
+ fixNumberFormatForDates(*nfToAdopt);
+ const SharedNumberFormat *result = new SharedNumberFormat(nfToAdopt);
+ if (result == NULL) {
+ delete nfToAdopt;
+ }
+ return result;
+}
+
+static const SharedNumberFormat *createSharedNumberFormat(
+ const Locale &loc, UErrorCode &status) {
+ NumberFormat *nf = NumberFormat::createInstance(loc, status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ const SharedNumberFormat *result = createSharedNumberFormat(nf);
+ if (result == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ }
+ return result;
+}
+
+static const SharedNumberFormat **allocSharedNumberFormatters() {
+ const SharedNumberFormat **result = (const SharedNumberFormat**)
+ uprv_malloc(UDAT_FIELD_COUNT * sizeof(const SharedNumberFormat*));
+ if (result == NULL) {
+ return NULL;
+ }
+ for (int32_t i = 0; i < UDAT_FIELD_COUNT; ++i) {
+ result[i] = NULL;
+ }
+ return result;
+}
+
+static void freeSharedNumberFormatters(const SharedNumberFormat ** list) {
+ for (int32_t i = 0; i < UDAT_FIELD_COUNT; ++i) {
+ SharedObject::clearPtr(list[i]);
+ }
+ uprv_free(list);
+}
+
+const NumberFormat &SimpleDateFormat::getNumberFormatByIndex(
+ UDateFormatField index) const {
+ if (fSharedNumberFormatters == NULL ||
+ fSharedNumberFormatters[index] == NULL) {
+ return *fNumberFormat;
+ }
+ return **fSharedNumberFormatters[index];
+}
+
+class SimpleDateFormatMutableNFNode {
+ public:
+ const NumberFormat *key;
+ NumberFormat *value;
+ SimpleDateFormatMutableNFNode()
+ : key(NULL), value(NULL) { }
+ ~SimpleDateFormatMutableNFNode() {
+ delete value;
+ }
+ private:
+ SimpleDateFormatMutableNFNode(const SimpleDateFormatMutableNFNode &);
+ SimpleDateFormatMutableNFNode &operator=(const SimpleDateFormatMutableNFNode &);
+};
+
+// Single threaded cache of non const NumberFormats. Designed to be stack
+// allocated and used for a single format call.
+class SimpleDateFormatMutableNFs : public UMemory {
+ public:
+ SimpleDateFormatMutableNFs() {
+ }
+
+ // Returns a non-const clone of nf which can be safely modified.
+ // Subsequent calls with same nf will return the same non-const clone.
+ // This object maintains ownership of all returned non-const
+ // NumberFormat objects. On memory allocation error returns NULL.
+ // Caller must check for NULL return value.
+ NumberFormat *get(const NumberFormat &nf) {
+ int32_t idx = 0;
+ while (nodes[idx].value) {
+ if (&nf == nodes[idx].key) {
+ return nodes[idx].value;
+ }
+ ++idx;
+ }
+ U_ASSERT(idx < UDAT_FIELD_COUNT);
+ nodes[idx].key = &nf;
+ nodes[idx].value = (NumberFormat *) nf.clone();
+ return nodes[idx].value;
+ }
+ private:
+ // +1 extra for sentinel. If each field had its own NumberFormat, this
+ // cache would have to allocate UDAT_FIELD_COUNT mutable versions worst
+ // case.
+ SimpleDateFormatMutableNFNode nodes[UDAT_FIELD_COUNT + 1];
+ SimpleDateFormatMutableNFs(const SimpleDateFormatMutableNFs &);
+ SimpleDateFormatMutableNFs &operator=(const SimpleDateFormatMutableNFs &);
+};
+
//----------------------------------------------------------------------
SimpleDateFormat::~SimpleDateFormat()
{
delete fSymbols;
- if (fNumberFormatters) {
- uprv_free(fNumberFormatters);
+ if (fSharedNumberFormatters) {
+ freeSharedNumberFormatters(fSharedNumberFormatters);
}
if (fTimeZoneFormat) {
delete fTimeZoneFormat;
}
- while (fOverrideList) {
- NSOverride *cur = fOverrideList;
- fOverrideList = cur->next;
- delete cur->nf;
- uprv_free(cur);
- }
-
#if !UCONFIG_NO_BREAK_ITERATION
delete fCapitalizationBrkIter;
#endif
: fLocale(Locale::getDefault()),
fSymbols(NULL),
fTimeZoneFormat(NULL),
- fNumberFormatters(NULL),
- fOverrideList(NULL),
+ fSharedNumberFormatters(NULL),
fCapitalizationBrkIter(NULL)
{
initializeBooleanAttributes();
fLocale(Locale::getDefault()),
fSymbols(NULL),
fTimeZoneFormat(NULL),
- fNumberFormatters(NULL),
- fOverrideList(NULL),
+ fSharedNumberFormatters(NULL),
fCapitalizationBrkIter(NULL)
{
fDateOverride.setToBogus();
fLocale(Locale::getDefault()),
fSymbols(NULL),
fTimeZoneFormat(NULL),
- fNumberFormatters(NULL),
- fOverrideList(NULL),
+ fSharedNumberFormatters(NULL),
fCapitalizationBrkIter(NULL)
{
fDateOverride.setTo(override);
: fPattern(pattern),
fLocale(locale),
fTimeZoneFormat(NULL),
- fNumberFormatters(NULL),
- fOverrideList(NULL),
+ fSharedNumberFormatters(NULL),
fCapitalizationBrkIter(NULL)
{
: fPattern(pattern),
fLocale(locale),
fTimeZoneFormat(NULL),
- fNumberFormatters(NULL),
- fOverrideList(NULL),
+ fSharedNumberFormatters(NULL),
fCapitalizationBrkIter(NULL)
{
fLocale(Locale::getDefault()),
fSymbols(symbolsToAdopt),
fTimeZoneFormat(NULL),
- fNumberFormatters(NULL),
- fOverrideList(NULL),
+ fSharedNumberFormatters(NULL),
fCapitalizationBrkIter(NULL)
{
fLocale(Locale::getDefault()),
fSymbols(new DateFormatSymbols(symbols)),
fTimeZoneFormat(NULL),
- fNumberFormatters(NULL),
- fOverrideList(NULL),
+ fSharedNumberFormatters(NULL),
fCapitalizationBrkIter(NULL)
{
: fLocale(locale),
fSymbols(NULL),
fTimeZoneFormat(NULL),
- fNumberFormatters(NULL),
- fOverrideList(NULL),
+ fSharedNumberFormatters(NULL),
fCapitalizationBrkIter(NULL)
{
initializeBooleanAttributes();
fLocale(locale),
fSymbols(NULL),
fTimeZoneFormat(NULL),
- fNumberFormatters(NULL),
- fOverrideList(NULL),
+ fSharedNumberFormatters(NULL),
fCapitalizationBrkIter(NULL)
{
if (U_FAILURE(status)) return;
fLocale(other.fLocale),
fSymbols(NULL),
fTimeZoneFormat(NULL),
- fNumberFormatters(NULL),
- fOverrideList(NULL),
+ fSharedNumberFormatters(NULL),
fCapitalizationBrkIter(NULL)
{
initializeBooleanAttributes();
return *this;
}
DateFormat::operator=(other);
+ fDateOverride = other.fDateOverride;
+ fTimeOverride = other.fTimeOverride;
delete fSymbols;
fSymbols = NULL;
}
#endif
+ if (fSharedNumberFormatters != NULL) {
+ freeSharedNumberFormatters(fSharedNumberFormatters);
+ fSharedNumberFormatters = NULL;
+ }
+ if (other.fSharedNumberFormatters != NULL) {
+ fSharedNumberFormatters = allocSharedNumberFormatters();
+ if (fSharedNumberFormatters) {
+ for (int32_t i = 0; i < UDAT_FIELD_COUNT; ++i) {
+ SharedObject::copyPtr(
+ other.fSharedNumberFormatters[i],
+ fSharedNumberFormatters[i]);
+ }
+ }
+ }
+
return *this;
}
fNumberFormat = NumberFormat::createInstance(locale, status);
if (fNumberFormat != NULL && U_SUCCESS(status))
{
- // no matter what the locale's default number format looked like, we want
- // to modify it so that it doesn't use thousands separators, doesn't always
- // show the decimal point, and recognizes integers only when parsing
-
- fNumberFormat->setGroupingUsed(FALSE);
- DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(fNumberFormat);
- if (decfmt != NULL) {
- decfmt->setDecimalSeparatorAlwaysShown(FALSE);
- }
- fNumberFormat->setParseIntegerOnly(TRUE);
- fNumberFormat->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
-
+ fixNumberFormatForDates(*fNumberFormat);
//fNumberFormat->setLenient(TRUE); // Java uses a custom DateNumberFormat to format/parse
initNumberFormatters(locale,status);
int32_t fieldNum = 0;
UDisplayContext capitalizationContext = getContext(UDISPCTX_TYPE_CAPITALIZATION, status);
+ // Create temporary cache of mutable number format objects. This way
+ // subFormat won't have to clone the const NumberFormat for each field.
+ // if several fields share the same NumberFormat, which will almost
+ // always be the case, this is a big save.
+ SimpleDateFormatMutableNFs mutableNFs;
// loop through the pattern string character by character
for (int32_t i = 0; i < fPattern.length() && U_SUCCESS(status); ++i) {
UChar ch = fPattern[i];
// Use subFormat() to format a repeated pattern character
// when a different pattern or non-pattern character is seen
if (ch != prevCh && count > 0) {
- subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status);
+ subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, mutableNFs, status);
count = 0;
}
if (ch == QUOTE) {
// Format the last item in the pattern, if any
if (count > 0) {
- subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status);
+ subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, mutableNFs, status);
}
if (calClone != NULL) {
return;
}
umtx_lock(&LOCK);
- if (fNumberFormatters == NULL) {
- fNumberFormatters = (NumberFormat**)uprv_malloc(UDAT_FIELD_COUNT * sizeof(NumberFormat*));
- if (fNumberFormatters) {
- for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) {
- fNumberFormatters[i] = fNumberFormat;
- }
- } else {
+ if (fSharedNumberFormatters == NULL) {
+ fSharedNumberFormatters = allocSharedNumberFormatters();
+ if (fSharedNumberFormatters == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
}
return;
}
- U_ASSERT(fNumberFormatters != NULL);
-
int32_t start = 0;
int32_t len;
UnicodeString nsName;
UnicodeString ovrField;
UBool moreToProcess = TRUE;
+ NSOverride *overrideList = NULL;
while (moreToProcess) {
int32_t delimiterPosition = str.indexOf((UChar)ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE,start);
int32_t nsNameHash = nsName.hashCode();
// See if the numbering system is in the override list, if not, then add it.
- NSOverride *cur = fOverrideList;
- NumberFormat *nf = NULL;
+ NSOverride *cur = overrideList;
+ const SharedNumberFormat *snf = NULL;
UBool found = FALSE;
while ( cur && !found ) {
if ( cur->hash == nsNameHash ) {
- nf = cur->nf;
+ snf = cur->snf;
found = TRUE;
}
cur = cur->next;
}
if (!found) {
- cur = (NSOverride *)uprv_malloc(sizeof(NSOverride));
- if (cur) {
+ LocalPointer<NSOverride> cur(new NSOverride);
+ if (!cur.isNull()) {
char kw[ULOC_KEYWORD_AND_VALUES_CAPACITY];
uprv_strcpy(kw,"numbers=");
nsName.extract(0,len,kw+8,ULOC_KEYWORD_AND_VALUES_CAPACITY-8,US_INV);
Locale ovrLoc(locale.getLanguage(),locale.getCountry(),locale.getVariant(),kw);
- nf = NumberFormat::createInstance(ovrLoc,status);
-
- // no matter what the locale's default number format looked like, we want
- // to modify it so that it doesn't use thousands separators, doesn't always
- // show the decimal point, and recognizes integers only when parsing
-
- if (U_SUCCESS(status)) {
- nf->setGroupingUsed(FALSE);
- DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(nf);
- if (decfmt != NULL) {
- decfmt->setDecimalSeparatorAlwaysShown(FALSE);
- }
- nf->setParseIntegerOnly(TRUE);
- nf->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
-
- cur->nf = nf;
- cur->hash = nsNameHash;
- cur->next = fOverrideList;
- fOverrideList = cur;
- }
- else {
- // clean up before returning
- if (cur != NULL) {
- uprv_free(cur);
+ cur->hash = nsNameHash;
+ cur->next = overrideList;
+ SharedObject::copyPtr(
+ createSharedNumberFormat(ovrLoc, status), cur->snf);
+ if (U_FAILURE(status)) {
+ if (overrideList) {
+ overrideList->free();
}
- return;
+ return;
}
-
+ snf = cur->snf;
+ overrideList = cur.orphan();
} else {
status = U_MEMORY_ALLOCATION_ERROR;
+ if (overrideList) {
+ overrideList->free();
+ }
return;
}
}
case kOvrStrDate:
case kOvrStrBoth: {
for ( int8_t i=0 ; i<kDateFieldsCount; i++ ) {
- fNumberFormatters[kDateFields[i]] = nf;
+ SharedObject::copyPtr(snf, fSharedNumberFormatters[kDateFields[i]]);
}
if (type==kOvrStrDate) {
break;
}
case kOvrStrTime : {
for ( int8_t i=0 ; i<kTimeFieldsCount; i++ ) {
- fNumberFormatters[kTimeFields[i]] = nf;
+ SharedObject::copyPtr(snf, fSharedNumberFormatters[kTimeFields[i]]);
}
break;
}
DateFormatSymbols::getPatternCharIndex(ovrField.charAt(0));
if (patternCharIndex == UDAT_FIELD_COUNT) {
status = U_INVALID_FORMAT_ERROR;
+ if (overrideList) {
+ overrideList->free();
+ }
return;
}
-
- // Set the number formatter in the table
- fNumberFormatters[patternCharIndex] = nf;
+ SharedObject::copyPtr(snf, fSharedNumberFormatters[patternCharIndex]);
}
start = delimiterPosition + 1;
}
+ if (overrideList) {
+ overrideList->free();
+ }
}
//---------------------------------------------------------------------
int32_t fieldNum,
FieldPositionHandler& handler,
Calendar& cal,
+ SimpleDateFormatMutableNFs &mutableNFs,
UErrorCode& status) const
{
if (U_FAILURE(status)) {
return;
}
- currentNumberFormat = getNumberFormatByIndex(patternCharIndex);
+ currentNumberFormat = mutableNFs.get(
+ getNumberFormatByIndex(patternCharIndex));
+ if (currentNumberFormat == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
UnicodeString hebr("hebr", 4, US_INV);
switch (patternCharIndex) {
//----------------------------------------------------------------------
void SimpleDateFormat::adoptNumberFormat(NumberFormat *formatToAdopt) {
- formatToAdopt->setParseIntegerOnly(TRUE);
- if (fNumberFormat && fNumberFormat != formatToAdopt){
- delete fNumberFormat;
- }
+ fixNumberFormatForDates(*formatToAdopt);
+ delete fNumberFormat;
fNumberFormat = formatToAdopt;
-
- if (fNumberFormatters) {
- for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) {
- if (fNumberFormatters[i] == formatToAdopt) {
- fNumberFormatters[i] = NULL;
- }
- }
- uprv_free(fNumberFormatters);
- fNumberFormatters = NULL;
- }
- while (fOverrideList) {
- NSOverride *cur = fOverrideList;
- fOverrideList = cur->next;
- if (cur->nf != formatToAdopt) { // only delete those not duplicate
- delete cur->nf;
- uprv_free(cur);
- } else {
- cur->nf = NULL;
- uprv_free(cur);
- }
+ // We successfully set the default number format. Now delete the overrides
+ // (can't fail).
+ if (fSharedNumberFormatters) {
+ freeSharedNumberFormatters(fSharedNumberFormatters);
+ fSharedNumberFormatters = NULL;
}
}
void SimpleDateFormat::adoptNumberFormat(const UnicodeString& fields, NumberFormat *formatToAdopt, UErrorCode &status){
- // if it has not been initialized yet, initialize
- if (fNumberFormatters == NULL) {
- fNumberFormatters = (NumberFormat**)uprv_malloc(UDAT_FIELD_COUNT * sizeof(NumberFormat*));
- if (fNumberFormatters) {
- for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) {
- fNumberFormatters[i] = fNumberFormat;
- }
- } else {
- status = U_MEMORY_ALLOCATION_ERROR;
- return;
- }
+ fixNumberFormatForDates(*formatToAdopt);
+ LocalPointer<NumberFormat> fmt(formatToAdopt);
+ if (U_FAILURE(status)) {
+ return;
}
-
- // See if the numbering format is in the override list, if not, then add it.
- NSOverride *cur = fOverrideList;
- UBool found = FALSE;
- while (cur && !found) {
- if ( cur->nf == formatToAdopt ) {
- found = TRUE;
- }
- cur = cur->next;
- }
-
- if (!found) {
- cur = (NSOverride *)uprv_malloc(sizeof(NSOverride));
- if (cur) {
- // no matter what the locale's default number format looked like, we want
- // to modify it so that it doesn't use thousands separators, doesn't always
- // show the decimal point, and recognizes integers only when parsing
- formatToAdopt->setGroupingUsed(FALSE);
- DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(formatToAdopt);
- if (decfmt != NULL) {
- decfmt->setDecimalSeparatorAlwaysShown(FALSE);
- }
- formatToAdopt->setParseIntegerOnly(TRUE);
- formatToAdopt->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
-
- cur->nf = formatToAdopt;
- cur->hash = -1; // set duplicate here (before we set it with NumberSystem Hash, here we cannot get nor use it)
- cur->next = fOverrideList;
- fOverrideList = cur;
- } else {
+
+ // We must ensure fSharedNumberFormatters is allocated.
+ if (fSharedNumberFormatters == NULL) {
+ fSharedNumberFormatters = allocSharedNumberFormatters();
+ if (fSharedNumberFormatters == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
}
-
+ const SharedNumberFormat *newFormat = createSharedNumberFormat(fmt.orphan());
+ if (newFormat == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
for (int i=0; i<fields.length(); i++) {
UChar field = fields.charAt(i);
// if the pattern character is unrecognized, signal an error and bail out
UDateFormatField patternCharIndex = DateFormatSymbols::getPatternCharIndex(field);
if (patternCharIndex == UDAT_FIELD_COUNT) {
status = U_INVALID_FORMAT_ERROR;
+ newFormat->deleteIfZeroRefCount();
return;
}
// Set the number formatter in the table
- fNumberFormatters[patternCharIndex] = formatToAdopt;
+ SharedObject::copyPtr(
+ newFormat, fSharedNumberFormatters[patternCharIndex]);
}
+ newFormat->deleteIfZeroRefCount();
}
const NumberFormat *
SimpleDateFormat::getNumberFormatForField(UChar field) const {
UDateFormatField index = DateFormatSymbols::getPatternCharIndex(field);
- return getNumberFormatByIndex(index);
-}
-
-NumberFormat *
-SimpleDateFormat::getNumberFormatByIndex(UDateFormatField index) const {
- if (fNumberFormatters != NULL) {
- return fNumberFormatters[index];
- } else {
- return fNumberFormat;
- }
+ return &getNumberFormatByIndex(index);
}
//----------------------------------------------------------------------
void
-SimpleDateFormat::zeroPaddingNumber(NumberFormat *currentNumberFormat,UnicodeString &appendTo,
- int32_t value, int32_t minDigits, int32_t maxDigits) const
+SimpleDateFormat::zeroPaddingNumber(
+ NumberFormat *currentNumberFormat,
+ UnicodeString &appendTo,
+ int32_t value, int32_t minDigits, int32_t maxDigits) const
{
if (currentNumberFormat!=NULL) {
FieldPosition pos(0);
int32_t saveHebrewMonth = -1;
int32_t count = 0;
UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
+ SimpleDateFormatMutableNFs mutableNFs;
// For parsing abutting numeric fields. 'abutPat' is the
// offset into 'pattern' of the first of 2 or more abutting
}
pos = subParse(text, pos, ch, count,
- TRUE, FALSE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType);
+ TRUE, FALSE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType, mutableNFs);
// If the parse fails anywhere in the run, back up to the
// start of the run and retry.
// fields.
else if (ch != 0x6C) { // pattern char 'l' (SMALL LETTER L) just gets ignored
int32_t s = subParse(text, pos, ch, count,
- FALSE, TRUE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType);
+ FALSE, TRUE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType, mutableNFs);
if (s == -pos-1) {
// era not present, in special cases allow this to continue
*/
int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UChar ch, int32_t count,
UBool obeyCount, UBool allowNegative, UBool ambiguousYear[], int32_t& saveHebrewMonth, Calendar& cal,
- int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType) const
+ int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType, SimpleDateFormatMutableNFs &mutableNFs) const
{
Formattable number;
int32_t value = 0;
return -start;
}
- currentNumberFormat = getNumberFormatByIndex(patternCharIndex);
+ currentNumberFormat = mutableNFs.get(getNumberFormatByIndex(patternCharIndex));
+ if (currentNumberFormat == NULL) {
+ return -start;
+ }
UCalendarDateFields field = fgPatternIndexToCalendarField[patternCharIndex];
UnicodeString hebr("hebr", 4, US_INV);
EStyle timeStyle = kDefault,
const Locale& aLocale = Locale::getDefault());
+#ifndef U_HIDE_DRAFT_API
+
+ /**
+ * Creates a date/time formatter for the given skeleton and
+ * default locale.
+ *
+ * @param skeleton The skeleton e.g "yMMMMd." Fields in the skeleton can
+ * be in any order, and this method uses the locale to
+ * map the skeleton to a pattern that includes locale
+ * specific separators with the fields in the appropriate
+ * order for that locale.
+ * @param status Any error returned here.
+ * @return A date/time formatter which the caller owns.
+ * @draft ICU 55
+ */
+ static DateFormat* U_EXPORT2 createInstanceForSkeleton(
+ const UnicodeString& skeleton,
+ UErrorCode &status);
+
+ /**
+ * Creates a date/time formatter for the given skeleton and locale.
+ *
+ * @param skeleton The skeleton e.g "yMMMMd." Fields in the skeleton can
+ * be in any order, and this method uses the locale to
+ * map the skeleton to a pattern that includes locale
+ * specific separators with the fields in the appropriate
+ * order for that locale.
+ * @param locale The given locale.
+ * @param status Any error returned here.
+ * @return A date/time formatter which the caller owns.
+ * @draft ICU 55
+ */
+ static DateFormat* U_EXPORT2 createInstanceForSkeleton(
+ const UnicodeString& skeleton,
+ const Locale &locale,
+ UErrorCode &status);
+
+ /**
+ * Creates a date/time formatter for the given skeleton and locale.
+ *
+ * @param calendarToAdopt the calendar returned DateFormat is to use.
+ * @param skeleton The skeleton e.g "yMMMMd." Fields in the skeleton can
+ * be in any order, and this method uses the locale to
+ * map the skeleton to a pattern that includes locale
+ * specific separators with the fields in the appropriate
+ * order for that locale.
+ * @param locale The given locale.
+ * @param status Any error returned here.
+ * @return A date/time formatter which the caller owns.
+ * @draft ICU 55
+ */
+ static DateFormat* U_EXPORT2 createInstanceForSkeleton(
+ Calendar *calendarToAdopt,
+ const UnicodeString& skeleton,
+ const Locale &locale,
+ UErrorCode &status);
+
+#endif /* U_HIDE_DRAFT_API */
+
+#ifndef U_HIDE_INTERNAL_API
+
+ /**
+ * Creates a date/time formatter for the given skeleton and locale and
+ * uses the given DateTimePatternGenerator to convert the skeleton to
+ * a format pattern. As creating a DateTimePatternGenerator is
+ * expensive, callers can supply it here (if they already have it) to save
+ * this method from creating its own.
+ *
+ * @param skeleton The skeleton e.g "yMMMMd." Fields in the skeleton can
+ * be in any order, and this method uses the provided
+ * DateTimePatternGenerator to map the skeleton to a
+ * pattern that includes appropriate separators with
+ * the fields in the appropriate order.
+ * @param locale The given locale.
+ * @param dpng The user supplied DateTimePatternGenerator. dpng
+ * must be created for the same locale as locale.
+ * Moreover, the caller must not modify dpng between
+ * creating it by locale and calling this method.
+ * Although dpng is a non-const reference, the caller
+ * must not regard it as an out or in-out parameter.
+ * The only reason dpng is a non-const reference is
+ * because its method, getBestPattern, which converts
+ * a skeleton to a date format pattern is non-const.
+ * @return A date/time formatter which the caller owns.
+ * @internal For ICU use only
+ */
+ static DateFormat* U_EXPORT2 internalCreateInstanceForSkeleton(
+ const UnicodeString& skeleton,
+ const Locale &locale,
+ DateTimePatternGenerator &dpng,
+ UErrorCode &status);
+
+#endif /* U_HIDE_INTERNAL_API */
+
/**
* Gets the set of locales for which DateFormats are installed.
* @param count Filled in with the number of locales in the list that is returned.
UDisplayContext fCapitalizationContext;
+ friend class DateFmtKeyByStyle;
public:
#ifndef U_HIDE_OBSOLETE_API
/*
*******************************************************************************
-* Copyright (C) 2007-2013, International Business Machines Corporation and
+* Copyright (C) 2007-2014, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
class DistanceInfo;
class PatternMap;
class PtnSkeleton;
+class SharedDateTimePatternGenerator;
/**
* This class provides flexible generation of date format patterns, like "yy-MM-dd".
*/
static DateTimePatternGenerator* U_EXPORT2 createInstance(const Locale& uLocale, UErrorCode& status);
+#ifndef U_HIDE_INTERNAL_API
+
+ /**
+ * For ICU use only
+ *
+ * @internal
+ */
+ static DateTimePatternGenerator* U_EXPORT2 internalMakeInstance(const Locale& uLocale, UErrorCode& status);
+
+#endif /* U_HIDE_INTERNAL_API */
+
/**
* Create an empty generator, to be constructed with addPattern(...) etc.
* @param status Output param set to success/failure code on exit,
class MessageFormat;
class FieldPositionHandler;
class TimeZoneFormat;
+class SharedNumberFormat;
+class SimpleDateFormatMutableNFs;
/**
*
int32_t fieldNum,
FieldPositionHandler& handler,
Calendar& cal,
+ SimpleDateFormatMutableNFs &mutableNFs,
UErrorCode& status) const; // in case of illegal argument
/**
*/
int32_t subParse(const UnicodeString& text, int32_t& start, UChar ch, int32_t count,
UBool obeyCount, UBool allowNegative, UBool ambiguousYear[], int32_t& saveHebrewMonth, Calendar& cal,
- int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType) const;
+ int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType, SimpleDateFormatMutableNFs &mutableNFs) const;
void parseInt(const UnicodeString& text,
Formattable& number,
*/
void initNumberFormatters(const Locale &locale,UErrorCode &status);
- /**
- * Get the numbering system to be used for a particular field.
- */
- NumberFormat * getNumberFormatByIndex(UDateFormatField index) const;
-
/**
* Parse the given override string and set up structures for number formats
*/
*/
TimeZoneFormat *tzFormat() const;
+ const NumberFormat &getNumberFormatByIndex(UDateFormatField index) const;
+
/**
* Used to map Calendar field to field level.
* The larger the level, the smaller the field unit.
*/
/*transient*/ int32_t fDefaultCenturyStartYear;
- typedef struct NSOverride {
- NumberFormat *nf;
+ struct NSOverride : public UMemory {
+ const SharedNumberFormat *snf;
int32_t hash;
NSOverride *next;
- } NSOverride;
-
- NumberFormat **fNumberFormatters;
+ void free();
+ NSOverride() : snf(NULL), hash(0), next(NULL) {
+ }
+ ~NSOverride();
+ };
- NSOverride *fOverrideList;
+ /**
+ * The number format in use for each date field. NULL means fall back
+ * to fNumberFormat in DateFormat.
+ */
+ const SharedNumberFormat **fSharedNumberFormatters;
UBool fHaveDefaultCentury;
u_uastrcpy(fields, "d");
u_uastrcpy(pattern,"MM d");
+
fmt=udat_open(UDAT_PATTERN, UDAT_PATTERN,"en_US",NULL,0,pattern, u_strlen(pattern), &status);
if (!assertSuccess("udat_open()", &status)) {
return;
}
-
- // loop 50 times to check getter/setter
+ // loop 5 times to check getter/setter
for (i = 0; i < 5; i++){
UNumberFormat* overrideFmt;
overrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
assertSuccess("unum_open()", &status);
-
udat_adoptNumberFormatForFields(fmt, fields, overrideFmt, &status);
overrideFmt = NULL; // no longer valid
assertSuccess("udat_setNumberFormatForField()", &status);
log_err("FAIL: udat_getNumberFormatForField did not return a valid pointer\n");
}
}
-
{
UNumberFormat* overrideFmt;
overrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
TESTCASE_AUTO(TestRelative);
TESTCASE_AUTO(TestRelativeClone);
TESTCASE_AUTO(TestHostClone);
+ TESTCASE_AUTO(TestHebrewClone);
+ TESTCASE_AUTO(TestDateFormatSymbolsClone);
TESTCASE_AUTO(TestTimeZoneDisplayName);
TESTCASE_AUTO(TestRoundtripWithCalendar);
TESTCASE_AUTO(Test6338);
TESTCASE_AUTO(TestParseLeniencyAPIs);
TESTCASE_AUTO(TestNumberFormatOverride);
+ TESTCASE_AUTO(TestCreateInstanceForSkeleton);
+ TESTCASE_AUTO(TestCreateInstanceForSkeletonDefault);
+ TESTCASE_AUTO(TestCreateInstanceForSkeletonWithCalendar);
TESTCASE_AUTO_END;
}
UDate now = Calendar::getNow();
DateFormat *full = DateFormat::createDateInstance(DateFormat::kFull, loc);
if (full == NULL) {
- dataerrln("FAIL: Can't create Relative date instance");
+ dataerrln("FAIL: Can't create host date instance");
return;
}
UnicodeString result1;
delete fullClone;
}
+void DateFormatTest::TestHebrewClone(void)
+{
+ /*
+ Verify that a cloned formatter gives the same results
+ and is useable after the original has been deleted.
+ */
+ UErrorCode status = U_ZERO_ERROR;
+ Locale loc("he@calendar=hebrew");
+ UDate now = Calendar::getNow();
+ LocalPointer<DateFormat> fmt(
+ DateFormat::createDateInstance(DateFormat::kLong, loc));
+ if (fmt.isNull()) {
+ dataerrln("FAIL: Can't create Hebrew date instance");
+ return;
+ }
+ UnicodeString result1;
+ fmt->format(now, result1, status);
+ LocalPointer<Format> fmtClone(fmt->clone());
+
+ // free fmt to be sure that fmtClone is independent of fmt.
+ fmt.adoptInstead(NULL);
+
+ UnicodeString result2;
+ fmtClone->format(now, result2, status);
+ ASSERT_OK(status);
+ if (result1 != result2) {
+ errln("FAIL: Clone returned different result from non-clone.");
+ }
+}
+
+static UBool getActualAndValidLocales(
+ const Format &fmt, Locale &valid, Locale &actual) {
+ const SimpleDateFormat* dat = dynamic_cast<const SimpleDateFormat*>(&fmt);
+ if (dat == NULL) {
+ return FALSE;
+ }
+ const DateFormatSymbols *sym = dat->getDateFormatSymbols();
+ if (sym == NULL) {
+ return FALSE;
+ }
+ UErrorCode status = U_ZERO_ERROR;
+ valid = sym->getLocale(ULOC_VALID_LOCALE, status);
+ actual = sym->getLocale(ULOC_ACTUAL_LOCALE, status);
+ return U_SUCCESS(status);
+}
+
+void DateFormatTest::TestDateFormatSymbolsClone(void)
+{
+ /*
+ Verify that a cloned formatter gives the same results
+ and is useable after the original has been deleted.
+ */
+ Locale loc("de_CH_LUCERNE");
+ LocalPointer<DateFormat> fmt(
+ DateFormat::createDateInstance(DateFormat::kDefault, loc));
+ Locale valid1;
+ Locale actual1;
+ if (!getActualAndValidLocales(*fmt, valid1, actual1)) {
+ errln("FAIL: Could not fetch valid + actual locales");
+ return;
+ }
+ LocalPointer<Format> fmtClone(fmt->clone());
+
+ // Free fmt to be sure that fmtClone is really independent of fmt.
+ fmt.adoptInstead(NULL);
+ Locale valid2;
+ Locale actual2;
+ if (!getActualAndValidLocales(*fmtClone, valid2, actual2)) {
+ errln("FAIL: Could not fetch valid + actual locales");
+ return;
+ }
+ if (valid1 != valid2 || actual1 != actual2) {
+ errln("Date format symbol locales of clone don't match original");
+ }
+}
+
void DateFormatTest::TestTimeZoneDisplayName()
{
// This test data was ported from ICU4J. Don't know why the 6th column in there because it's not being
return;
}
- NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
- assertSuccess("NumberFormat en_US", status);
- // loop 100 times to test setter/getter
- for(int i=0; i<100; i++){
+ for(int i=0; i<3; i++){
+ NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
+ assertSuccess("NumberFormat en_US", status);
fmt->adoptNumberFormat(fields, check_nf, status);
assertSuccess("adoptNumberFormat check_nf", status);
const NumberFormat* get_nf = fmt->getNumberFormatForField('M');
if (get_nf != check_nf) errln("FAIL: getter and setter do not work");
}
+ NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
+ assertSuccess("NumberFormat en_US", status);
fmt->adoptNumberFormat(check_nf); // make sure using the same NF will not crash
const char * DATA [][2] = {
errln("FAIL: Expected " + expected + " get: " + result);
}
}
+
+void DateFormatTest::TestCreateInstanceForSkeleton() {
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
+ "yMMMMd", "en", status));
+ if (!assertSuccess("Create with pattern yMMMMd", status)) {
+ return;
+ }
+ UnicodeString result;
+ FieldPosition pos(0);
+ fmt->format(date(98, 5-1, 25), result, pos);
+ assertEquals("format yMMMMd", "May 25, 1998", result);
+ fmt.adoptInstead(DateFormat::createInstanceForSkeleton(
+ "yMd", "en", status));
+ if (!assertSuccess("Create with pattern yMd", status)) {
+ return;
+ }
+ result.remove();
+ fmt->format(date(98, 5-1, 25), result, pos);
+ assertEquals("format yMd", "5/25/1998", result);
+}
+
+void DateFormatTest::TestCreateInstanceForSkeletonDefault() {
+ UErrorCode status = U_ZERO_ERROR;
+ Locale savedLocale;
+ Locale::setDefault(Locale::getUS(), status);
+ LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
+ "yMMMd", status));
+ Locale::setDefault(savedLocale, status);
+ if (!assertSuccess("Create with pattern yMMMd", status)) {
+ return;
+ }
+ UnicodeString result;
+ FieldPosition pos(0);
+ fmt->format(date(98, 5-1, 25), result, pos);
+ assertEquals("format yMMMd", "May 25, 1998", result);
+}
+
+void DateFormatTest::TestCreateInstanceForSkeletonWithCalendar() {
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<DateFormat> fmt(
+ DateFormat::createInstanceForSkeleton(
+ Calendar::createInstance(
+ TimeZone::createTimeZone("GMT-3:00"),
+ status),
+ "yMdHm", "en", status));
+ if (!assertSuccess("Create with pattern yMMMMd", status)) {
+ return;
+ }
+ UnicodeString result;
+ FieldPosition pos(0);
+
+ LocalPointer<Calendar> cal(Calendar::createInstance(
+ TimeZone::createTimeZone("GMT-7:00"),
+ status));
+ if (!assertSuccess("Creating GMT-7 time zone failed", status)) {
+ return;
+ }
+ cal->clear();
+ cal->set(1998, 5-1, 25, 0, 0, 0);
+
+ // date format time zone should be 4 hours ahead.
+ fmt->format(cal->getTime(status), result, pos);
+ assertEquals("format yMdHm", "5/25/1998, 04:00", result);
+ assertSuccess("", status);
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */
//eof
void TestHostClone(void);
+ void TestHebrewClone(void);
+
+ void TestDateFormatSymbolsClone(void);
+
void TestTimeZoneDisplayName(void);
void TestRoundtripWithCalendar(void);
// test override NumberFormat
void TestNumberFormatOverride();
+ void TestCreateInstanceForSkeleton();
+ void TestCreateInstanceForSkeletonDefault();
+ void TestCreateInstanceForSkeletonWithCalendar();
private:
UBool showParse(DateFormat &format, const UnicodeString &formattedString);
/*
**********************************************************************
-* Copyright (c) 2002-2011,International Business Machines
+* Copyright (c) 2002-2014,International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
**********************************************************************
TESTCASE(8,NumFmt100000);
TESTCASE(9,Collation10000);
TESTCASE(10,Collation100000);
+ TESTCASE(11, DIFCreate250);
+ TESTCASE(12, DIFCreate10000);
+ TESTCASE(13, TimeZoneCreate250);
+ TESTCASE(14, TimeZoneCreate10000);
+ TESTCASE(15, DTPatternGeneratorCreate250);
+ TESTCASE(16, DTPatternGeneratorCreate10000);
+ TESTCASE(17, DTPatternGeneratorCopy250);
+ TESTCASE(18, DTPatternGeneratorCopy10000);
+ TESTCASE(19, DTPatternGeneratorBestValue250);
+ TESTCASE(20, DTPatternGeneratorBestValue10000);
+ TESTCASE(21,DateFmtCopy250);
+ TESTCASE(22,DateFmtCopy10000);
+ TESTCASE(23,DateFmtCreate250);
+ TESTCASE(24,DateFmtCreate10000);
+
default:
name = "";
}
+UPerfFunction *DateFormatPerfTest::DIFCreate250() {
+ DIFCreateFunction* func = new DIFCreateFunction(250, locale);
+ return func;
+}
+
+UPerfFunction *DateFormatPerfTest::DIFCreate10000() {
+ DIFCreateFunction* func = new DIFCreateFunction(10000, locale);
+ return func;
+}
+
+UPerfFunction *DateFormatPerfTest::TimeZoneCreate250() {
+ return new TimeZoneCreateFunction(250, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::TimeZoneCreate10000() {
+ return new TimeZoneCreateFunction(10000, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::DTPatternGeneratorCreate250() {
+ return new DTPatternGeneratorCreateFunction(250, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::DTPatternGeneratorCreate10000() {
+ return new DTPatternGeneratorCreateFunction(10000, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::DTPatternGeneratorCopy250() {
+ return new DTPatternGeneratorCopyFunction(250, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::DTPatternGeneratorCopy10000() {
+ return new DTPatternGeneratorCopyFunction(10000, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::DTPatternGeneratorBestValue250() {
+ return new DTPatternGeneratorBestValueFunction(250, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::DTPatternGeneratorBestValue10000() {
+ return new DTPatternGeneratorBestValueFunction(10000, locale);
+}
+
+UPerfFunction* DateFormatPerfTest::DateFmtCopy250(){
+ return new DateFmtCopyFunction(250, locale);
+}
+
+UPerfFunction* DateFormatPerfTest::DateFmtCopy10000(){
+ return new DateFmtCopyFunction(10000, locale);
+}
+
+UPerfFunction* DateFormatPerfTest::DateFmtCreate250(){
+ return new DateFmtCreateFunction(250, locale);
+}
+
+UPerfFunction* DateFormatPerfTest::DateFmtCreate10000(){
+ return new DateFmtCreateFunction(10000, locale);
+}
+
int main(int argc, const char* argv[]){
/*
**********************************************************************
-* Copyright (c) 2002-2011,International Business Machines
+* Copyright (c) 2002-2014,International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
**********************************************************************
#include "unicode/unistr.h"
#include "unicode/uperf.h"
+#include "unicode/dtitvfmt.h"
#include "unicode/utypes.h"
#include "unicode/datefmt.h"
#include "unicode/calendar.h"
BreakItFunction(){num = -1;}
BreakItFunction(int a, bool b){num = a; wordIteration = b;}
- virtual void call(UErrorCode *status)
+ virtual void call(UErrorCode * status)
{
BreakIterator* boundary;
};
+class DateFmtCreateFunction : public UPerfFunction
+{
+
+private:
+ int num;
+ char locale[25];
+public:
+
+ DateFmtCreateFunction(int a, const char* loc)
+ {
+ num = a;
+ strcpy(locale, loc);
+ }
+
+ virtual void call(UErrorCode* /* status */)
+ {
+
+ Locale loc(locale);
+ DateFormat *fmt;
+ // (dates are imported from datedata.h)
+ for(int j = 0; j < num; j++) {
+ fmt = DateFormat::createDateTimeInstance(
+ DateFormat::kShort, DateFormat::kFull, loc);
+ delete fmt;
+ }
+ }
+
+ virtual long getOperationsPerIteration()
+ {
+ return num;
+ }
+
+};
+
+class DateFmtCopyFunction : public UPerfFunction
+{
+
+private:
+ int num;
+ char locale[25];
+public:
+
+ DateFmtCopyFunction()
+ {
+ num = -1;
+ }
+
+ DateFmtCopyFunction(int a, const char* loc)
+ {
+ num = a;
+ strcpy(locale, loc);
+ }
+
+ virtual void call(UErrorCode* /* status */)
+ {
+ Locale loc(locale);
+ UErrorCode status2 = U_ZERO_ERROR;
+ DateFormat *fmt = DateFormat::createDateTimeInstance(
+ DateFormat::kShort, DateFormat::kFull, loc);
+ for(int j = 0; j < num; j++) {
+ Format *cp = fmt->clone();
+ delete cp;
+ }
+ delete fmt;
+ }
+
+ virtual long getOperationsPerIteration()
+ {
+ return num;
+ }
+
+ // Verify that a UErrorCode is successful; exit(1) if not
+ void check(UErrorCode& status, const char* msg) {
+ if (U_FAILURE(status)) {
+ printf("ERROR: %s (%s)\n", u_errorName(status), msg);
+ exit(1);
+ }
+ }
+
+};
+
+class DIFCreateFunction : public UPerfFunction
+{
+
+private:
+ int num;
+ char locale[25];
+public:
+
+ DIFCreateFunction()
+ {
+ num = -1;
+ }
+
+ DIFCreateFunction(int a, const char* loc)
+ {
+ num = a;
+ strcpy(locale, loc);
+ }
+
+ virtual void call(UErrorCode* /* status */)
+ {
+ UErrorCode status2 = U_ZERO_ERROR;
+ Calendar *cal;
+ TimeZone *zone;
+
+ cal = Calendar::createInstance(status2);
+ check(status2, "Calendar::createInstance");
+ zone = TimeZone::createTimeZone("GMT"); // Create a GMT zone
+ cal->adoptTimeZone(zone);
+
+ Locale loc(locale);
+ UnicodeString skeleton("yMMMMdHms");
+
+ for(int j = 0; j < num; j++) {
+ DateIntervalFormat* fmt(DateIntervalFormat::createInstance(skeleton, loc, status2));
+ delete fmt;
+ }
+ delete cal;
+ }
+
+ virtual long getOperationsPerIteration()
+ {
+ return num;
+ }
+
+ // Verify that a UErrorCode is successful; exit(1) if not
+ void check(UErrorCode& status, const char* msg) {
+ if (U_FAILURE(status)) {
+ printf("ERROR: %s (%s)\n", u_errorName(status), msg);
+ exit(1);
+ }
+ }
+
+};
+
+class TimeZoneCreateFunction : public UPerfFunction
+{
+
+private:
+ int num;
+ char locale[25];
+public:
+
+ TimeZoneCreateFunction()
+ {
+ num = -1;
+ }
+
+ TimeZoneCreateFunction(int a, const char* loc)
+ {
+ num = a;
+ strcpy(locale, loc);
+ }
+
+ virtual void call(UErrorCode* /* status */)
+ {
+ Locale loc(locale);
+ UnicodeString tzname("UTC");
+ for(int j = 0; j < num; j++) {
+ TimeZone* tz(TimeZone::createTimeZone(tzname));
+ delete tz;
+ }
+ }
+
+ virtual long getOperationsPerIteration()
+ {
+ return num;
+ }
+
+ // Verify that a UErrorCode is successful; exit(1) if not
+ void check(UErrorCode& status, const char* msg) {
+ if (U_FAILURE(status)) {
+ printf("ERROR: %s (%s)\n", u_errorName(status), msg);
+ exit(1);
+ }
+ }
+
+};
+
+class DTPatternGeneratorCreateFunction : public UPerfFunction
+{
+
+private:
+ int num;
+ char locale[25];
+public:
+
+ DTPatternGeneratorCreateFunction()
+ {
+ num = -1;
+ }
+
+ DTPatternGeneratorCreateFunction(int a, const char* loc)
+ {
+ num = a;
+ strcpy(locale, loc);
+ }
+
+ virtual void call(UErrorCode* /* status */)
+ {
+ UErrorCode status2 = U_ZERO_ERROR;
+ Locale loc(locale);
+
+ for(int j = 0; j < num; j++) {
+ DateTimePatternGenerator* gen(DateTimePatternGenerator::createInstance(loc, status2));
+ delete gen;
+ }
+ }
+
+ virtual long getOperationsPerIteration()
+ {
+ return num;
+ }
+
+ // Verify that a UErrorCode is successful; exit(1) if not
+ void check(UErrorCode& status, const char* msg) {
+ if (U_FAILURE(status)) {
+ printf("ERROR: %s (%s)\n", u_errorName(status), msg);
+ exit(1);
+ }
+ }
+
+};
+
+class DTPatternGeneratorCopyFunction : public UPerfFunction
+{
+
+private:
+ int num;
+ char locale[25];
+public:
+
+ DTPatternGeneratorCopyFunction()
+ {
+ num = -1;
+ }
+
+ DTPatternGeneratorCopyFunction(int a, const char* loc)
+ {
+ num = a;
+ strcpy(locale, loc);
+ }
+
+ virtual void call(UErrorCode* /* status */)
+ {
+ UErrorCode status2 = U_ZERO_ERROR;
+ Locale loc(locale);
+ DateTimePatternGenerator* gen(DateTimePatternGenerator::createInstance(loc, status2));
+
+ for(int j = 0; j < num; j++) {
+ DateTimePatternGenerator *cl = gen->clone();
+ delete cl;
+ }
+ delete gen;
+ }
+
+ virtual long getOperationsPerIteration()
+ {
+ return num;
+ }
+
+ // Verify that a UErrorCode is successful; exit(1) if not
+ void check(UErrorCode& status, const char* msg) {
+ if (U_FAILURE(status)) {
+ printf("ERROR: %s (%s)\n", u_errorName(status), msg);
+ exit(1);
+ }
+ }
+
+};
+
+class DTPatternGeneratorBestValueFunction : public UPerfFunction
+{
+
+private:
+ int num;
+ char locale[25];
+public:
+
+ DTPatternGeneratorBestValueFunction()
+ {
+ num = -1;
+ }
+
+ DTPatternGeneratorBestValueFunction(int a, const char* loc)
+ {
+ num = a;
+ strcpy(locale, loc);
+ }
+
+ virtual void call(UErrorCode* /* status */)
+ {
+ UErrorCode status2 = U_ZERO_ERROR;
+ Locale loc(locale);
+ DateTimePatternGenerator* gen(DateTimePatternGenerator::createInstance(loc, status2));
+ UnicodeString skeleton("yMMMMdHms");
+
+ for(int j = 0; j < num; j++) {
+ gen->getBestPattern(skeleton, status2);
+ }
+ check(status2, "getBestPattern");
+ delete gen;
+ }
+
+ virtual long getOperationsPerIteration()
+ {
+ return num;
+ }
+
+ // Verify that a UErrorCode is successful; exit(1) if not
+ void check(UErrorCode& status, const char* msg) {
+ if (U_FAILURE(status)) {
+ printf("ERROR: %s (%s)\n", u_errorName(status), msg);
+ exit(1);
+ }
+ }
+
+};
+
class NumFmtFunction : public UPerfFunction
{
UPerfFunction* DateFmt250();
UPerfFunction* DateFmt10000();
UPerfFunction* DateFmt100000();
+ UPerfFunction* DateFmtCreate250();
+ UPerfFunction* DateFmtCreate10000();
+ UPerfFunction* DateFmtCopy250();
+ UPerfFunction* DateFmtCopy10000();
UPerfFunction* BreakItWord250();
UPerfFunction* BreakItWord10000();
UPerfFunction* BreakItChar250();
UPerfFunction* NumFmt100000();
UPerfFunction* Collation10000();
UPerfFunction* Collation100000();
+ UPerfFunction* DIFCreate250();
+ UPerfFunction* DIFCreate10000();
+ UPerfFunction* TimeZoneCreate250();
+ UPerfFunction* TimeZoneCreate10000();
+ UPerfFunction* DTPatternGeneratorCreate250();
+ UPerfFunction* DTPatternGeneratorCreate10000();
+ UPerfFunction* DTPatternGeneratorCopy250();
+ UPerfFunction* DTPatternGeneratorCopy10000();
+ UPerfFunction* DTPatternGeneratorBestValue250();
+ UPerfFunction* DTPatternGeneratorBestValue10000();
};
#endif // DateFmtPerf