ICU-8464 Add Suggested changes from Markus.

X-SVN-Rev: 34875
This commit is contained in:
Travis Keep 2014-01-11 00:30:39 +00:00
parent 8067293d35
commit 132ff6d742
12 changed files with 476 additions and 326 deletions

2
.gitattributes vendored
View file

@ -55,6 +55,8 @@ icu4c/source/common/common.vcxproj -text
icu4c/source/common/common.vcxproj.filters -text
icu4c/source/common/lrucache.cpp -text
icu4c/source/common/lrucache.h -text
icu4c/source/common/sharedobject.cpp -text
icu4c/source/common/sharedobject.h -text
icu4c/source/common/sharedptr.h -text
icu4c/source/data/curr/pool.res -text
icu4c/source/data/in/coll/invuca.icu -text

View file

@ -1,6 +1,6 @@
#******************************************************************************
#
# Copyright (C) 1999-2013, International Business Machines
# Copyright (C) 1999-2014, International Business Machines
# Corporation and others. All Rights Reserved.
#
#******************************************************************************
@ -104,7 +104,8 @@ rbbi.o rbbidata.o rbbinode.o rbbirb.o rbbiscan.o rbbisetb.o rbbistbl.o rbbitblb.
serv.o servnotf.o servls.o servlk.o servlkf.o servrbf.o servslkf.o \
uidna.o usprep.o uts46.o punycode.o \
util.o util_props.o parsepos.o locbased.o cwchar.o wintz.o dtintrv.o ucnvsel.o propsvec.o \
ulist.o uloc_tag.o icudataver.o icuplug.o listformatter.o lrucache.o
ulist.o uloc_tag.o icudataver.o icuplug.o listformatter.o lrucache.o \
sharedobject.o
## Header files to install
HEADERS = $(srcdir)/unicode/*.h

View file

@ -1084,6 +1084,8 @@
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
</CustomBuild>
<ClInclude Include="sharedobject.h" />
<ClCompile Include="sharedobject.cpp" />
<ClInclude Include="sharedptr.h" />
<CustomBuild Include="unicode\ucat.h">
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode

View file

@ -244,6 +244,9 @@
<ClCompile Include="cmemory.c">
<Filter>data &amp; memory</Filter>
</ClCompile>
<ClCompile Include="sharedobject.cpp">
<Filter>data &amp; memory</Filter>
</ClCompile>
<ClCompile Include="ucln_cmn.c">
<Filter>data &amp; memory</Filter>
</ClCompile>
@ -702,6 +705,9 @@
<ClInclude Include="cmemory.h">
<Filter>data &amp; memory</Filter>
</ClInclude>
<ClInclude Include="sharedobject.h">
<Filter>data &amp; memory</Filter>
</ClInclude>
<ClInclude Include="sharedptr.h">
<Filter>data &amp; memory</Filter>
</ClInclude>

View file

@ -1,50 +1,33 @@
/*
*******************************************************************************
* Copyright (C) 2013, International Business Machines Corporation and
******************************************************************************
* Copyright (C) 2014, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
******************************************************************************
*
* File LRUCACHE.CPP
*******************************************************************************
******************************************************************************
*/
#include "lrucache.h"
#include "uhash.h"
#include "cstring.h"
#include "uassert.h"
U_NAMESPACE_BEGIN
// Named CacheEntry2 to avoid conflict with CacheEntry in serv.cpp
// Don't know how to make truly private class that the linker can't see.
class CacheEntry2 : public UMemory {
public:
CacheEntry2 *moreRecent;
CacheEntry2 *lessRecent;
char *localeId;
SharedPtr<UObject> cachedData;
UErrorCode status; // This is the error if any from creating cachedData.
// TODO (Travis Keep): Consider building synchronization into this cache
// instead of leaving synchronization up to the clients.
CacheEntry2();
~CacheEntry2();
void unlink();
void uninit();
UBool init(const char *localeId, UObject *dataToAdopt, UErrorCode err);
private:
CacheEntry2(const CacheEntry2& other);
CacheEntry2 &operator=(const CacheEntry2& other);
};
CacheEntry2::CacheEntry2()
: moreRecent(NULL), lessRecent(NULL), localeId(NULL), cachedData(),
LRUCache::CacheEntry::CacheEntry()
: moreRecent(NULL), lessRecent(NULL), localeId(NULL), cachedData(NULL),
status(U_ZERO_ERROR) {
}
CacheEntry2::~CacheEntry2() {
uninit();
LRUCache::CacheEntry::~CacheEntry() {
reset();
}
void CacheEntry2::unlink() {
void LRUCache::CacheEntry::unlink() {
if (moreRecent != NULL) {
moreRecent->lessRecent = lessRecent;
}
@ -55,8 +38,8 @@ void CacheEntry2::unlink() {
lessRecent = NULL;
}
void CacheEntry2::uninit() {
cachedData.clear();
void LRUCache::CacheEntry::reset() {
SharedObject::clearPtr(cachedData);
status = U_ZERO_ERROR;
if (localeId != NULL) {
uprv_free(localeId);
@ -64,23 +47,18 @@ void CacheEntry2::uninit() {
localeId = NULL;
}
UBool CacheEntry2::init(const char *locId, UObject *dataToAdopt, UErrorCode err) {
uninit();
localeId = (char *) uprv_malloc(strlen(locId) + 1);
if (localeId == NULL) {
delete dataToAdopt;
return FALSE;
}
uprv_strcpy(localeId, locId);
if (!cachedData.adoptInstead(dataToAdopt)) {
status = U_MEMORY_ALLOCATION_ERROR;
return TRUE;
}
void LRUCache::CacheEntry::init(
char *adoptedLocId, SharedObject *dataToAdopt, UErrorCode err) {
U_ASSERT(localeId == NULL);
localeId = adoptedLocId;
SharedObject::copyPtr(dataToAdopt, cachedData);
status = err;
return TRUE;
}
void LRUCache::moveToMostRecent(CacheEntry2 *entry) {
void LRUCache::moveToMostRecent(LRUCache::CacheEntry *entry) {
if (entry->moreRecent == mostRecentlyUsedMarker) {
return;
}
entry->unlink();
entry->moreRecent = mostRecentlyUsedMarker;
entry->lessRecent = mostRecentlyUsedMarker->lessRecent;
@ -88,29 +66,10 @@ void LRUCache::moveToMostRecent(CacheEntry2 *entry) {
mostRecentlyUsedMarker->lessRecent = entry;
}
UObject *LRUCache::safeCreate(const char *localeId, UErrorCode &status) {
UObject *result = create(localeId, status);
// Safe guard to ensure that some error is reported for missing data in
// case subclass forgets to set status.
if (result == NULL && U_SUCCESS(status)) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
// Safe guard to ensure that if subclass reports an error and returns
// data that we don't leak memory.
if (result != NULL && U_FAILURE(status)) {
delete result;
return NULL;
}
return result;
}
UBool LRUCache::init(const char *localeId, CacheEntry2 *entry) {
void LRUCache::init(char *adoptedLocId, LRUCache::CacheEntry *entry) {
UErrorCode status = U_ZERO_ERROR;
UObject *result = safeCreate(localeId, status);
return entry->init(localeId, result, status);
SharedObject *result = create(adoptedLocId, status);
entry->init(adoptedLocId, result, status);
}
UBool LRUCache::contains(const char *localeId) const {
@ -118,56 +77,53 @@ UBool LRUCache::contains(const char *localeId) const {
}
void LRUCache::_get(const char *localeId, SharedPtr<UObject>& ptr, UErrorCode &status) {
CacheEntry2 *entry = (CacheEntry2 *) uhash_get(localeIdToEntries, localeId);
if (entry != NULL) {
moveToMostRecent(entry);
} else {
const SharedObject *LRUCache::_get(const char *localeId, UErrorCode &status) {
// TODO (Travis Keep): Consider stripping irrelevant locale keywords.
LRUCache::CacheEntry *entry = (LRUCache::CacheEntry *) uhash_get(
localeIdToEntries, localeId);
if (entry == NULL) {
// Its a cache miss.
if (uhash_count(localeIdToEntries) < maxSize) {
entry = new CacheEntry2;
// Cache not full. There is room for a new entry.
entry = new LRUCache::CacheEntry;
if (entry == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
} else {
// Cache full. Must evict an entry and re-use it.
entry = leastRecentlyUsedMarker->moreRecent;
uhash_remove(localeIdToEntries, entry->localeId);
entry->unlink();
entry->uninit();
entry->reset();
}
// entry is an uninitialized, unlinked cache entry
// or entry is null if memory could not be allocated.
if (entry != NULL) {
if (!init(localeId, entry)) {
delete entry;
entry = NULL;
}
char *dupLocaleId = uprv_strdup(localeId);
if (dupLocaleId == NULL) {
delete entry;
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
init(dupLocaleId, entry);
// Entry is initialized, but unlinked or entry is null on
// memory allocation error.
if (entry != NULL) {
// Add to hashtable
uhash_put(localeIdToEntries, entry->localeId, entry, &status);
if (U_FAILURE(status)) {
delete entry;
entry = NULL;
}
}
if (entry != NULL) {
moveToMostRecent(entry);
// Entry is initialized, add to hashtable
uhash_put(localeIdToEntries, entry->localeId, entry, &status);
if (U_FAILURE(status)) {
delete entry;
return NULL;
}
}
if (entry == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
// If we get here our data is cached.
// Re-link entry so that it is the most recent.
moveToMostRecent(entry);
if (U_FAILURE(entry->status)) {
status = entry->status;
return;
return NULL;
}
ptr = entry->cachedData;
return entry->cachedData;
}
LRUCache::LRUCache(int32_t size, UErrorCode &status) :
@ -178,8 +134,8 @@ LRUCache::LRUCache(int32_t size, UErrorCode &status) :
if (U_FAILURE(status)) {
return;
}
mostRecentlyUsedMarker = new CacheEntry2;
leastRecentlyUsedMarker = new CacheEntry2;
mostRecentlyUsedMarker = new LRUCache::CacheEntry;
leastRecentlyUsedMarker = new LRUCache::CacheEntry;
if (mostRecentlyUsedMarker == NULL || leastRecentlyUsedMarker == NULL) {
delete mostRecentlyUsedMarker;
delete leastRecentlyUsedMarker;
@ -204,8 +160,8 @@ LRUCache::LRUCache(int32_t size, UErrorCode &status) :
LRUCache::~LRUCache() {
uhash_close(localeIdToEntries);
for (CacheEntry2 *i = mostRecentlyUsedMarker; i != NULL;) {
CacheEntry2 *next = i->lessRecent;
for (LRUCache::CacheEntry *i = mostRecentlyUsedMarker; i != NULL;) {
LRUCache::CacheEntry *next = i->lessRecent;
delete i;
i = next;
}
@ -214,7 +170,7 @@ LRUCache::~LRUCache() {
SimpleLRUCache::~SimpleLRUCache() {
}
UObject *SimpleLRUCache::create(const char *localeId, UErrorCode &status) {
SharedObject *SimpleLRUCache::create(const char *localeId, UErrorCode &status) {
return createFunc(localeId, status);
}

View file

@ -1,18 +1,18 @@
/*
*******************************************************************************
* Copyright (C) 2013, International Business Machines Corporation and
******************************************************************************
* Copyright (C) 2014, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
******************************************************************************
*
* File LRUCACHE.H
*******************************************************************************
******************************************************************************
*/
#ifndef __LRU_CACHE_H__
#define __LRU_CACHE_H__
#include "unicode/uobject.h"
#include "sharedptr.h"
#include "sharedobject.h"
struct UHashtable;
@ -22,40 +22,60 @@ U_NAMESPACE_BEGIN
* LRUCache keyed by locale ID.
*/
class CacheEntry2;
class SharedObject;
class U_COMMON_API LRUCache : public UObject {
public:
public:
template<typename T>
void get(const char *localeId, SharedPtr<T> &ptr, UErrorCode &status) {
SharedPtr<UObject> p;
_get(localeId, p, status);
void get(const char *localeId, const T *&ptr, UErrorCode &status) {
const T *value = (const T *) _get(localeId, status);
if (U_FAILURE(status)) {
return;
}
ptr = p;
SharedObject::copyPtr(value, ptr);
}
UBool contains(const char *localeId) const;
virtual ~LRUCache();
protected:
virtual UObject *create(const char *localeId, UErrorCode &status)=0;
protected:
virtual SharedObject *create(const char *localeId, UErrorCode &status)=0;
LRUCache(int32_t maxSize, UErrorCode &status);
private:
private:
class CacheEntry : public UMemory {
public:
CacheEntry *moreRecent;
CacheEntry *lessRecent;
char *localeId;
const SharedObject *cachedData;
UErrorCode status; // This is the error if any from creating
// cachedData.
CacheEntry();
~CacheEntry();
void unlink();
void reset();
void init(
char *adoptedLocId, SharedObject *dataToAdopt, UErrorCode err);
private:
CacheEntry(const CacheEntry& other);
CacheEntry &operator=(const CacheEntry& other);
};
LRUCache();
LRUCache(const LRUCache &other);
LRUCache &operator=(const LRUCache &other);
UObject *safeCreate(const char *localeId, UErrorCode &status);
CacheEntry2 *mostRecentlyUsedMarker;
CacheEntry2 *leastRecentlyUsedMarker;
// TODO (Travis Keep): Consider replacing both of these end nodes with a
// single sentinel.
CacheEntry *mostRecentlyUsedMarker;
CacheEntry *leastRecentlyUsedMarker;
UHashtable *localeIdToEntries;
int32_t maxSize;
void moveToMostRecent(CacheEntry2 *cacheEntry);
UBool init(const char *localeId, CacheEntry2 *cacheEntry);
void _get(const char *localeId, SharedPtr<UObject> &ptr, UErrorCode &status);
void moveToMostRecent(CacheEntry *cacheEntry);
void init(char *localeId, CacheEntry *cacheEntry);
const SharedObject *_get(const char *localeId, UErrorCode &status);
};
typedef UObject *(*CreateFunc)(const char *localeId, UErrorCode &status);
typedef SharedObject *CreateFunc(const char *localeId, UErrorCode &status);
class U_COMMON_API SimpleLRUCache : public LRUCache {
public:
@ -67,9 +87,9 @@ public:
}
virtual ~SimpleLRUCache();
protected:
virtual UObject *create(const char *localeId, UErrorCode &status);
virtual SharedObject *create(const char *localeId, UErrorCode &status);
private:
CreateFunc createFunc;
CreateFunc *createFunc;
};
U_NAMESPACE_END

View file

@ -0,0 +1,37 @@
/*
******************************************************************************
* Copyright (C) 2014, International Business Machines
* Corporation and others. All Rights Reserved.
******************************************************************************
* sharedobject.cpp
*/
#include "sharedobject.h"
U_NAMESPACE_BEGIN
SharedObject::~SharedObject() {}
void
SharedObject::addRef() const {
umtx_atomic_inc(&refCount);
}
void
SharedObject::removeRef() const {
if(umtx_atomic_dec(&refCount) == 0) {
delete this;
}
}
int32_t
SharedObject::getRefCount() const {
return umtx_loadAcquire(refCount);
}
void
SharedObject::deleteIfZeroRefCount() const {
if(getRefCount() == 0) {
delete this;
}
}
U_NAMESPACE_END

View file

@ -0,0 +1,111 @@
/*
******************************************************************************
* Copyright (C) 2014, International Business Machines
* Corporation and others. All Rights Reserved.
******************************************************************************
* sharedobject.h
*/
#ifndef __SHAREDOBJECT_H__
#define __SHAREDOBJECT_H__
#include "unicode/uobject.h"
#include "umutex.h"
U_NAMESPACE_BEGIN
/**
* Base class for shared, reference-counted, auto-deleted objects.
* Subclasses can be immutable.
* If they are mutable, then they must implement their copy constructor
* so that copyOnWrite() works.
*
* Either stack-allocate, use LocalPointer, or use addRef()/removeRef().
* Sharing requires reference-counting.
*/
class U_COMMON_API SharedObject : public UObject {
public:
/** Initializes refCount to 0. */
SharedObject() : refCount(0) {}
/** Initializes refCount to 0. */
SharedObject(const SharedObject &/*other*/) : refCount(0) {}
virtual ~SharedObject();
/**
* Increments the number of references to this object. Thread-safe.
*/
void addRef() const;
/**
* Decrements the number of references to this object,
* and auto-deletes "this" if the number becomes 0. Thread-safe.
*/
void removeRef() const;
/**
* Returns the reference counter. Uses a memory barrier.
*/
int32_t getRefCount() const;
void deleteIfZeroRefCount() const;
/**
* Returns a writable version of ptr.
* If there is exactly one owner, then ptr itself is returned as a
* non-const pointer.
* If there are multiple owners, then ptr is replaced with a
* copy-constructed clone,
* and that is returned.
* Returns NULL if cloning failed.
*
* T must be a subclass of SharedObject.
*/
template<typename T>
static T *copyOnWrite(const T *&ptr) {
const T *p = ptr;
if(p->getRefCount() <= 1) { return const_cast<T *>(p); }
T *p2 = new T(*p);
if(p2 == NULL) { return NULL; }
p->removeRef();
ptr = p2;
p2->addRef();
return p2;
}
/**
* Makes dest an owner of the object pointed to by src while adjusting
* reference counts and deleting the previous object dest pointed to
* if necessary. Before this call is made, dest must either be NULL or
* own its object.
*
* T must be a subclass of SharedObject.
*/
template<typename T>
static void copyPtr(const T *src, const T *&dest) {
if(src != dest) {
if(dest != NULL) { dest->removeRef(); }
dest = src;
if(src != NULL) { src->addRef(); }
}
}
/**
* Equivalent to copy(NULL, dest).
*/
template<typename T>
static void clearPtr(const T *&ptr) {
if (ptr != NULL) {
ptr->removeRef();
ptr = NULL;
}
}
private:
mutable u_atomic_int32_t refCount;
};
U_NAMESPACE_END
#endif

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2013, International Business Machines Corporation and
* Copyright (C) 2014, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
@ -28,8 +28,8 @@ struct _AtomicInt : public UMemory {
* SharedPtr makes the act of copying large objects cheap by deferring the
* cost of the copy to the first write operation after the copy.
*
* A SharedPtr<T> instance can refer to no object or an object of type T where
* T is a subclass of UObject. T must also have a clone() method that copies
* A SharedPtr<T> instance can refer to no object or an object of type T.
* T must have a clone() method that copies
* the object and returns a pointer to the copy. Copy and assignment of
* SharedPtr instances are cheap because they only involve copying or
* assigning the SharedPtr instance, not the T object which could be large.
@ -44,6 +44,9 @@ struct _AtomicInt : public UMemory {
* management by reference counting their T objects. T objects that are
* referenced by no SharedPtr<T> instances get deleted automatically.
*/
// TODO (Travis Keep): Leave interface the same, but find a more efficient
// implementation that is easier to understand.
template<typename T>
class SharedPtr {
public:
@ -61,13 +64,13 @@ public:
delete ptr;
ptr = NULL;
} else {
umtx_storeRelease(refPtr->value, 1);
refPtr->value = 1;
}
}
}
/**
* Non-templated copy costructor. Needed to keep compiler from
* Non-templated copy constructor. Needed to keep compiler from
* creating its own.
*/
SharedPtr(const SharedPtr<T> &other) :
@ -82,7 +85,7 @@ public:
*/
template<typename U>
SharedPtr(const SharedPtr<U> &other) :
ptr((T *) other.ptr), refPtr(other.refPtr) {
ptr(other.ptr), refPtr(other.refPtr) {
if (refPtr != NULL) {
umtx_atomic_inc(&refPtr->value);
}
@ -118,9 +121,7 @@ public:
~SharedPtr() {
if (refPtr != NULL) {
if (umtx_atomic_dec(&refPtr->value) == 0) {
// Cast to UObject to avoid compiler warnings about incomplete
// type T.
delete (UObject *) ptr;
delete ptr;
delete refPtr;
}
}
@ -142,9 +143,9 @@ public:
}
/**
* clear makes this instance refer to no object.
* release makes this instance refer to no object.
*/
void clear() {
void release() {
adoptInstead(NULL);
}
@ -205,7 +206,7 @@ public:
*/
T *readWrite() {
int32_t refCount = count();
if (refCount == 0 || refCount == 1) {
if (refCount <= 1) {
return ptr;
}
T *result = (T *) ptr->clone();

View file

@ -1,11 +1,11 @@
/*
*******************************************************************************
* Copyright (C) 2013, International Business Machines Corporation and
******************************************************************************
* Copyright (C) 2014, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
******************************************************************************
*
* File RELDATEFMT.CPP
*******************************************************************************
******************************************************************************
*/
#include "unicode/reldatefmt.h"
@ -24,9 +24,13 @@
#include "plurrule_impl.h"
#include "ucln_in.h"
#include "mutex.h"
#include "charstr.h"
#include "sharedptr.h"
// Copied from uscript_props.cpp
#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
static icu::LRUCache *gCache = NULL;
static UMutex gCacheMutex = U_MUTEX_INITIALIZER;
static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER;
@ -46,105 +50,77 @@ U_NAMESPACE_BEGIN
// other must always be first.
static const char * const gPluralForms[] = {
"other", "zero", "one", "two", "few", "many", NULL};
"other", "zero", "one", "two", "few", "many"};
// Must be equal to number of plural forms just above.
#define MAX_PLURAL_FORMS 6
static const UChar gPlaceholder[] = { 0x7b, 0x30, 0x7d}; /* {0} */
class QualitativeUnits : public UObject {
class QualitativeUnits : public UMemory {
public:
QualitativeUnits() { }
UnicodeString data[UDAT_ABSOLUTE_UNIT_COUNT][UDAT_DIRECTION_COUNT];
virtual ~QualitativeUnits() {
}
private:
QualitativeUnits(const QualitativeUnits &other);
QualitativeUnits &operator=(const QualitativeUnits& other);
};
struct UnitPattern {
UnicodeString prefix;
UnicodeString suffix;
UBool prefixOnly;
UBool valid;
UnicodeString pattern;
int32_t offset; // Offset of "{0}". -1 means no {0}.
UBool valid; // True if initialize, false otherwise.
UnitPattern() : prefix(), suffix(), prefixOnly(FALSE), valid(FALSE) {
UnitPattern() : pattern(), offset(0), valid(FALSE) {
}
void set(const UnicodeString &patternStr) {
UnicodeString placeholder("{0}");
int32_t idx = patternStr.indexOf(placeholder);
pattern = patternStr;
offset = patternStr.indexOf(gPlaceholder, LENGTHOF(gPlaceholder), 0);
valid = TRUE;
if (idx == -1) {
prefixOnly = TRUE;
prefix = patternStr;
} else {
prefixOnly = FALSE;
prefix = patternStr.tempSubStringBetween(0, idx);
suffix = patternStr.tempSubStringBetween(idx + placeholder.length());
}
}
UnicodeString& append(double quantity, const NumberFormat &nf, UnicodeString &appendTo) const {
UnicodeString& append(
double quantity,
const NumberFormat &nf,
UnicodeString &appendTo) const {
if (!valid) {
return appendTo;
}
appendTo.append(prefix);
if (!prefixOnly) {
nf.format(quantity, appendTo);
appendTo.append(suffix);
if (offset == -1) {
appendTo.append(pattern);
return appendTo;
}
appendTo.append(pattern.tempSubStringBetween(0, offset));
nf.format(quantity, appendTo);
appendTo.append(pattern.tempSubStringBetween(
offset + LENGTHOF(gPlaceholder)));
return appendTo;
}
};
class QuantitativeUnits : public UObject {
class QuantitativeUnits : public UMemory {
public:
QuantitativeUnits() { }
UnitPattern data[UDAT_RELATIVE_UNIT_COUNT][2][MAX_PLURAL_FORMS];
virtual ~QuantitativeUnits() {
}
UnitPattern data[UDAT_RELATIVE_UNIT_COUNT][2][LENGTHOF(gPluralForms)];
private:
QuantitativeUnits(const QuantitativeUnits &other);
QuantitativeUnits &operator=(const QuantitativeUnits& other);
};
class RelativeDateTimeData : public UObject {
class RelativeDateTimeData : public SharedObject {
public:
RelativeDateTimeData() {
}
SharedPtr<QualitativeUnits> qualitativeUnits;
SharedPtr<QuantitativeUnits> quantitativeUnits;
SharedPtr<MessageFormat> combinedDateAndTime;
SharedPtr<PluralRules> pluralRules;
SharedPtr<NumberFormat> numberFormat;
RelativeDateTimeData *clone() const {
return new RelativeDateTimeData(*this);
}
virtual ~RelativeDateTimeData() {
}
virtual ~RelativeDateTimeData();
private:
RelativeDateTimeData(const RelativeDateTimeData &other);
RelativeDateTimeData &operator=(const RelativeDateTimeData& other);
};
RelativeDateTimeData::RelativeDateTimeData(
const RelativeDateTimeData &other) :
qualitativeUnits(other.qualitativeUnits),
quantitativeUnits(other.quantitativeUnits),
combinedDateAndTime(other.combinedDateAndTime),
pluralRules(other.pluralRules),
numberFormat(other.numberFormat) {
RelativeDateTimeData::~RelativeDateTimeData() {
}
static char *UnicodeString2Char(
const UnicodeString &source, char *buffer, int32_t bufCapacity) {
source.extract(0, source.length(), buffer, bufCapacity, US_INV);
return buffer;
}
static void getStringWithFallback(
static UBool getStringWithFallback(
const UResourceBundle *resource,
const char *key,
UnicodeString &result,
@ -153,18 +129,19 @@ static void getStringWithFallback(
const UChar *resStr = ures_getStringByKeyWithFallback(
resource, key, &len, &status);
if (U_FAILURE(status)) {
return;
return FALSE;
}
result.setTo(TRUE, resStr, len);
return TRUE;
}
static void getOptionalStringWithFallback(
static UBool getOptionalStringWithFallback(
const UResourceBundle *resource,
const char *key,
UnicodeString &result,
UErrorCode &status) {
if (U_FAILURE(status)) {
return;
return FALSE;
}
int32_t len = 0;
const UChar *resStr = ures_getStringByKey(
@ -172,42 +149,44 @@ static void getOptionalStringWithFallback(
if (status == U_MISSING_RESOURCE_ERROR) {
result.remove();
status = U_ZERO_ERROR;
return;
return TRUE;
}
if (U_FAILURE(status)) {
return;
return FALSE;
}
result.setTo(TRUE, resStr, len);
return TRUE;
}
static void getString(
static UBool getString(
const UResourceBundle *resource,
UnicodeString &result,
UErrorCode &status) {
int32_t len = 0;
const UChar *resStr = ures_getString(resource, &len, &status);
if (U_FAILURE(status)) {
return;
return FALSE;
}
result.setTo(TRUE, resStr, len);
return TRUE;
}
static void getUnitPattern(
static UBool getUnitPattern(
const UResourceBundle *resource,
UnitPattern &result,
UErrorCode &status) {
if (U_FAILURE(status)) {
return;
return FALSE;
}
UnicodeString rawPattern;
getString(resource, rawPattern, status);
if (U_FAILURE(status)) {
return;
if (!getString(resource, rawPattern, status)) {
return FALSE;
}
result.set(rawPattern);
return TRUE;
}
static void getStringByIndex(
static UBool getStringByIndex(
const UResourceBundle *resource,
int32_t idx,
UnicodeString &result,
@ -216,9 +195,10 @@ static void getStringByIndex(
const UChar *resStr = ures_getStringByIndex(
resource, idx, &len, &status);
if (U_FAILURE(status)) {
return;
return FALSE;
}
result.setTo(TRUE, resStr, len);
return TRUE;
}
static void addQualitativeUnit(
@ -256,7 +236,8 @@ static void addQualitativeUnit(
}
static int32_t getPluralIndex(const char *pluralForm) {
for (int32_t i = 0; gPluralForms[i] != NULL; ++i) {
int32_t len = LENGTHOF(gPluralForms);
for (int32_t i = 0; i < len; ++i) {
if (uprv_strcmp(pluralForm, gPluralForms[i]) == 0) {
return i;
}
@ -283,11 +264,10 @@ static void addTimeUnit(
int32_t pluralIndex = getPluralIndex(
ures_getKey(pluralBundle.getAlias()));
if (pluralIndex != -1) {
getUnitPattern(
if (!getUnitPattern(
pluralBundle.getAlias(),
quantitativeUnits.data[relativeUnit][pastOrFuture][pluralIndex],
status);
if (U_FAILURE(status)) {
status)) {
return;
}
}
@ -300,7 +280,8 @@ static void addTimeUnit(
QuantitativeUnits &quantitativeUnits,
UErrorCode &status) {
LocalUResourceBundlePointer topLevel(
ures_getByKeyWithFallback(resource, "relativeTime", NULL, &status));
ures_getByKeyWithFallback(
resource, "relativeTime", NULL, &status));
if (U_FAILURE(status)) {
return;
}
@ -357,8 +338,7 @@ static void addTimeUnit(
}
addTimeUnit(topLevel.getAlias(), relativeUnit, quantitativeUnits, status);
UnicodeString unitName;
getStringWithFallback(topLevel.getAlias(), "dn", unitName, status);
if (U_FAILURE(status)) {
if (!getStringWithFallback(topLevel.getAlias(), "dn", unitName, status)) {
return;
}
// TODO(Travis Keep): This is a hack to get around CLDR bug 6818.
@ -401,8 +381,7 @@ static void readDaysOfWeek(
return;
}
for (int32_t i = 0; i < size; ++i) {
getStringByIndex(topLevel.getAlias(), i, daysOfWeek[i], status);
if (U_FAILURE(status)) {
if (!getStringByIndex(topLevel.getAlias(), i, daysOfWeek[i], status)) {
return;
}
}
@ -428,7 +407,7 @@ static void addWeekDay(
status);
}
static void load(
static UBool load(
const UResourceBundle *resource,
QualitativeUnits &qualitativeUnits,
QuantitativeUnits &quantitativeUnits,
@ -543,46 +522,43 @@ static void load(
UDAT_ABSOLUTE_SUNDAY,
qualitativeUnits,
status);
return U_SUCCESS(status);
}
static void getDateTimePattern(
static UBool getDateTimePattern(
const UResourceBundle *resource,
UnicodeString &result,
UErrorCode &status) {
UnicodeString defaultCalendarName;
getStringWithFallback(
if (!getStringWithFallback(
resource,
"calendar/default",
defaultCalendarName,
status);
if (U_FAILURE(status)) {
return;
status)) {
return FALSE;
}
char calendarNameBuffer[128];
char pathBuffer[256];
sprintf(
pathBuffer,
"calendar/%s/DateTimePatterns",
UnicodeString2Char(
defaultCalendarName,
calendarNameBuffer,
128));
CharString pathBuffer;
pathBuffer.append("calendar/", status)
.appendInvariantChars(defaultCalendarName, status)
.append("/DateTimePatterns", status);
LocalUResourceBundlePointer topLevel(
ures_getByKeyWithFallback(resource, pathBuffer, NULL, &status));
ures_getByKeyWithFallback(
resource, pathBuffer.data(), NULL, &status));
if (U_FAILURE(status)) {
return;
return FALSE;
}
int32_t size = ures_getSize(topLevel.getAlias());
if (size < 9) {
if (size <= 8) {
// Oops, size is to small to access the index that we want, fallback
// to a hard-coded value.
result = UNICODE_STRING_SIMPLE("{1} {0}");
return;
return TRUE;
}
getStringByIndex(topLevel.getAlias(), 8, result, status);
return getStringByIndex(topLevel.getAlias(), 8, result, status);
}
static UObject *U_CALLCONV createData(const char *localeId, UErrorCode &status) {
static SharedObject *U_CALLCONV createData(
const char *localeId, UErrorCode &status) {
LocalUResourceBundlePointer topLevel(ures_open(NULL, localeId, &status));
if (U_FAILURE(status)) {
return NULL;
@ -590,12 +566,17 @@ static UObject *U_CALLCONV createData(const char *localeId, UErrorCode &status)
LocalPointer<RelativeDateTimeData> result(new RelativeDateTimeData());
LocalPointer<QualitativeUnits> qualitativeUnits(new QualitativeUnits());
LocalPointer<QuantitativeUnits> quantitativeUnits(new QuantitativeUnits());
if (qualitativeUnits.getAlias() == NULL || quantitativeUnits.getAlias() == NULL) {
if (result.getAlias() == NULL
|| qualitativeUnits.getAlias() == NULL
|| quantitativeUnits.getAlias() == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
load(topLevel.getAlias(), *qualitativeUnits, *quantitativeUnits, status);
if (U_FAILURE(status)) {
if (!load(
topLevel.getAlias(),
*qualitativeUnits,
*quantitativeUnits,
status)) {
return NULL;
}
if (!result->qualitativeUnits.adoptInstead(qualitativeUnits.orphan())) {
@ -609,12 +590,16 @@ static UObject *U_CALLCONV createData(const char *localeId, UErrorCode &status)
UnicodeString dateTimePattern;
getDateTimePattern(topLevel.getAlias(), dateTimePattern, status);
if (!getDateTimePattern(topLevel.getAlias(), dateTimePattern, status)) {
return NULL;
}
LocalPointer<MessageFormat> mf(
new MessageFormat(dateTimePattern, localeId, status));
if (U_FAILURE(status)) {
return NULL;
}
LocalPointer<MessageFormat> mf(new MessageFormat(dateTimePattern, localeId, status));
if (U_FAILURE(status)) {
if (mf.getAlias() == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
if (!result->combinedDateAndTime.adoptInstead(mf.orphan())) {
@ -651,7 +636,10 @@ static void U_CALLCONV cacheInit(UErrorCode &status) {
}
}
static void getFromCache(const char *locale, SharedPtr<RelativeDateTimeData>& ptr, UErrorCode &status) {
static void getFromCache(
const char *locale,
const RelativeDateTimeData *&ptr,
UErrorCode &status) {
umtx_initOnce(gCacheInitOnce, &cacheInit, status);
if (U_FAILURE(status)) {
return;
@ -660,21 +648,24 @@ static void getFromCache(const char *locale, SharedPtr<RelativeDateTimeData>& pt
gCache->get(locale, ptr, status);
}
RelativeDateTimeFormatter::RelativeDateTimeFormatter(UErrorCode& status) {
RelativeDateTimeFormatter::RelativeDateTimeFormatter(UErrorCode& status)
: ptr(NULL) {
getFromCache(Locale::getDefault().getName(), ptr, status);
}
RelativeDateTimeFormatter::RelativeDateTimeFormatter(const Locale& locale, UErrorCode& status) {
RelativeDateTimeFormatter::RelativeDateTimeFormatter(
const Locale& locale, UErrorCode& status) : ptr(NULL) {
getFromCache(locale.getName(), ptr, status);
}
RelativeDateTimeFormatter::RelativeDateTimeFormatter(
const Locale& locale, NumberFormat *nfToAdopt, UErrorCode& status) {
const Locale& locale, NumberFormat *nfToAdopt, UErrorCode& status)
: ptr(NULL) {
getFromCache(locale.getName(), ptr, status);
if (U_FAILURE(status)) {
return;
}
RelativeDateTimeData* wptr = ptr.readWrite();
RelativeDateTimeData* wptr = SharedObject::copyOnWrite(ptr);
if (wptr == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
@ -685,23 +676,26 @@ RelativeDateTimeFormatter::RelativeDateTimeFormatter(
}
}
const NumberFormat& RelativeDateTimeFormatter::getNumberFormat() const {
return *ptr->numberFormat;
RelativeDateTimeFormatter::RelativeDateTimeFormatter(
const RelativeDateTimeFormatter& other) : ptr(other.ptr) {
ptr->addRef();
}
RelativeDateTimeFormatter::RelativeDateTimeFormatter(const RelativeDateTimeFormatter& other) : ptr(other.ptr) {
}
RelativeDateTimeFormatter& RelativeDateTimeFormatter::operator=(const RelativeDateTimeFormatter& other) {
RelativeDateTimeFormatter& RelativeDateTimeFormatter::operator=(
const RelativeDateTimeFormatter& other) {
if (this != &other) {
ptr = other.ptr;
SharedObject::copyPtr(other.ptr, ptr);
}
return *this;
}
RelativeDateTimeFormatter::~RelativeDateTimeFormatter() {
ptr->removeRef();
}
const NumberFormat& RelativeDateTimeFormatter::getNumberFormat() const {
return *ptr->numberFormat;
}
UnicodeString& RelativeDateTimeFormatter::format(
double quantity, UDateDirection direction, UDateRelativeUnit unit,
@ -719,12 +713,13 @@ UnicodeString& RelativeDateTimeFormatter::format(
if (decFmt != NULL) {
dec = decFmt->getFixedDecimal(quantity, status);
}
CharString buffer;
buffer.appendInvariantChars(ptr->pluralRules->select(dec), status);
if (U_FAILURE(status)) {
return appendTo;
}
char buffer[256];
int32_t pluralIndex = getPluralIndex(
UnicodeString2Char(ptr->pluralRules->select(dec), buffer, 256));
int32_t pluralIndex = getPluralIndex(buffer.data());
if (pluralIndex == -1) {
pluralIndex = 0;
}
@ -752,11 +747,9 @@ UnicodeString& RelativeDateTimeFormatter::format(
UnicodeString& RelativeDateTimeFormatter::combineDateAndTime(
const UnicodeString& relativeDateString, const UnicodeString& timeString,
UnicodeString& appendTo, UErrorCode& status) const {
Formattable formattable[2];
formattable[0].setString(timeString);
formattable[1].setString(relativeDateString);
Formattable args[2] = {timeString, relativeDateString};
FieldPosition fpos(0);
return ptr->combinedDateAndTime->format(formattable, 2, appendTo, fpos, status);
return ptr->combinedDateAndTime->format(args, 2, appendTo, fpos, status);
}
U_NAMESPACE_END

View file

@ -1,12 +1,12 @@
/*
********************************************************************************
* Copyright (C) 2013, International Business Machines Corporation and
*****************************************************************************
* Copyright (C) 2014, International Business Machines Corporation and
* others.
* All Rights Reserved.
********************************************************************************
*****************************************************************************
*
* File RELDATEFMT.H
********************************************************************************
*****************************************************************************
*/
#ifndef __RELDATEFMT_H
@ -14,10 +14,14 @@
#include "unicode/utypes.h"
/**
* \file
* \brief C++ API: Formats relative dates such as "1 day ago" or "tomorrow"
*/
#if !UCONFIG_NO_FORMATTING
#include "unicode/locid.h"
#include "sharedptr.h"
/**
@ -234,7 +238,7 @@ class NumberFormat;
* caller's responsibility to handle cut-off logic such as deciding between
* displaying "in 7 days" or "in 1 week." This API supports relative dates
* involving one single unit. This API does not support relative dates
* involving compound units.
* involving compound units,
* e.g "in 5 days and 4 hours" nor does it support parsing.
* <p>
* This class is mostly thread safe and immutable with the following caveats:
@ -327,7 +331,8 @@ public:
* Assignment operator.
* @draft ICU 53
*/
RelativeDateTimeFormatter& operator=(const RelativeDateTimeFormatter& other);
RelativeDateTimeFormatter& operator=(
const RelativeDateTimeFormatter& other);
/**
* Destructor.
@ -350,7 +355,12 @@ public:
* @return appendTo
* @draft ICU 53
*/
UnicodeString& format(double quantity, UDateDirection direction, UDateRelativeUnit unit, UnicodeString& appendTo, UErrorCode& status) const;
UnicodeString& format(
double quantity,
UDateDirection direction,
UDateRelativeUnit unit,
UnicodeString& appendTo,
UErrorCode& status) const;
/**
* Formats a relative date without a quantity.
@ -364,7 +374,11 @@ public:
* @return appendTo
* @draft ICU 53
*/
UnicodeString& format(UDateDirection direction, UDateAbsoluteUnit unit, UnicodeString& appendTo, UErrorCode& status) const;
UnicodeString& format(
UDateDirection direction,
UDateAbsoluteUnit unit,
UnicodeString& appendTo,
UErrorCode& status) const;
/**
* Combines a relative date string and a time string in this object's
@ -379,8 +393,10 @@ public:
* @draft ICU 53
*/
UnicodeString& combineDateAndTime(
const UnicodeString& relativeDateString, const UnicodeString& timeString,
UnicodeString& appendTo, UErrorCode& status) const;
const UnicodeString& relativeDateString,
const UnicodeString& timeString,
UnicodeString& appendTo,
UErrorCode& status) const;
/**
* Returns the NumberFormat this object is using.
@ -391,7 +407,7 @@ public:
private:
RelativeDateTimeFormatter();
SharedPtr<icu::RelativeDateTimeData> ptr;
const RelativeDateTimeData* ptr;
};
U_NAMESPACE_END

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2013, International Business Machines Corporation and *
* Copyright (C) 2014, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -11,25 +11,27 @@
#include "cstring.h"
#include "intltest.h"
#include "lrucache.h"
#include "sharedptr.h"
class CopyOnWriteForTesting : public UObject {
class CopyOnWriteForTesting : public SharedObject {
public:
CopyOnWriteForTesting() : localeNamePtr(), formatStrPtr(), length(0) {
CopyOnWriteForTesting() : SharedObject(), localeNamePtr(), formatStrPtr(), length(0) {
}
UObject *clone() const {
return new CopyOnWriteForTesting(*this);
}
virtual ~CopyOnWriteForTesting() {
}
SharedPtr<UnicodeString> localeNamePtr;
SharedPtr<UnicodeString> formatStrPtr;
int32_t length;
private:
CopyOnWriteForTesting(const CopyOnWriteForTesting &other) :
SharedObject(other),
localeNamePtr(other.localeNamePtr),
formatStrPtr(other.formatStrPtr),
length(other.length) {
}
virtual ~CopyOnWriteForTesting() {
}
SharedPtr<UnicodeString> localeNamePtr;
SharedPtr<UnicodeString> formatStrPtr;
int32_t length;
private:
CopyOnWriteForTesting &operator=(const CopyOnWriteForTesting &rhs);
};
@ -41,7 +43,7 @@ public:
virtual ~LRUCacheForTesting() {
}
protected:
virtual UObject *create(const char *localeId, UErrorCode &status);
virtual SharedObject *create(const char *localeId, UErrorCode &status);
private:
SharedPtr<UnicodeString> defaultFormatStr;
};
@ -56,7 +58,7 @@ LRUCacheForTesting::LRUCacheForTesting(
defaultFormatStr.adoptInstead(new UnicodeString(dfs));
}
UObject *LRUCacheForTesting::create(const char *localeId, UErrorCode &status) {
SharedObject *LRUCacheForTesting::create(const char *localeId, UErrorCode &status) {
if (uprv_strcmp(localeId, "error") == 0) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return NULL;
@ -79,14 +81,13 @@ private:
void TestLRUCache();
void TestLRUCacheError();
void verifySharedPointer(
const SharedPtr<CopyOnWriteForTesting>& ptr,
const CopyOnWriteForTesting* ptr,
const UnicodeString& name,
const UnicodeString& format);
void verifyString(
const UnicodeString &expected, const UnicodeString &actual);
void verifyPtr(const void *expected, const void *actual);
void verifyReferences(
const SharedPtr<CopyOnWriteForTesting>& ptr,
const CopyOnWriteForTesting* ptr,
int32_t count, int32_t nameCount, int32_t formatCount);
};
@ -102,27 +103,28 @@ void LRUCacheTest::runIndexedTest(int32_t index, UBool exec, const char* &name,
void LRUCacheTest::TestSharedPointer() {
UErrorCode status = U_ZERO_ERROR;
LRUCacheForTesting cache(3, "little", status);
SharedPtr<CopyOnWriteForTesting> ptr;
const CopyOnWriteForTesting* ptr = NULL;
cache.get("boo", ptr, status);
verifySharedPointer(ptr, "boo", "little");
SharedPtr<CopyOnWriteForTesting> ptrCopy = ptr;
verifyPtr(ptr.readOnly(), ptrCopy.readOnly());
const CopyOnWriteForTesting* ptrCopy = ptr;
ptrCopy->addRef();
{
SharedPtr<CopyOnWriteForTesting> ptrCopy2(ptrCopy);
const CopyOnWriteForTesting* ptrCopy2(ptrCopy);
ptrCopy2->addRef();
verifyReferences(ptr, 4, 1, 2);
ptrCopy2->removeRef();
}
// Test identity assignment
ptr = ptr;
verifyReferences(ptr, 3, 1, 2);
verifyReferences(ptrCopy, 3, 1, 2);
*ptrCopy.readWrite()->localeNamePtr.readWrite() = UnicodeString("hi there");
*ptrCopy.readWrite()->formatStrPtr.readWrite() = UnicodeString("see you");
CopyOnWriteForTesting *wPtrCopy = SharedObject::copyOnWrite(ptrCopy);
*wPtrCopy->localeNamePtr.readWrite() = UnicodeString("hi there");
*wPtrCopy->formatStrPtr.readWrite() = UnicodeString("see you");
verifyReferences(ptr, 2, 1, 2);
verifyReferences(ptrCopy, 1, 1, 1);
verifySharedPointer(ptr, "boo", "little");
verifySharedPointer(ptrCopy, "hi there", "see you");
ptrCopy->removeRef();
ptr->removeRef();
}
void LRUCacheTest::TestErrorCallingConstructor() {
@ -133,11 +135,11 @@ void LRUCacheTest::TestErrorCallingConstructor() {
void LRUCacheTest::TestLRUCache() {
UErrorCode status = U_ZERO_ERROR;
LRUCacheForTesting cache(3, "little", status);
SharedPtr<CopyOnWriteForTesting> ptr1;
SharedPtr<CopyOnWriteForTesting> ptr2;
SharedPtr<CopyOnWriteForTesting> ptr3;
SharedPtr<CopyOnWriteForTesting> ptr4;
SharedPtr<CopyOnWriteForTesting> ptr5;
const CopyOnWriteForTesting* ptr1 = NULL;
const CopyOnWriteForTesting* ptr2 = NULL;
const CopyOnWriteForTesting* ptr3 = NULL;
const CopyOnWriteForTesting* ptr4 = NULL;
const CopyOnWriteForTesting* ptr5 = NULL;
cache.get("foo", ptr1, status);
cache.get("bar", ptr2, status);
cache.get("baz", ptr3, status);
@ -166,7 +168,8 @@ void LRUCacheTest::TestLRUCache() {
verifyReferences(ptr5, 3, 1, 5);
// This should delete foo data since it got evicted from cache.
ptr1.clear();
ptr1->removeRef();
ptr1 = NULL;
// Reference count for little drops to 4 because foo data was deleted.
verifyReferences(ptr5, 3, 1, 4);
@ -186,7 +189,8 @@ void LRUCacheTest::TestLRUCache() {
// Since bar was evicted, clearing its pointer should delete its data.
// Notice that the reference count to 'little' dropped from 5 to 4.
ptr2.clear();
ptr2->removeRef();
ptr2 = NULL;
verifyReferences(ptr5, 2, 1, 4);
if (cache.contains("bar") || !cache.contains("full")) {
errln("Unexpected 'bar' in cache.");
@ -199,7 +203,8 @@ void LRUCacheTest::TestLRUCache() {
verifyReferences(ptr5, 2, 1, 5);
// since "full" was evicted, clearing its pointer should delete its data.
ptr4.clear();
ptr4->removeRef();
ptr4 = NULL;
verifyReferences(ptr5, 2, 1, 4);
if (cache.contains("full") || !cache.contains("baz")) {
errln("Unexpected 'full' in cache.");
@ -212,17 +217,23 @@ void LRUCacheTest::TestLRUCache() {
verifyReferences(ptr5, 2, 1, 5);
// since "baz" was evicted, clearing its pointer should delete its data.
ptr3.clear();
ptr3->removeRef();
ptr3 = NULL;
verifyReferences(ptr5, 2, 1, 4);
if (cache.contains("baz") || !cache.contains("new3")) {
errln("Unexpected 'baz' in cache.");
}
SharedObject::clearPtr(ptr1);
SharedObject::clearPtr(ptr2);
SharedObject::clearPtr(ptr3);
SharedObject::clearPtr(ptr4);
SharedObject::clearPtr(ptr5);
}
void LRUCacheTest::TestLRUCacheError() {
UErrorCode status = U_ZERO_ERROR;
LRUCacheForTesting cache(3, "little", status);
SharedPtr<CopyOnWriteForTesting> ptr1;
const CopyOnWriteForTesting *ptr1;
cache.get("error", ptr1, status);
if (status != U_ILLEGAL_ARGUMENT_ERROR) {
errln("Expected an error.");
@ -230,7 +241,7 @@ void LRUCacheTest::TestLRUCacheError() {
}
void LRUCacheTest::verifySharedPointer(
const SharedPtr<CopyOnWriteForTesting>& ptr,
const CopyOnWriteForTesting* ptr,
const UnicodeString& name,
const UnicodeString& format) {
const UnicodeString *strPtr = ptr->localeNamePtr.readOnly();
@ -245,14 +256,8 @@ void LRUCacheTest::verifyString(const UnicodeString &expected, const UnicodeStri
}
}
void LRUCacheTest::verifyPtr(const void *expected, const void *actual) {
if (expected != actual) {
errln("Pointer mismatch.");
}
}
void LRUCacheTest::verifyReferences(const SharedPtr<CopyOnWriteForTesting>& ptr, int32_t count, int32_t nameCount, int32_t formatCount) {
int32_t actual = ptr.count();
void LRUCacheTest::verifyReferences(const CopyOnWriteForTesting* ptr, int32_t count, int32_t nameCount, int32_t formatCount) {
int32_t actual = ptr->getRefCount();
if (count != actual) {
errln("Main reference count wrong: Expected %d, got %d", count, actual);
}