]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/translit.cpp
ICU-62123.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / translit.cpp
index 8a990f40bcd5c8ca18e3e226aaa1dc1b8328d9fc..8ff0c9f57091d6ed5a97aca765019d57bf89d774 100644 (file)
@@ -1,12 +1,16 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /*
-**********************************************************************
-*   Copyright (C) 1999-2006, International Business Machines
-*   Corporation and others.  All Rights Reserved.
-**********************************************************************
-*   Date        Name        Description
-*   11/17/99    aliu        Creation.
-**********************************************************************
-*/
+ **********************************************************************
+ *   Copyright (C) 1999-2016, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ **********************************************************************
+ *   Date        Name        Description
+ *   11/17/99    aliu        Creation.
+ **********************************************************************
+ */
+
+#include "utypeinfo.h"  // for 'typeid' to work
 
 #include "unicode/utypes.h"
 
@@ -22,6 +26,7 @@
 #include "unicode/uniset.h"
 #include "unicode/uscript.h"
 #include "unicode/strenum.h"
+#include "unicode/utf16.h"
 #include "cpdtrans.h"
 #include "nultrans.h"
 #include "rbt_data.h"
@@ -35,6 +40,7 @@
 #include "tolowtrn.h"
 #include "toupptrn.h"
 #include "uni2name.h"
+#include "brktrans.h"
 #include "esctrn.h"
 #include "unesctrn.h"
 #include "tridpars.h"
@@ -85,19 +91,16 @@ static const char RB_RULE_BASED_IDS[] = "RuleBasedTransliteratorIDs";
 /**
  * The mutex controlling access to registry object.
  */
-static UMTX registryMutex = 0;
+static UMutex registryMutex = U_MUTEX_INITIALIZER;
 
 /**
  * System transliterator registry; non-null when initialized.
  */
-static TransliteratorRegistry* registry = 0;
+static icu::TransliteratorRegistry* registry = 0;
 
 // Macro to check/initialize the registry. ONLY USE WITHIN
 // MUTEX. Avoids function call when registry is initialized.
-#define HAVE_REGISTRY (registry!=0 || initializeRegistry())
-
-// Empty string
-static const UChar EMPTY[] = {0}; //""
+#define HAVE_REGISTRY(status) (registry!=0 || initializeRegistry(status))
 
 U_NAMESPACE_BEGIN
 
@@ -368,7 +371,7 @@ void Transliterator::_transliterate(Replaceable& text,
     }
 
     if (index.limit > 0 &&
-        UTF_IS_LEAD(text.charAt(index.limit - 1))) {
+        U16_IS_LEAD(text.charAt(index.limit - 1))) {
         // Oops, there is a dangling lead surrogate in the buffer.
         // This will break most transliterators, since they will
         // assume it is part of a pair.  Don't transliterate until
@@ -407,7 +410,7 @@ void Transliterator::_transliterate(Replaceable& text,
     int32_t n = getMaximumContextLength();
     while (newCS > originalStart && n-- > 0) {
         --newCS;
-        newCS -= UTF_CHAR_LENGTH(text.char32At(newCS)) - 1;
+        newCS -= U16_LENGTH(text.char32At(newCS)) - 1;
     }
     index.contextStart = uprv_max(newCS, originalStart);
 #endif
@@ -478,14 +481,14 @@ void Transliterator::filteredTransliterate(Replaceable& text,
             UChar32 c;
             while (index.start < globalLimit &&
                    !filter->contains(c=text.char32At(index.start))) {
-                index.start += UTF_CHAR_LENGTH(c);
+                index.start += U16_LENGTH(c);
             }
 
             // Find the end of this run of unfiltered chars
             index.limit = index.start;
             while (index.limit < globalLimit &&
                    filter->contains(c=text.char32At(index.limit))) {
-                index.limit += UTF_CHAR_LENGTH(c);
+                index.limit += U16_LENGTH(c);
             }
         }
 
@@ -568,8 +571,7 @@ void Transliterator::filteredTransliterate(Replaceable& text,
             // transliterations and commit complete transliterations.
             for (;;) {
                 // Length of additional code point, either one or two
-                int32_t charLength =
-                    UTF_CHAR_LENGTH(text.char32At(passLimit));
+                int32_t charLength = U16_LENGTH(text.char32At(passLimit));
                 passLimit += charLength;
                 if (passLimit > runLimit) {
                     break;
@@ -595,7 +597,7 @@ void Transliterator::filteredTransliterate(Replaceable& text,
                     int32_t rs = rollbackStart + delta - (index.limit - passStart);
 
                     // Delete the partially transliterated text
-                    text.handleReplaceBetween(passStart, index.limit, EMPTY);
+                    text.handleReplaceBetween(passStart, index.limit, UnicodeString());
 
                     // Copy the rollback text back
                     text.copy(rs, rs + uncommittedLength, passStart);
@@ -633,7 +635,7 @@ void Transliterator::filteredTransliterate(Replaceable& text,
             globalLimit += totalDelta;
 
             // Delete the rollback copy
-            text.handleReplaceBetween(rollbackOrigin, rollbackOrigin + runLength, EMPTY);
+            text.handleReplaceBetween(rollbackOrigin, rollbackOrigin + runLength, UnicodeString());
 
             // Move start past committed text
             index.start = passStart;
@@ -948,10 +950,15 @@ Transliterator::createInstance(const UnicodeString& ID,
     else {
         t = (Transliterator*)list.elementAt(0);
     }
-    
-    t->setID(canonID);
-    if (globalFilter != NULL) {
-        t->adoptFilter(globalFilter);
+    // Check null pointer
+    if (t != NULL) {
+        t->setID(canonID);
+        if (globalFilter != NULL) {
+            t->adoptFilter(globalFilter);
+        }
+    }
+    else if (U_SUCCESS(status)) {
+        status = U_MEMORY_ALLOCATION_ERROR;
     }
     return t;
 }
@@ -971,9 +978,8 @@ Transliterator* Transliterator::createBasicInstance(const UnicodeString& id,
     TransliteratorAlias* alias = 0;
     Transliterator* t = 0;
 
-    umtx_init(&registryMutex);
     umtx_lock(&registryMutex);
-    if (HAVE_REGISTRY) {
+    if (HAVE_REGISTRY(ec)) {
         t = registry->get(id, alias, ec);
     }
     umtx_unlock(&registryMutex);
@@ -1005,7 +1011,7 @@ Transliterator* Transliterator::createBasicInstance(const UnicodeString& id,
 
             // Step 2. reget
             umtx_lock(&registryMutex);
-            if (HAVE_REGISTRY) {
+            if (HAVE_REGISTRY(ec)) {
                 t = registry->reget(id, parser, alias, ec);
             }
             umtx_unlock(&registryMutex);
@@ -1095,7 +1101,7 @@ Transliterator::createFromRules(const UnicodeString& ID,
                 UnicodeString* idBlock = (UnicodeString*)parser.idBlockVector.elementAt(i);
                 if (!idBlock->isEmpty()) {
                     Transliterator* temp = createInstance(*idBlock, UTRANS_FORWARD, parseError, status);
-                    if (temp != NULL && temp->getDynamicClassID() != NullTransliterator::getStaticClassID())
+                    if (temp != NULL && typeid(*temp) != typeid(NullTransliterator))
                         transliterators.addElement(temp, status);
                     else
                         delete temp;
@@ -1103,15 +1109,27 @@ Transliterator::createFromRules(const UnicodeString& ID,
             }
             if (!parser.dataVector.isEmpty()) {
                 TransliterationRuleData* data = (TransliterationRuleData*)parser.dataVector.orphanElementAt(0);
-                transliterators.addElement(
-                    new RuleBasedTransliterator(UnicodeString(CompoundTransliterator::PASS_STRING) + (passNumber++),
-                    data, TRUE), status);
+                // TODO: Should passNumber be turned into a decimal-string representation (1 -> "1")?
+                RuleBasedTransliterator* temprbt = new RuleBasedTransliterator(UnicodeString(CompoundTransliterator::PASS_STRING) + UnicodeString(passNumber++),
+                        data, TRUE);
+                // Check if NULL before adding it to transliterators to avoid future usage of NULL pointer.
+                if (temprbt == NULL) {
+                    status = U_MEMORY_ALLOCATION_ERROR;
+                    return t;
+                }
+                transliterators.addElement(temprbt, status);
             }
         }
 
         t = new CompoundTransliterator(transliterators, passNumber - 1, parseError, status);
-        t->setID(ID);
-        t->adoptFilter(parser.orphanCompoundFilter());
+        // Null pointer check
+        if (t != NULL) {
+            t->setID(ID);
+            t->adoptFilter(parser.orphanCompoundFilter());
+        }
+    }
+    if (U_SUCCESS(status) && t == NULL) {
+        status = U_MEMORY_ALLOCATION_ERROR;
     }
     return t;
 }
@@ -1128,7 +1146,7 @@ UnicodeString& Transliterator::toRules(UnicodeString& rulesSource,
             if (!ICU_Utility::escapeUnprintable(rulesSource, c)) {
                 rulesSource.append(c);
             }
-            i += UTF_CHAR_LENGTH(c);
+            i += U16_LENGTH(c);
         }
     } else {
         rulesSource = getID();
@@ -1140,18 +1158,15 @@ UnicodeString& Transliterator::toRules(UnicodeString& rulesSource,
 }
 
 int32_t Transliterator::countElements() const {
-    return (this->getDynamicClassID() ==
-            CompoundTransliterator::getStaticClassID()) ?
-        ((const CompoundTransliterator*) this)->getCount() : 0;
+    const CompoundTransliterator* ct = dynamic_cast<const CompoundTransliterator*>(this);
+    return ct != NULL ? ct->getCount() : 0;
 }
 
 const Transliterator& Transliterator::getElement(int32_t index, UErrorCode& ec) const {
     if (U_FAILURE(ec)) {
         return *this;
     }
-    const CompoundTransliterator* cpd =
-        (this->getDynamicClassID() == CompoundTransliterator::getStaticClassID()) ?
-        (const CompoundTransliterator*) this : 0;
+    const CompoundTransliterator* cpd = dynamic_cast<const CompoundTransliterator*>(this);
     int32_t n = (cpd == NULL) ? 1 : cpd->getCount();
     if (index < 0 || index >= n) {
         ec = U_INDEX_OUTOFBOUNDS_ERROR;
@@ -1164,21 +1179,23 @@ const Transliterator& Transliterator::getElement(int32_t index, UErrorCode& ec)
 UnicodeSet& Transliterator::getSourceSet(UnicodeSet& result) const {
     handleGetSourceSet(result);
     if (filter != NULL) {
-    UnicodeSet* filterSet;
-    UBool deleteFilterSet = FALSE;
-    // Most, but not all filters will be UnicodeSets.  Optimize for
-    // the high-runner case.
-    if (filter->getDynamicClassID() == UnicodeSet::getStaticClassID()) {
-        filterSet = (UnicodeSet*) filter;
-    } else {
-        filterSet = new UnicodeSet();
-        deleteFilterSet = TRUE;
-        filter->addMatchSetTo(*filterSet);
-    }
-    result.retainAll(*filterSet);
-    if (deleteFilterSet) {
-        delete filterSet;
-    }
+        UnicodeSet* filterSet = dynamic_cast<UnicodeSet*>(filter);
+        UBool deleteFilterSet = FALSE;
+        // Most, but not all filters will be UnicodeSets.  Optimize for
+        // the high-runner case.
+        if (filterSet == NULL) {
+            filterSet = new UnicodeSet();
+            // Check null pointer
+            if (filterSet == NULL) {
+                return result;
+            }
+            deleteFilterSet = TRUE;
+            filter->addMatchSetTo(*filterSet);
+        }
+        result.retainAll(*filterSet);
+        if (deleteFilterSet) {
+            delete filterSet;
+        }
     }
     return result;
 }
@@ -1195,9 +1212,9 @@ UnicodeSet& Transliterator::getTargetSet(UnicodeSet& result) const {
 void U_EXPORT2 Transliterator::registerFactory(const UnicodeString& id,
                                      Transliterator::Factory factory,
                                      Transliterator::Token context) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
-    if (HAVE_REGISTRY) {
+    UErrorCode ec = U_ZERO_ERROR;
+    if (HAVE_REGISTRY(ec)) {
         _registerFactory(id, factory, context);
     }
 }
@@ -1207,7 +1224,8 @@ void U_EXPORT2 Transliterator::registerFactory(const UnicodeString& id,
 void Transliterator::_registerFactory(const UnicodeString& id,
                                       Transliterator::Factory factory,
                                       Transliterator::Token context) {
-    registry->put(id, factory, context, TRUE);
+    UErrorCode ec = U_ZERO_ERROR;
+    registry->put(id, factory, context, TRUE, ec);
 }
 
 // To be called only by Transliterator subclasses that are called
@@ -1233,43 +1251,45 @@ void Transliterator::_registerSpecialInverse(const UnicodeString& target,
  * @see #unregister
  */
 void U_EXPORT2 Transliterator::registerInstance(Transliterator* adoptedPrototype) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
-    if (HAVE_REGISTRY) {
+    UErrorCode ec = U_ZERO_ERROR;
+    if (HAVE_REGISTRY(ec)) {
         _registerInstance(adoptedPrototype);
     }
 }
 
 void Transliterator::_registerInstance(Transliterator* adoptedPrototype) {
-    registry->put(adoptedPrototype, TRUE);
+    UErrorCode ec = U_ZERO_ERROR;
+    registry->put(adoptedPrototype, TRUE, ec);
 }
 
 void U_EXPORT2 Transliterator::registerAlias(const UnicodeString& aliasID,
                                              const UnicodeString& realID) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
-    if (HAVE_REGISTRY) {
+    UErrorCode ec = U_ZERO_ERROR;
+    if (HAVE_REGISTRY(ec)) {
         _registerAlias(aliasID, realID);
     }
 }
 
 void Transliterator::_registerAlias(const UnicodeString& aliasID,
                                     const UnicodeString& realID) {
-    registry->put(aliasID, realID, FALSE, TRUE);
+    UErrorCode ec = U_ZERO_ERROR;
+    registry->put(aliasID, realID, FALSE, TRUE, ec);
 }
 
 /**
  * Unregisters a transliterator or class.  This may be either
  * a system transliterator or a user transliterator or class.
- * 
+ *
  * @param ID the ID of the transliterator or class
  * @see #registerInstance
 
  */
 void U_EXPORT2 Transliterator::unregister(const UnicodeString& ID) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
-    if (HAVE_REGISTRY) {
+    UErrorCode ec = U_ZERO_ERROR;
+    if (HAVE_REGISTRY(ec)) {
         registry->remove(ID);
     }
 }
@@ -1281,9 +1301,13 @@ void U_EXPORT2 Transliterator::unregister(const UnicodeString& ID) {
  * i from 0 to countAvailableIDs() - 1.
  */
 int32_t U_EXPORT2 Transliterator::countAvailableIDs(void) {
-    umtx_init(&registryMutex);
+    int32_t retVal = 0;
     Mutex lock(&registryMutex);
-    return HAVE_REGISTRY ? registry->countAvailableIDs() : 0;
+    UErrorCode ec = U_ZERO_ERROR;
+    if (HAVE_REGISTRY(ec)) {
+        retVal = registry->countAvailableIDs();
+    }
+    return retVal;
 }
 
 /**
@@ -1294,9 +1318,9 @@ int32_t U_EXPORT2 Transliterator::countAvailableIDs(void) {
  */
 const UnicodeString& U_EXPORT2 Transliterator::getAvailableID(int32_t index) {
     const UnicodeString* result = NULL;
-    umtx_init(&registryMutex);
     umtx_lock(&registryMutex);
-    if (HAVE_REGISTRY) {
+    UErrorCode ec = U_ZERO_ERROR;
+    if (HAVE_REGISTRY(ec)) {
         result = &registry->getAvailableID(index);
     }
     umtx_unlock(&registryMutex);
@@ -1307,9 +1331,8 @@ const UnicodeString& U_EXPORT2 Transliterator::getAvailableID(int32_t index) {
 StringEnumeration* U_EXPORT2 Transliterator::getAvailableIDs(UErrorCode& ec) {
     if (U_FAILURE(ec)) return NULL;
     StringEnumeration* result = NULL;
-    umtx_init(&registryMutex);
     umtx_lock(&registryMutex);
-    if (HAVE_REGISTRY) {
+    if (HAVE_REGISTRY(ec)) {
         result = registry->getAvailableIDs();
     }
     umtx_unlock(&registryMutex);
@@ -1320,33 +1343,33 @@ StringEnumeration* U_EXPORT2 Transliterator::getAvailableIDs(UErrorCode& ec) {
 }
 
 int32_t U_EXPORT2 Transliterator::countAvailableSources(void) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
-    return HAVE_REGISTRY ? _countAvailableSources() : 0;
+    UErrorCode ec = U_ZERO_ERROR;
+    return HAVE_REGISTRY(ec) ? _countAvailableSources() : 0;
 }
 
 UnicodeString& U_EXPORT2 Transliterator::getAvailableSource(int32_t index,
                                                   UnicodeString& result) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
-    if (HAVE_REGISTRY) {
+    UErrorCode ec = U_ZERO_ERROR;
+    if (HAVE_REGISTRY(ec)) {
         _getAvailableSource(index, result);
     }
     return result;
 }
 
 int32_t U_EXPORT2 Transliterator::countAvailableTargets(const UnicodeString& source) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
-    return HAVE_REGISTRY ? _countAvailableTargets(source) : 0;
+    UErrorCode ec = U_ZERO_ERROR;
+    return HAVE_REGISTRY(ec) ? _countAvailableTargets(source) : 0;
 }
 
 UnicodeString& U_EXPORT2 Transliterator::getAvailableTarget(int32_t index,
                                                   const UnicodeString& source,
                                                   UnicodeString& result) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
-    if (HAVE_REGISTRY) {
+    UErrorCode ec = U_ZERO_ERROR;
+    if (HAVE_REGISTRY(ec)) {
         _getAvailableTarget(index, source, result);
     }
     return result;
@@ -1354,18 +1377,18 @@ UnicodeString& U_EXPORT2 Transliterator::getAvailableTarget(int32_t index,
 
 int32_t U_EXPORT2 Transliterator::countAvailableVariants(const UnicodeString& source,
                                                const UnicodeString& target) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
-    return HAVE_REGISTRY ? _countAvailableVariants(source, target) : 0;
+    UErrorCode ec = U_ZERO_ERROR;
+    return HAVE_REGISTRY(ec) ? _countAvailableVariants(source, target) : 0;
 }
 
 UnicodeString& U_EXPORT2 Transliterator::getAvailableVariant(int32_t index,
                                                    const UnicodeString& source,
                                                    const UnicodeString& target,
                                                    UnicodeString& result) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
-    if (HAVE_REGISTRY) {
+    UErrorCode ec = U_ZERO_ERROR;
+    if (HAVE_REGISTRY(ec)) {
         _getAvailableVariant(index, source, target, result);
     }
     return result;
@@ -1424,18 +1447,16 @@ UChar Transliterator::filteredCharAt(const Replaceable& text, int32_t i) const {
  * and return TRUE.  If the registry cannot be initialized, return
  * FALSE (rare).
  *
- * IMPORTANT: Upon entry, registryMutex must be LOCKED.  The entirely
+ * IMPORTANT: Upon entry, registryMutex must be LOCKED.  The entire
  * initialization is done with the lock held.  There is NO REASON to
  * unlock, since no other thread that is waiting on the registryMutex
  * cannot itself proceed until the registry is initialized.
  */
-UBool Transliterator::initializeRegistry() {
+UBool Transliterator::initializeRegistry(UErrorCode &status) {
     if (registry != 0) {
         return TRUE;
     }
 
-    UErrorCode status = U_ZERO_ERROR;
-
     registry = new TransliteratorRegistry(status);
     if (registry == 0 || U_FAILURE(status)) {
         delete registry;
@@ -1464,13 +1485,13 @@ UBool Transliterator::initializeRegistry() {
      * <id> is the ID of the system transliterator being defined.  These
      * are public IDs enumerated by Transliterator.getAvailableIDs(),
      * unless the second field is "internal".
-     * 
+     *
      * <resource> is a ResourceReader resource name.  Currently these refer
      * to file names under com/ibm/text/resources.  This string is passed
      * directly to ResourceReader, together with <encoding>.
-     * 
+     *
      * <direction> is either "FORWARD" or "REVERSE".
-     * 
+     *
      * <getInstanceArg> is a string to be passed directly to
      * Transliterator.getInstance().  The returned Transliterator object
      * then has its ID changed to <id> and is returned.
@@ -1479,52 +1500,53 @@ UBool Transliterator::initializeRegistry() {
      */
     //static const char translit_index[] = "translit_index";
 
-    UResourceBundle *bundle, *transIDs, *colBund;
-    bundle = ures_open(U_ICUDATA_TRANSLIT, NULL/*open root bundle*/, &status);
-    transIDs = ures_getByKey(bundle, RB_RULE_BASED_IDS, 0, &status);
-
-    int32_t row, maxRows;
+    UResourceBundle *bundle = ures_open(U_ICUDATA_TRANSLIT, NULL/*open default locale*/, &status);
+    UResourceBundle *transIDs = ures_getByKey(bundle, RB_RULE_BASED_IDS, 0, &status);
     if (U_SUCCESS(status)) {
-        maxRows = ures_getSize(transIDs);
+        UResourceBundle *colBund = NULL;
+        UResourceBundle* res = NULL;
+        int32_t row, maxRows = ures_getSize(transIDs);
         for (row = 0; row < maxRows; row++) {
-            colBund = ures_getByIndex(transIDs, row, 0, &status);
-            if (U_SUCCESS(status)) {
-                UnicodeString id(ures_getKey(colBund), -1, US_INV);
-                UResourceBundle* res = ures_getNextResource(colBund, NULL, &status);
-                const char* typeStr = ures_getKey(res);
-                UChar type;
-                u_charsToUChars(typeStr, &type, 1);
-
-                if (U_SUCCESS(status)) {
-                    int32_t len = 0;
-                    const UChar *resString;
-                    switch (type) {
-                    case 0x66: // 'f'
-                    case 0x69: // 'i'
-                        // 'file' or 'internal';
-                        // row[2]=resource, row[3]=direction
-                        {
-                            
-                            resString = ures_getStringByKey(res, "resource", &len, &status);
-                            UBool visible = (type == 0x0066 /*f*/);
-                            UTransDirection dir = 
-                                (ures_getUnicodeStringByKey(res, "direction", &status).charAt(0) ==
-                                 0x0046 /*F*/) ?
-                                UTRANS_FORWARD : UTRANS_REVERSE;
-                            registry->put(id, UnicodeString(TRUE, resString, len), dir, TRUE, visible);
-                        }
-                        break;
-                    case 0x61: // 'a'
-                        // 'alias'; row[2]=createInstance argument
-                        resString = ures_getString(res, &len, &status);
-                        registry->put(id, UnicodeString(TRUE, resString, len), TRUE, TRUE);
-                        break;
+            colBund = ures_getByIndex(transIDs, row, colBund, &status);
+            if (U_FAILURE(status)) {
+                break;
+            }
+            const char *tridKey = ures_getKey(colBund);
+            if (tridKey == NULL || uprv_strstr(tridKey, "-t-") != NULL) {
+                continue; // Apple version should not get any of these, eliminated the root.txt entries
+            }
+            res = ures_getNextResource(colBund, res, &status);
+            if (U_FAILURE(status)) {
+                break;
+            }
+            UnicodeString trID(tridKey, -1, US_INV);
+            const char* typeStr = ures_getKey(res);
+            int32_t len = 0, dlen = 0;
+            UBool visible = FALSE;
+            const UChar *resString;
+            switch (typeStr[0]) {
+                case 'f': // "file"
+                    visible = TRUE;
+                    // FALLTHROUGH
+                case 'i': // "internal" => visible = FALSE
+                    // child resources are resource and direction
+                    {
+                        resString = ures_getStringByKey(res, "resource", &len, &status);
+                        const UChar* dirString = ures_getStringByKey(res, "direction", &dlen, &status);
+                        UTransDirection dir = (dlen <= 0 || dirString[0] ==  0x0046 /*F*/)? UTRANS_FORWARD : UTRANS_REVERSE;
+                        registry->put(trID, UnicodeString(TRUE, resString, len), dir, TRUE, visible, status);
                     }
-                }
-                ures_close(res);
+                    break;
+                case 'a': // "alias", string argument is alias
+                    resString = ures_getString(res, &len, &status);
+                    registry->put(trID, UnicodeString(TRUE, resString, len), TRUE, TRUE, status);
+                    break;
+                default: // do nothing
+                    break;
             }
-            ures_close(colBund);
         }
+        ures_close(res);
+        ures_close(colBund);
     }
 
     ures_close(transIDs);
@@ -1534,12 +1556,51 @@ UBool Transliterator::initializeRegistry() {
     // cache.  This is how new non-rule-based transliterators are
     // added to the system.
 
-    registry->put(new NullTransliterator(), TRUE);
-    registry->put(new LowercaseTransliterator(), TRUE);
-    registry->put(new UppercaseTransliterator(), TRUE);
-    registry->put(new TitlecaseTransliterator(), TRUE);
-    registry->put(new UnicodeNameTransliterator(), TRUE);
-    registry->put(new NameUnicodeTransliterator(), TRUE);
+    // This is to allow for null pointer check
+    NullTransliterator* tempNullTranslit = new NullTransliterator();
+    LowercaseTransliterator* tempLowercaseTranslit = new LowercaseTransliterator();
+    UppercaseTransliterator* tempUppercaseTranslit = new UppercaseTransliterator();
+    TitlecaseTransliterator* tempTitlecaseTranslit = new TitlecaseTransliterator();
+    UnicodeNameTransliterator* tempUnicodeTranslit = new UnicodeNameTransliterator();
+    NameUnicodeTransliterator* tempNameUnicodeTranslit = new NameUnicodeTransliterator();
+#if !UCONFIG_NO_BREAK_ITERATION
+     // TODO: could or should these transliterators be referenced polymorphically once constructed?
+     BreakTransliterator* tempBreakTranslit         = new BreakTransliterator();
+#endif
+    // Check for null pointers
+    if (tempNullTranslit == NULL || tempLowercaseTranslit == NULL || tempUppercaseTranslit == NULL ||
+        tempTitlecaseTranslit == NULL || tempUnicodeTranslit == NULL ||
+#if !UCONFIG_NO_BREAK_ITERATION
+        tempBreakTranslit == NULL ||
+#endif
+        tempNameUnicodeTranslit == NULL )
+    {
+        delete tempNullTranslit;
+        delete tempLowercaseTranslit;
+        delete tempUppercaseTranslit;
+        delete tempTitlecaseTranslit;
+        delete tempUnicodeTranslit;
+        delete tempNameUnicodeTranslit;
+#if !UCONFIG_NO_BREAK_ITERATION
+        delete tempBreakTranslit;
+#endif
+        // Since there was an error, remove registry
+        delete registry;
+        registry = NULL;
+
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return 0;
+    }
+
+    registry->put(tempNullTranslit, TRUE, status);
+    registry->put(tempLowercaseTranslit, TRUE, status);
+    registry->put(tempUppercaseTranslit, TRUE, status);
+    registry->put(tempTitlecaseTranslit, TRUE, status);
+    registry->put(tempUnicodeTranslit, TRUE, status);
+    registry->put(tempNameUnicodeTranslit, TRUE, status);
+#if !UCONFIG_NO_BREAK_ITERATION
+    registry->put(tempBreakTranslit, FALSE, status);   // FALSE means invisible.
+#endif
 
     RemoveTransliterator::registerIDs(); // Must be within mutex
     EscapeTransliterator::registerIDs();
@@ -1554,27 +1615,27 @@ UBool Transliterator::initializeRegistry() {
     _registerSpecialInverse(UNICODE_STRING_SIMPLE("Title"),
                             UNICODE_STRING_SIMPLE("Lower"), FALSE);
 
-    ucln_i18n_registerCleanup(UCLN_I18N_TRANSLITERATOR, transliterator_cleanup);
+    ucln_i18n_registerCleanup(UCLN_I18N_TRANSLITERATOR, utrans_transliterator_cleanup);
 
     return TRUE;
 }
 
 U_NAMESPACE_END
 
-// Defined in ucln_in.h:
+// Defined in transreg.h:
 
 /**
  * Release all static memory held by transliterator.  This will
  * necessarily invalidate any rule-based transliterators held by the
  * user, because RBTs hold pointers to common data objects.
  */
-U_CFUNC UBool transliterator_cleanup(void) {
+U_CFUNC UBool utrans_transliterator_cleanup(void) {
+    U_NAMESPACE_USE
     TransliteratorIDParser::cleanup();
     if (registry) {
         delete registry;
         registry = NULL;
     }
-    umtx_destroy(&registryMutex);
     return TRUE;
 }