X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/73c04bcfe1096173b00431f0cdc742894b15eef0..4f1e1a09ce4daed860e35d359ce2fceccb0764e8:/icuSources/i18n/translit.cpp diff --git a/icuSources/i18n/translit.cpp b/icuSources/i18n/translit.cpp index 8a990f40..8ff0c9f5 100644 --- a/icuSources/i18n/translit.cpp +++ b/icuSources/i18n/translit.cpp @@ -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(®istryMutex); umtx_lock(®istryMutex); - if (HAVE_REGISTRY) { + if (HAVE_REGISTRY(ec)) { t = registry->get(id, alias, ec); } umtx_unlock(®istryMutex); @@ -1005,7 +1011,7 @@ Transliterator* Transliterator::createBasicInstance(const UnicodeString& id, // Step 2. reget umtx_lock(®istryMutex); - if (HAVE_REGISTRY) { + if (HAVE_REGISTRY(ec)) { t = registry->reget(id, parser, alias, ec); } umtx_unlock(®istryMutex); @@ -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(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(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(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(®istryMutex); Mutex lock(®istryMutex); - 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(®istryMutex); Mutex lock(®istryMutex); - 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(®istryMutex); Mutex lock(®istryMutex); - 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(®istryMutex); Mutex lock(®istryMutex); - 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(®istryMutex); + int32_t retVal = 0; Mutex lock(®istryMutex); - 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(®istryMutex); umtx_lock(®istryMutex); - if (HAVE_REGISTRY) { + UErrorCode ec = U_ZERO_ERROR; + if (HAVE_REGISTRY(ec)) { result = ®istry->getAvailableID(index); } umtx_unlock(®istryMutex); @@ -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(®istryMutex); umtx_lock(®istryMutex); - if (HAVE_REGISTRY) { + if (HAVE_REGISTRY(ec)) { result = registry->getAvailableIDs(); } umtx_unlock(®istryMutex); @@ -1320,33 +1343,33 @@ StringEnumeration* U_EXPORT2 Transliterator::getAvailableIDs(UErrorCode& ec) { } int32_t U_EXPORT2 Transliterator::countAvailableSources(void) { - umtx_init(®istryMutex); Mutex lock(®istryMutex); - 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(®istryMutex); Mutex lock(®istryMutex); - 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(®istryMutex); Mutex lock(®istryMutex); - 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(®istryMutex); Mutex lock(®istryMutex); - 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(®istryMutex); Mutex lock(®istryMutex); - 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(®istryMutex); Mutex lock(®istryMutex); - 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() { * is the ID of the system transliterator being defined. These * are public IDs enumerated by Transliterator.getAvailableIDs(), * unless the second field is "internal". - * + * * 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 . - * + * * is either "FORWARD" or "REVERSE". - * + * * is a string to be passed directly to * Transliterator.getInstance(). The returned Transliterator object * then has its ID changed to 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(®istryMutex); return TRUE; }