]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/serv.cpp
ICU-511.25.tar.gz
[apple/icu.git] / icuSources / common / serv.cpp
index c00b9c8fb6402596ebead6c89a528c171c9eeedb..1a8c9166e043b124b2d753d79f393701fee61533 100644 (file)
@@ -1,9 +1,9 @@
- /**
- *******************************************************************************
- * 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() 
@@ -35,355 +35,356 @@ 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
@@ -392,7 +393,7 @@ ICUService::getKey(ICUServiceKey& key, UErrorCode& status) const
 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.
@@ -400,335 +401,336 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode&
 // 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& 
@@ -737,232 +739,240 @@ ICUService::getDisplayNames(UVector& result,
                             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