- /**
- *******************************************************************************
- * Copyright (C) 2001-2004, International Business Machines Corporation. *
- * All Rights Reserved. *
- *******************************************************************************
- */
+/**
+*******************************************************************************
+* Copyright (C) 2001-2012, International Business Machines Corporation.
+* All Rights Reserved.
+*******************************************************************************
+*/
#include "unicode/utypes.h"
U_NAMESPACE_BEGIN
/*
- ******************************************************************
- */
+******************************************************************
+*/
const UChar ICUServiceKey::PREFIX_DELIMITER = 0x002F; /* '/' */
ICUServiceKey::ICUServiceKey(const UnicodeString& id)
- : _id(id) {
+: _id(id) {
}
ICUServiceKey::~ICUServiceKey()
const UnicodeString&
ICUServiceKey::getID() const
{
- return _id;
+ return _id;
}
UnicodeString&
ICUServiceKey::canonicalID(UnicodeString& result) const
{
- return result.append(_id);
+ return result.append(_id);
}
UnicodeString&
ICUServiceKey::currentID(UnicodeString& result) const
{
- return canonicalID(result);
+ return canonicalID(result);
}
UnicodeString&
ICUServiceKey::currentDescriptor(UnicodeString& result) const
{
- prefix(result);
- result.append(PREFIX_DELIMITER);
- return currentID(result);
+ prefix(result);
+ result.append(PREFIX_DELIMITER);
+ return currentID(result);
}
UBool
ICUServiceKey::fallback()
{
- return FALSE;
+ return FALSE;
}
UBool
ICUServiceKey::isFallbackOf(const UnicodeString& id) const
{
- return id == _id;
+ return id == _id;
}
UnicodeString&
ICUServiceKey::prefix(UnicodeString& result) const
{
- return result;
+ return result;
}
UnicodeString&
ICUServiceKey::parsePrefix(UnicodeString& result)
{
- int32_t n = result.indexOf(PREFIX_DELIMITER);
- if (n < 0) {
- n = 0;
- }
- result.remove(n);
- return result;
+ int32_t n = result.indexOf(PREFIX_DELIMITER);
+ if (n < 0) {
+ n = 0;
+ }
+ result.remove(n);
+ return result;
}
UnicodeString&
ICUServiceKey::parseSuffix(UnicodeString& result)
{
- int32_t n = result.indexOf(PREFIX_DELIMITER);
- if (n >= 0) {
- result.remove(0, n+1);
- }
- return result;
+ int32_t n = result.indexOf(PREFIX_DELIMITER);
+ if (n >= 0) {
+ result.remove(0, n+1);
+ }
+ return result;
}
#ifdef SERVICE_DEBUG
UnicodeString&
ICUServiceKey::debug(UnicodeString& result) const
{
- debugClass(result);
- result.append(" id: ");
- result.append(_id);
- return result;
+ debugClass(result);
+ result.append(" id: ");
+ result.append(_id);
+ return result;
}
UnicodeString&
ICUServiceKey::debugClass(UnicodeString& result) const
{
- return result.append("ICUServiceKey");
+ return result.append("ICUServiceKey");
}
#endif
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ICUServiceKey)
/*
- ******************************************************************
- */
+******************************************************************
+*/
+
+ICUServiceFactory::~ICUServiceFactory() {}
SimpleFactory::SimpleFactory(UObject* instanceToAdopt, const UnicodeString& id, UBool visible)
- : _instance(instanceToAdopt), _id(id), _visible(visible)
+: _instance(instanceToAdopt), _id(id), _visible(visible)
{
}
SimpleFactory::~SimpleFactory()
{
- delete _instance;
+ delete _instance;
}
UObject*
SimpleFactory::create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const
{
- if (U_SUCCESS(status)) {
- UnicodeString temp;
- if (_id == key.currentID(temp)) {
- return service->cloneInstance(_instance);
+ if (U_SUCCESS(status)) {
+ UnicodeString temp;
+ if (_id == key.currentID(temp)) {
+ return service->cloneInstance(_instance);
+ }
}
- }
- return NULL;
+ return NULL;
}
void
SimpleFactory::updateVisibleIDs(Hashtable& result, UErrorCode& status) const
{
- if (_visible) {
- result.put(_id, (void*)this, status); // cast away const
- } else {
- result.remove(_id);
- }
+ if (_visible) {
+ result.put(_id, (void*)this, status); // cast away const
+ } else {
+ result.remove(_id);
+ }
}
UnicodeString&
SimpleFactory::getDisplayName(const UnicodeString& id, const Locale& /* locale */, UnicodeString& result) const
{
- if (_visible && _id == id) {
- result = _id;
- } else {
- result.setToBogus();
- }
- return result;
+ if (_visible && _id == id) {
+ result = _id;
+ } else {
+ result.setToBogus();
+ }
+ return result;
}
#ifdef SERVICE_DEBUG
UnicodeString&
SimpleFactory::debug(UnicodeString& toAppendTo) const
{
- debugClass(toAppendTo);
- toAppendTo.append(" id: ");
- toAppendTo.append(_id);
- toAppendTo.append(", visible: ");
- toAppendTo.append(_visible ? "T" : "F");
- return toAppendTo;
+ debugClass(toAppendTo);
+ toAppendTo.append(" id: ");
+ toAppendTo.append(_id);
+ toAppendTo.append(", visible: ");
+ toAppendTo.append(_visible ? "T" : "F");
+ return toAppendTo;
}
UnicodeString&
SimpleFactory::debugClass(UnicodeString& toAppendTo) const
{
- return toAppendTo.append("SimpleFactory");
+ return toAppendTo.append("SimpleFactory");
}
#endif
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleFactory)
/*
- ******************************************************************
- */
+******************************************************************
+*/
+
+ServiceListener::~ServiceListener() {}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceListener)
/*
- ******************************************************************
- */
+******************************************************************
+*/
- // Record the actual id for this service in the cache, so we can return it
- // even if we succeed later with a different id.
+// Record the actual id for this service in the cache, so we can return it
+// even if we succeed later with a different id.
class CacheEntry : public UMemory {
private:
- int32_t refcount;
+ int32_t refcount;
public:
- UnicodeString actualDescriptor;
- UObject* service;
-
- /**
- * Releases a reference to the shared resource.
- */
- ~CacheEntry() {
- delete service;
- }
-
- CacheEntry(const UnicodeString& _actualDescriptor, UObject* _service)
- : refcount(1), actualDescriptor(_actualDescriptor), service(_service) {
- }
-
- /**
- * Instantiation creates an initial reference, so don't call this
- * unless you're creating a new pointer to this. Management of
- * that pointer will have to know how to deal with refcounts.
- * Return true if the resource has not already been released.
- */
- CacheEntry* ref() {
- ++refcount;
- return this;
- }
-
- /**
- * Destructions removes a reference, so don't call this unless
- * you're removing pointer to this somewhere. Management of that
- * pointer will have to know how to deal with refcounts. Once
- * the refcount drops to zero, the resource is released. Return
- * false if the resouce has been released.
- */
- CacheEntry* unref() {
- if ((--refcount) == 0) {
- delete this;
- return NULL;
- }
- return this;
- }
-
- /**
- * Return TRUE if there is at least one reference to this and the
- * resource has not been released.
- */
- UBool isShared() const {
- return refcount > 1;
- }
+ UnicodeString actualDescriptor;
+ UObject* service;
+
+ /**
+ * Releases a reference to the shared resource.
+ */
+ ~CacheEntry() {
+ delete service;
+ }
+
+ CacheEntry(const UnicodeString& _actualDescriptor, UObject* _service)
+ : refcount(1), actualDescriptor(_actualDescriptor), service(_service) {
+ }
+
+ /**
+ * Instantiation creates an initial reference, so don't call this
+ * unless you're creating a new pointer to this. Management of
+ * that pointer will have to know how to deal with refcounts.
+ * Return true if the resource has not already been released.
+ */
+ CacheEntry* ref() {
+ ++refcount;
+ return this;
+ }
+
+ /**
+ * Destructions removes a reference, so don't call this unless
+ * you're removing pointer to this somewhere. Management of that
+ * pointer will have to know how to deal with refcounts. Once
+ * the refcount drops to zero, the resource is released. Return
+ * false if the resouce has been released.
+ */
+ CacheEntry* unref() {
+ if ((--refcount) == 0) {
+ delete this;
+ return NULL;
+ }
+ return this;
+ }
+
+ /**
+ * Return TRUE if there is at least one reference to this and the
+ * resource has not been released.
+ */
+ UBool isShared() const {
+ return refcount > 1;
+ }
};
// UObjectDeleter for serviceCache
U_CDECL_BEGIN
static void U_CALLCONV
cacheDeleter(void* obj) {
- U_NAMESPACE_USE
- ((CacheEntry*)obj)->unref();
+ U_NAMESPACE_USE ((CacheEntry*)obj)->unref();
}
/**
- * Deleter for UObjects
- */
+* Deleter for UObjects
+*/
static void U_CALLCONV
deleteUObject(void *obj) {
- U_NAMESPACE_USE
- delete (UObject*) obj;
+ U_NAMESPACE_USE delete (UObject*) obj;
}
U_CDECL_END
/*
- ******************************************************************
- */
+******************************************************************
+*/
class DNCache : public UMemory {
public:
- Hashtable cache;
- const Locale locale;
-
- DNCache(const Locale& _locale)
- : cache(), locale(_locale)
- {
- // cache.setKeyDeleter(uhash_deleteUnicodeString);
- }
+ Hashtable cache;
+ const Locale locale;
+
+ DNCache(const Locale& _locale)
+ : cache(), locale(_locale)
+ {
+ // cache.setKeyDeleter(uprv_deleteUObject);
+ }
};
/*
- ******************************************************************
- */
+******************************************************************
+*/
StringPair*
StringPair::create(const UnicodeString& displayName,
const UnicodeString& id,
UErrorCode& status)
{
- if (U_SUCCESS(status)) {
- StringPair* sp = new StringPair(displayName, id);
- if (sp == NULL || sp->isBogus()) {
- status = U_MEMORY_ALLOCATION_ERROR;
- delete sp;
- return NULL;
+ if (U_SUCCESS(status)) {
+ StringPair* sp = new StringPair(displayName, id);
+ if (sp == NULL || sp->isBogus()) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ delete sp;
+ return NULL;
+ }
+ return sp;
}
- return sp;
- }
- return NULL;
+ return NULL;
}
UBool
StringPair::isBogus() const {
- return displayName.isBogus() || id.isBogus();
+ return displayName.isBogus() || id.isBogus();
}
StringPair::StringPair(const UnicodeString& _displayName,
const UnicodeString& _id)
- : displayName(_displayName)
- , id(_id)
+: displayName(_displayName)
+, id(_id)
{
}
-U_CAPI void U_EXPORT2
+U_CDECL_BEGIN
+static void U_CALLCONV
userv_deleteStringPair(void *obj) {
- U_NAMESPACE_USE
- delete (StringPair*) obj;
+ U_NAMESPACE_USE delete (StringPair*) obj;
}
+U_CDECL_END
/*
- ******************************************************************
- */
+******************************************************************
+*/
+
+static UMutex lock = U_MUTEX_INITIALIZER;
ICUService::ICUService()
- : name()
- , lock(0)
- , timestamp(0)
- , factories(NULL)
- , serviceCache(NULL)
- , idCache(NULL)
- , dnCache(NULL)
+: name()
+, timestamp(0)
+, factories(NULL)
+, serviceCache(NULL)
+, idCache(NULL)
+, dnCache(NULL)
{
- umtx_init(&lock);
}
ICUService::ICUService(const UnicodeString& newName)
- : name(newName)
- , lock(0)
- , timestamp(0)
- , factories(NULL)
- , serviceCache(NULL)
- , idCache(NULL)
- , dnCache(NULL) {
- umtx_init(&lock);
+: name(newName)
+, timestamp(0)
+, factories(NULL)
+, serviceCache(NULL)
+, idCache(NULL)
+, dnCache(NULL)
+{
}
ICUService::~ICUService()
- {
- {
- Mutex mutex(&lock);
- clearCaches();
- delete factories;
- factories = NULL;
- }
- umtx_destroy(&lock);
+{
+ {
+ Mutex mutex(&lock);
+ clearCaches();
+ delete factories;
+ factories = NULL;
+ }
}
UObject*
ICUService::get(const UnicodeString& descriptor, UErrorCode& status) const
{
- return get(descriptor, NULL, status);
+ return get(descriptor, NULL, status);
}
UObject*
ICUService::get(const UnicodeString& descriptor, UnicodeString* actualReturn, UErrorCode& status) const
{
- UObject* result = NULL;
+ UObject* result = NULL;
ICUServiceKey* key = createKey(&descriptor, status);
if (key) {
- result = getKey(*key, actualReturn, status);
- delete key;
+ result = getKey(*key, actualReturn, status);
+ delete key;
}
- return result;
+ return result;
}
UObject*
ICUService::getKey(ICUServiceKey& key, UErrorCode& status) const
{
- return getKey(key, NULL, status);
+ return getKey(key, NULL, status);
}
// this is a vector that subclasses of ICUService can override to further customize the result object
UObject*
ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const
{
- return getKey(key, actualReturn, NULL, status);
+ return getKey(key, actualReturn, NULL, status);
}
// make it possible to call reentrantly on systems that don't have reentrant mutexes.
// reentrantly even without knowing the thread.
class XMutex : public UMemory {
public:
- inline XMutex(UMTX *mutex, UBool reentering)
- : fMutex(mutex)
- , fActive(!reentering)
- {
- if (fActive) umtx_lock(fMutex);
- }
- inline ~XMutex() {
- if (fActive) umtx_unlock(fMutex);
- }
+ inline XMutex(UMutex *mutex, UBool reentering)
+ : fMutex(mutex)
+ , fActive(!reentering)
+ {
+ if (fActive) umtx_lock(fMutex);
+ }
+ inline ~XMutex() {
+ if (fActive) umtx_unlock(fMutex);
+ }
private:
- UMTX *fMutex;
- UBool fActive;
+ UMutex *fMutex;
+ UBool fActive;
};
struct UVectorDeleter {
- UVector* _obj;
- UVectorDeleter() : _obj(NULL) {}
- ~UVectorDeleter() { delete _obj; }
+ UVector* _obj;
+ UVectorDeleter() : _obj(NULL) {}
+ ~UVectorDeleter() { delete _obj; }
};
// called only by factories, treat as private
UObject*
ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUServiceFactory* factory, UErrorCode& status) const
{
- if (U_FAILURE(status)) {
- return NULL;
- }
-
- if (isDefault()) {
- return handleDefault(key, actualReturn, status);
- }
-
- ICUService* ncthis = (ICUService*)this; // cast away semantic const
-
- CacheEntry* result = NULL;
- {
- // The factory list can't be modified until we're done,
- // otherwise we might update the cache with an invalid result.
- // The cache has to stay in synch with the factory list.
- // ICU doesn't have monitors so we can't use rw locks, so
- // we single-thread everything using this service, for now.
-
- // if factory is not null, we're calling from within the mutex,
- // and since some unix machines don't have reentrant mutexes we
- // need to make sure not to try to lock it again.
- XMutex(&ncthis->lock, factory != NULL);
-
- if (serviceCache == NULL) {
- ncthis->serviceCache = new Hashtable(status);
- if (U_FAILURE(status)) {
- delete serviceCache;
+ if (U_FAILURE(status)) {
return NULL;
- }
- serviceCache->setValueDeleter(cacheDeleter);
}
- UnicodeString currentDescriptor;
- UVectorDeleter cacheDescriptorList;
- UBool putInCache = FALSE;
+ if (isDefault()) {
+ return handleDefault(key, actualReturn, status);
+ }
- int32_t startIndex = 0;
- int32_t limit = factories->size();
- UBool cacheResult = TRUE;
+ ICUService* ncthis = (ICUService*)this; // cast away semantic const
- if (factory != NULL) {
- for (int32_t i = 0; i < limit; ++i) {
- if (factory == (const ICUServiceFactory*)factories->elementAt(i)) {
- startIndex = i + 1;
- break;
- }
- }
- if (startIndex == 0) {
- // throw new InternalError("Factory " + factory + "not registered with service: " + this);
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return NULL;
- }
- cacheResult = FALSE;
- }
-
- do {
- currentDescriptor.remove();
- key.currentDescriptor(currentDescriptor);
- result = (CacheEntry*)serviceCache->get(currentDescriptor);
- if (result != NULL) {
- break;
- }
-
- // first test of cache failed, so we'll have to update
- // the cache if we eventually succeed-- that is, if we're
- // going to update the cache at all.
- putInCache = TRUE;
-
- int32_t index = startIndex;
- while (index < limit) {
- ICUServiceFactory* f = (ICUServiceFactory*)factories->elementAt(index++);
- UObject* service = f->create(key, this, status);
- if (U_FAILURE(status)) {
- delete service;
- return NULL;
+ CacheEntry* result = NULL;
+ {
+ // The factory list can't be modified until we're done,
+ // otherwise we might update the cache with an invalid result.
+ // The cache has to stay in synch with the factory list.
+ // ICU doesn't have monitors so we can't use rw locks, so
+ // we single-thread everything using this service, for now.
+
+ // if factory is not null, we're calling from within the mutex,
+ // and since some unix machines don't have reentrant mutexes we
+ // need to make sure not to try to lock it again.
+ XMutex mutex(&lock, factory != NULL);
+
+ if (serviceCache == NULL) {
+ ncthis->serviceCache = new Hashtable(status);
+ if (ncthis->serviceCache == NULL) {
+ return NULL;
+ }
+ if (U_FAILURE(status)) {
+ delete serviceCache;
+ return NULL;
+ }
+ serviceCache->setValueDeleter(cacheDeleter);
}
- if (service != NULL) {
- result = new CacheEntry(currentDescriptor, service);
- if (result == NULL) {
- delete service;
- status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- }
- goto outerEnd;
- }
- }
-
- // prepare to load the cache with all additional ids that
- // will resolve to result, assuming we'll succeed. We
- // don't want to keep querying on an id that's going to
- // fallback to the one that succeeded, we want to hit the
- // cache the first time next goaround.
- if (cacheDescriptorList._obj == NULL) {
- cacheDescriptorList._obj = new UVector(uhash_deleteUnicodeString, NULL, 5, status);
- if (U_FAILURE(status)) {
- return NULL;
- }
- }
- UnicodeString* idToCache = new UnicodeString(currentDescriptor);
- if (idToCache == NULL || idToCache->isBogus()) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- }
+ UnicodeString currentDescriptor;
+ UVectorDeleter cacheDescriptorList;
+ UBool putInCache = FALSE;
- cacheDescriptorList._obj->addElement(idToCache, status);
- if (U_FAILURE(status)) {
- return NULL;
- }
- } while (key.fallback());
- outerEnd:
+ int32_t startIndex = 0;
+ int32_t limit = factories->size();
+ UBool cacheResult = TRUE;
- if (result != NULL) {
- if (putInCache && cacheResult) {
- serviceCache->put(result->actualDescriptor, result, status);
- if (U_FAILURE(status)) {
- delete result;
- return NULL;
+ if (factory != NULL) {
+ for (int32_t i = 0; i < limit; ++i) {
+ if (factory == (const ICUServiceFactory*)factories->elementAt(i)) {
+ startIndex = i + 1;
+ break;
+ }
+ }
+ if (startIndex == 0) {
+ // throw new InternalError("Factory " + factory + "not registered with service: " + this);
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return NULL;
+ }
+ cacheResult = FALSE;
}
- if (cacheDescriptorList._obj != NULL) {
- for (int32_t i = cacheDescriptorList._obj->size(); --i >= 0;) {
- UnicodeString* desc = (UnicodeString*)cacheDescriptorList._obj->elementAt(i);
- serviceCache->put(*desc, result, status);
+ do {
+ currentDescriptor.remove();
+ key.currentDescriptor(currentDescriptor);
+ result = (CacheEntry*)serviceCache->get(currentDescriptor);
+ if (result != NULL) {
+ break;
+ }
+
+ // first test of cache failed, so we'll have to update
+ // the cache if we eventually succeed-- that is, if we're
+ // going to update the cache at all.
+ putInCache = TRUE;
+
+ int32_t index = startIndex;
+ while (index < limit) {
+ ICUServiceFactory* f = (ICUServiceFactory*)factories->elementAt(index++);
+ UObject* service = f->create(key, this, status);
+ if (U_FAILURE(status)) {
+ delete service;
+ return NULL;
+ }
+ if (service != NULL) {
+ result = new CacheEntry(currentDescriptor, service);
+ if (result == NULL) {
+ delete service;
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+
+ goto outerEnd;
+ }
+ }
+
+ // prepare to load the cache with all additional ids that
+ // will resolve to result, assuming we'll succeed. We
+ // don't want to keep querying on an id that's going to
+ // fallback to the one that succeeded, we want to hit the
+ // cache the first time next goaround.
+ if (cacheDescriptorList._obj == NULL) {
+ cacheDescriptorList._obj = new UVector(uprv_deleteUObject, NULL, 5, status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ }
+ UnicodeString* idToCache = new UnicodeString(currentDescriptor);
+ if (idToCache == NULL || idToCache->isBogus()) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+
+ cacheDescriptorList._obj->addElement(idToCache, status);
if (U_FAILURE(status)) {
- delete result;
- return NULL;
+ return NULL;
+ }
+ } while (key.fallback());
+outerEnd:
+
+ if (result != NULL) {
+ if (putInCache && cacheResult) {
+ serviceCache->put(result->actualDescriptor, result, status);
+ if (U_FAILURE(status)) {
+ delete result;
+ return NULL;
+ }
+
+ if (cacheDescriptorList._obj != NULL) {
+ for (int32_t i = cacheDescriptorList._obj->size(); --i >= 0;) {
+ UnicodeString* desc = (UnicodeString*)cacheDescriptorList._obj->elementAt(i);
+ serviceCache->put(*desc, result, status);
+ if (U_FAILURE(status)) {
+ delete result;
+ return NULL;
+ }
+
+ result->ref();
+ cacheDescriptorList._obj->removeElementAt(i);
+ }
+ }
}
- result->ref();
- cacheDescriptorList._obj->removeElementAt(i);
- }
- }
- }
-
- if (actualReturn != NULL) {
- // strip null prefix
- if (result->actualDescriptor.indexOf((UChar)0x2f) == 0) { // U+002f=slash (/)
- actualReturn->remove();
- actualReturn->append(result->actualDescriptor,
- 1,
- result->actualDescriptor.length() - 1);
- } else {
- *actualReturn = result->actualDescriptor;
- }
+ if (actualReturn != NULL) {
+ // strip null prefix
+ if (result->actualDescriptor.indexOf((UChar)0x2f) == 0) { // U+002f=slash (/)
+ actualReturn->remove();
+ actualReturn->append(result->actualDescriptor,
+ 1,
+ result->actualDescriptor.length() - 1);
+ } else {
+ *actualReturn = result->actualDescriptor;
+ }
+
+ if (actualReturn->isBogus()) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ delete result;
+ return NULL;
+ }
+ }
- if (actualReturn->isBogus()) {
- status = U_MEMORY_ALLOCATION_ERROR;
- delete result;
- return NULL;
+ UObject* service = cloneInstance(result->service);
+ if (putInCache && !cacheResult) {
+ delete result;
+ }
+ return service;
}
- }
-
- UObject* service = cloneInstance(result->service);
- if (putInCache && !cacheResult) {
- delete result;
- }
- return service;
}
- }
- return handleDefault(key, actualReturn, status);
+ return handleDefault(key, actualReturn, status);
}
UObject*
ICUService::handleDefault(const ICUServiceKey& /* key */, UnicodeString* /* actualIDReturn */, UErrorCode& /* status */) const
{
- return NULL;
+ return NULL;
}
-
+
UVector&
ICUService::getVisibleIDs(UVector& result, UErrorCode& status) const {
- return getVisibleIDs(result, NULL, status);
+ return getVisibleIDs(result, NULL, status);
}
UVector&
ICUService::getVisibleIDs(UVector& result, const UnicodeString* matchID, UErrorCode& status) const
{
- result.removeAllElements();
-
- if (U_FAILURE(status)) {
- return result;
- }
-
- ICUService * ncthis = (ICUService*)this; // cast away semantic const
- {
- Mutex mutex(&ncthis->lock);
- const Hashtable* map = getVisibleIDMap(status);
- if (map != NULL) {
- ICUServiceKey* fallbackKey = createKey(matchID, status);
-
- for (int32_t pos = -1;;) {
- const UHashElement* e = map->nextElement(pos);
- if (e == NULL) {
- break;
- }
+ result.removeAllElements();
- const UnicodeString* id = (const UnicodeString*)e->key.pointer;
- if (fallbackKey != NULL) {
- if (!fallbackKey->isFallbackOf(*id)) {
- continue;
- }
- }
+ if (U_FAILURE(status)) {
+ return result;
+ }
- UnicodeString* idClone = new UnicodeString(*id);
- if (idClone == NULL || idClone->isBogus()) {
- delete idClone;
- status = U_MEMORY_ALLOCATION_ERROR;
- break;
- }
- result.addElement(idClone, status);
- if (U_FAILURE(status)) {
- delete idClone;
- break;
+ {
+ Mutex mutex(&lock);
+ const Hashtable* map = getVisibleIDMap(status);
+ if (map != NULL) {
+ ICUServiceKey* fallbackKey = createKey(matchID, status);
+
+ for (int32_t pos = -1;;) {
+ const UHashElement* e = map->nextElement(pos);
+ if (e == NULL) {
+ break;
+ }
+
+ const UnicodeString* id = (const UnicodeString*)e->key.pointer;
+ if (fallbackKey != NULL) {
+ if (!fallbackKey->isFallbackOf(*id)) {
+ continue;
+ }
+ }
+
+ UnicodeString* idClone = new UnicodeString(*id);
+ if (idClone == NULL || idClone->isBogus()) {
+ delete idClone;
+ status = U_MEMORY_ALLOCATION_ERROR;
+ break;
+ }
+ result.addElement(idClone, status);
+ if (U_FAILURE(status)) {
+ delete idClone;
+ break;
+ }
+ }
+ delete fallbackKey;
}
- }
- delete fallbackKey;
}
- }
- if (U_FAILURE(status)) {
- result.removeAllElements();
- }
- return result;
+ if (U_FAILURE(status)) {
+ result.removeAllElements();
+ }
+ return result;
}
const Hashtable*
ICUService::getVisibleIDMap(UErrorCode& status) const {
- if (U_FAILURE(status)) return NULL;
+ if (U_FAILURE(status)) return NULL;
- // must only be called when lock is already held
+ // must only be called when lock is already held
- ICUService* ncthis = (ICUService*)this; // cast away semantic const
- if (idCache == NULL) {
- ncthis->idCache = new Hashtable(status);
+ ICUService* ncthis = (ICUService*)this; // cast away semantic const
if (idCache == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- } else if (factories != NULL) {
- for (int32_t pos = factories->size(); --pos >= 0;) {
- ICUServiceFactory* f = (ICUServiceFactory*)factories->elementAt(pos);
- f->updateVisibleIDs(*idCache, status);
- }
- if (U_FAILURE(status)) {
- delete idCache;
- ncthis->idCache = NULL;
- }
+ ncthis->idCache = new Hashtable(status);
+ if (idCache == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ } else if (factories != NULL) {
+ for (int32_t pos = factories->size(); --pos >= 0;) {
+ ICUServiceFactory* f = (ICUServiceFactory*)factories->elementAt(pos);
+ f->updateVisibleIDs(*idCache, status);
+ }
+ if (U_FAILURE(status)) {
+ delete idCache;
+ ncthis->idCache = NULL;
+ }
+ }
}
- }
- return idCache;
+ return idCache;
}
-
+
UnicodeString&
ICUService::getDisplayName(const UnicodeString& id, UnicodeString& result) const
{
- return getDisplayName(id, result, Locale::getDefault());
+ return getDisplayName(id, result, Locale::getDefault());
}
UnicodeString&
ICUService::getDisplayName(const UnicodeString& id, UnicodeString& result, const Locale& locale) const
{
- {
- ICUService* ncthis = (ICUService*)this; // cast away semantic const
- UErrorCode status = U_ZERO_ERROR;
- Mutex mutex(&ncthis->lock);
- const Hashtable* map = getVisibleIDMap(status);
- if (map != NULL) {
- ICUServiceFactory* f = (ICUServiceFactory*)map->get(id);
- if (f != NULL) {
- f->getDisplayName(id, locale, result);
- return result;
- }
-
- // fallback
- UErrorCode status = U_ZERO_ERROR;
- ICUServiceKey* fallbackKey = createKey(&id, status);
- while (fallbackKey->fallback()) {
- UnicodeString us;
- fallbackKey->currentID(us);
- f = (ICUServiceFactory*)map->get(us);
- if (f != NULL) {
- f->getDisplayName(id, locale, result);
- delete fallbackKey;
- return result;
- }
- }
- delete fallbackKey;
- }
- }
- result.setToBogus();
- return result;
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ Mutex mutex(&lock);
+ const Hashtable* map = getVisibleIDMap(status);
+ if (map != NULL) {
+ ICUServiceFactory* f = (ICUServiceFactory*)map->get(id);
+ if (f != NULL) {
+ f->getDisplayName(id, locale, result);
+ return result;
+ }
+
+ // fallback
+ UErrorCode status = U_ZERO_ERROR;
+ ICUServiceKey* fallbackKey = createKey(&id, status);
+ while (fallbackKey->fallback()) {
+ UnicodeString us;
+ fallbackKey->currentID(us);
+ f = (ICUServiceFactory*)map->get(us);
+ if (f != NULL) {
+ f->getDisplayName(id, locale, result);
+ delete fallbackKey;
+ return result;
+ }
+ }
+ delete fallbackKey;
+ }
+ }
+ result.setToBogus();
+ return result;
}
UVector&
ICUService::getDisplayNames(UVector& result, UErrorCode& status) const
{
- return getDisplayNames(result, Locale::getDefault(), NULL, status);
+ return getDisplayNames(result, Locale::getDefault(), NULL, status);
}
UVector&
ICUService::getDisplayNames(UVector& result, const Locale& locale, UErrorCode& status) const
{
- return getDisplayNames(result, locale, NULL, status);
+ return getDisplayNames(result, locale, NULL, status);
}
UVector&
const UnicodeString* matchID,
UErrorCode& status) const
{
- result.removeAllElements();
- if (U_SUCCESS(status)) {
- ICUService* ncthis = (ICUService*)this; // cast away semantic const
- Mutex mutex(&ncthis->lock);
+ result.removeAllElements();
+ result.setDeleter(userv_deleteStringPair);
+ if (U_SUCCESS(status)) {
+ ICUService* ncthis = (ICUService*)this; // cast away semantic const
+ Mutex mutex(&lock);
- if (dnCache != NULL && dnCache->locale != locale) {
- delete dnCache;
- ncthis->dnCache = NULL;
- }
+ if (dnCache != NULL && dnCache->locale != locale) {
+ delete dnCache;
+ ncthis->dnCache = NULL;
+ }
- if (dnCache == NULL) {
- const Hashtable* m = getVisibleIDMap(status);
- if (m != NULL) {
- ncthis->dnCache = new DNCache(locale);
if (dnCache == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return result;
- }
+ const Hashtable* m = getVisibleIDMap(status);
+ if (U_FAILURE(status)) {
+ return result;
+ }
+ ncthis->dnCache = new DNCache(locale);
+ if (dnCache == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return result;
+ }
- int32_t pos = 0;
- const UHashElement* entry = NULL;
- while ((entry = m->nextElement(pos)) != NULL) {
- const UnicodeString* id = (const UnicodeString*)entry->key.pointer;
- ICUServiceFactory* f = (ICUServiceFactory*)entry->value.pointer;
- UnicodeString dname;
- f->getDisplayName(*id, locale, dname);
- if (dname.isBogus()) {
- status = U_MEMORY_ALLOCATION_ERROR;
- } else {
- dnCache->cache.put(dname, (void*)id, status); // share pointer with visibleIDMap
- if (U_SUCCESS(status)) {
- continue;
+ int32_t pos = -1;
+ const UHashElement* entry = NULL;
+ while ((entry = m->nextElement(pos)) != NULL) {
+ const UnicodeString* id = (const UnicodeString*)entry->key.pointer;
+ ICUServiceFactory* f = (ICUServiceFactory*)entry->value.pointer;
+ UnicodeString dname;
+ f->getDisplayName(*id, locale, dname);
+ if (dname.isBogus()) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ } else {
+ dnCache->cache.put(dname, (void*)id, status); // share pointer with visibleIDMap
+ if (U_SUCCESS(status)) {
+ continue;
+ }
+ }
+ delete dnCache;
+ ncthis->dnCache = NULL;
+ return result;
}
- }
- delete dnCache;
- ncthis->dnCache = NULL;
- return result;
}
- }
}
- }
- ICUServiceKey* matchKey = createKey(matchID, status);
- int32_t pos = 0;
- const UHashElement *entry = NULL;
- while ((entry = dnCache->cache.nextElement(pos)) != NULL) {
- const UnicodeString* id = (const UnicodeString*)entry->value.pointer;
- if (matchKey != NULL && !matchKey->isFallbackOf(*id)) {
- continue;
- }
- const UnicodeString* dn = (const UnicodeString*)entry->key.pointer;
- StringPair* sp = StringPair::create(*id, *dn, status);
- result.addElement(sp, status);
- if (U_FAILURE(status)) {
- result.removeAllElements();
- break;
+ ICUServiceKey* matchKey = createKey(matchID, status);
+ /* To ensure that all elements in the hashtable are iterated, set pos to -1.
+ * nextElement(pos) will skip the position at pos and begin the iteration
+ * at the next position, which in this case will be 0.
+ */
+ int32_t pos = -1;
+ const UHashElement *entry = NULL;
+ while ((entry = dnCache->cache.nextElement(pos)) != NULL) {
+ const UnicodeString* id = (const UnicodeString*)entry->value.pointer;
+ if (matchKey != NULL && !matchKey->isFallbackOf(*id)) {
+ continue;
+ }
+ const UnicodeString* dn = (const UnicodeString*)entry->key.pointer;
+ StringPair* sp = StringPair::create(*id, *dn, status);
+ result.addElement(sp, status);
+ if (U_FAILURE(status)) {
+ result.removeAllElements();
+ break;
+ }
}
- }
- delete matchKey;
+ delete matchKey;
- return result;
+ return result;
}
URegistryKey
ICUService::registerInstance(UObject* objToAdopt, const UnicodeString& id, UErrorCode& status)
{
- return registerInstance(objToAdopt, id, TRUE, status);
+ return registerInstance(objToAdopt, id, TRUE, status);
}
URegistryKey
ICUService::registerInstance(UObject* objToAdopt, const UnicodeString& id, UBool visible, UErrorCode& status)
{
- ICUServiceKey* key = createKey(&id, status);
- if (key != NULL) {
- UnicodeString canonicalID;
- key->canonicalID(canonicalID);
- delete key;
+ ICUServiceKey* key = createKey(&id, status);
+ if (key != NULL) {
+ UnicodeString canonicalID;
+ key->canonicalID(canonicalID);
+ delete key;
- ICUServiceFactory* f = createSimpleFactory(objToAdopt, canonicalID, visible, status);
- if (f != NULL) {
- return registerFactory(f, status);
+ ICUServiceFactory* f = createSimpleFactory(objToAdopt, canonicalID, visible, status);
+ if (f != NULL) {
+ return registerFactory(f, status);
+ }
}
- }
- delete objToAdopt;
- return NULL;
+ delete objToAdopt;
+ return NULL;
}
ICUServiceFactory*
ICUService::createSimpleFactory(UObject* objToAdopt, const UnicodeString& id, UBool visible, UErrorCode& status)
{
- if (U_SUCCESS(status)) {
- if ((objToAdopt != NULL) && (!id.isBogus())) {
- return new SimpleFactory(objToAdopt, id, visible);
+ if (U_SUCCESS(status)) {
+ if ((objToAdopt != NULL) && (!id.isBogus())) {
+ return new SimpleFactory(objToAdopt, id, visible);
+ }
+ status = U_ILLEGAL_ARGUMENT_ERROR;
}
- status = U_ILLEGAL_ARGUMENT_ERROR;
- }
- return NULL;
+ return NULL;
}
URegistryKey
ICUService::registerFactory(ICUServiceFactory* factoryToAdopt, UErrorCode& status)
{
- if (U_SUCCESS(status) && factoryToAdopt != NULL) {
- Mutex mutex(&lock);
+ if (U_SUCCESS(status) && factoryToAdopt != NULL) {
+ Mutex mutex(&lock);
- if (factories == NULL) {
- factories = new UVector(deleteUObject, NULL, status);
- if (U_FAILURE(status)) {
- delete factories;
- return NULL;
- }
- }
- factories->insertElementAt(factoryToAdopt, 0, status);
- if (U_SUCCESS(status)) {
- clearCaches();
- } else {
- delete factoryToAdopt;
- factoryToAdopt = NULL;
+ if (factories == NULL) {
+ factories = new UVector(deleteUObject, NULL, status);
+ if (U_FAILURE(status)) {
+ delete factories;
+ return NULL;
+ }
+ }
+ factories->insertElementAt(factoryToAdopt, 0, status);
+ if (U_SUCCESS(status)) {
+ clearCaches();
+ } else {
+ delete factoryToAdopt;
+ factoryToAdopt = NULL;
+ }
}
- }
- if (factoryToAdopt != NULL) {
- notifyChanged();
- }
+ if (factoryToAdopt != NULL) {
+ notifyChanged();
+ }
- return (URegistryKey)factoryToAdopt;
+ return (URegistryKey)factoryToAdopt;
}
UBool
ICUService::unregister(URegistryKey rkey, UErrorCode& status)
{
- ICUServiceFactory *factory = (ICUServiceFactory*)rkey;
- UBool result = FALSE;
- if (factory != NULL && factories != NULL) {
- Mutex mutex(&lock);
+ ICUServiceFactory *factory = (ICUServiceFactory*)rkey;
+ UBool result = FALSE;
+ if (factory != NULL && factories != NULL) {
+ Mutex mutex(&lock);
- if (factories->removeElement(factory)) {
- clearCaches();
- result = TRUE;
- } else {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- delete factory;
+ if (factories->removeElement(factory)) {
+ clearCaches();
+ result = TRUE;
+ } else {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ delete factory;
+ }
}
- }
- if (result) {
- notifyChanged();
- }
- return result;
+ if (result) {
+ notifyChanged();
+ }
+ return result;
}
void
ICUService::reset()
{
- {
- Mutex mutex(&lock);
- reInitializeFactories();
- clearCaches();
- }
- notifyChanged();
+ {
+ Mutex mutex(&lock);
+ reInitializeFactories();
+ clearCaches();
+ }
+ notifyChanged();
}
void
ICUService::reInitializeFactories()
{
- if (factories != NULL) {
- factories->removeAllElements();
- }
+ if (factories != NULL) {
+ factories->removeAllElements();
+ }
}
UBool
ICUService::isDefault() const
{
- return countFactories() == 0;
+ return countFactories() == 0;
}
ICUServiceKey*
ICUService::createKey(const UnicodeString* id, UErrorCode& status) const
{
- return (U_FAILURE(status) || id == NULL) ? NULL : new ICUServiceKey(*id);
+ return (U_FAILURE(status) || id == NULL) ? NULL : new ICUServiceKey(*id);
}
void
ICUService::clearCaches()
{
- // callers synchronize before use
- ++timestamp;
- delete dnCache; dnCache = NULL;
- delete idCache; idCache = NULL;
- delete serviceCache; serviceCache = NULL;
+ // callers synchronize before use
+ ++timestamp;
+ delete dnCache;
+ dnCache = NULL;
+ delete idCache;
+ idCache = NULL;
+ delete serviceCache; serviceCache = NULL;
}
void
ICUService::clearServiceCache()
{
- // callers synchronize before use
- delete serviceCache; serviceCache = NULL;
+ // callers synchronize before use
+ delete serviceCache; serviceCache = NULL;
}
UBool
ICUService::acceptsListener(const EventListener& l) const
{
- return l.getDynamicClassID() == ServiceListener::getStaticClassID();
+ return dynamic_cast<const ServiceListener*>(&l) != NULL;
}
void
ICUService::notifyListener(EventListener& l) const
{
- ((ServiceListener&)l).serviceChanged(*this);
+ ((ServiceListener&)l).serviceChanged(*this);
}
UnicodeString&
ICUService::getName(UnicodeString& result) const
{
- return result.append(name);
+ return result.append(name);
}
int32_t
ICUService::countFactories() const
{
- return factories == NULL ? 0 : factories->size();
+ return factories == NULL ? 0 : factories->size();
}
int32_t
ICUService::getTimestamp() const
{
- return timestamp;
+ return timestamp;
}
U_NAMESPACE_END