]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/translit.cpp
ICU-531.31.tar.gz
[apple/icu.git] / icuSources / i18n / translit.cpp
index a39d6e91c55593745ed552aafb649c65e0e1ea54..bb9ba9b19039564fb0a520c1494e674ae46f92cf 100644 (file)
@@ -1,6 +1,6 @@
 /*
  **********************************************************************
- *   Copyright (C) 1999-2008, International Business Machines
+ *   Copyright (C) 1999-2012, International Business Machines
  *   Corporation and others.  All Rights Reserved.
  **********************************************************************
  *   Date        Name        Description
@@ -8,6 +8,8 @@
  **********************************************************************
  */
 
+#include "utypeinfo.h"  // for 'typeid' to work
+
 #include "unicode/utypes.h"
 
 #if !UCONFIG_NO_TRANSLITERATION
@@ -22,6 +24,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"
@@ -86,20 +89,17 @@ 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 U_NAMESPACE_QUALIFIER 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(status) (registry!=0 || initializeRegistry(status))
 
-// Empty string
-static const UChar EMPTY[] = {0}; //""
-
 U_NAMESPACE_BEGIN
 
 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(Transliterator)
@@ -369,7 +369,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
@@ -408,7 +408,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
@@ -479,14 +479,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);
             }
         }
 
@@ -569,8 +569,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;
@@ -596,7 +595,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);
@@ -634,7 +633,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;
@@ -977,7 +976,6 @@ Transliterator* Transliterator::createBasicInstance(const UnicodeString& id,
     TransliteratorAlias* alias = 0;
     Transliterator* t = 0;
 
-    umtx_init(&registryMutex);
     umtx_lock(&registryMutex);
     if (HAVE_REGISTRY(ec)) {
         t = registry->get(id, alias, ec);
@@ -1101,7 +1099,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;
@@ -1109,7 +1107,8 @@ Transliterator::createFromRules(const UnicodeString& ID,
             }
             if (!parser.dataVector.isEmpty()) {
                 TransliterationRuleData* data = (TransliterationRuleData*)parser.dataVector.orphanElementAt(0);
-                RuleBasedTransliterator* temprbt = new RuleBasedTransliterator(UnicodeString(CompoundTransliterator::PASS_STRING) + (passNumber++),
+                // 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) {
@@ -1145,7 +1144,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();
@@ -1157,18 +1156,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;
@@ -1181,13 +1177,11 @@ const Transliterator& Transliterator::getElement(int32_t index, UErrorCode& ec)
 UnicodeSet& Transliterator::getSourceSet(UnicodeSet& result) const {
     handleGetSourceSet(result);
     if (filter != NULL) {
-        UnicodeSet* 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 (filter->getDynamicClassID() == UnicodeSet::getStaticClassID()) {
-            filterSet = (UnicodeSet*) filter;
-        } else {
+        if (filterSet == NULL) {
             filterSet = new UnicodeSet();
             // Check null pointer
             if (filterSet == NULL) {
@@ -1216,7 +1210,6 @@ 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);
     UErrorCode ec = U_ZERO_ERROR;
     if (HAVE_REGISTRY(ec)) {
@@ -1256,7 +1249,6 @@ void Transliterator::_registerSpecialInverse(const UnicodeString& target,
  * @see #unregister
  */
 void U_EXPORT2 Transliterator::registerInstance(Transliterator* adoptedPrototype) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
     UErrorCode ec = U_ZERO_ERROR;
     if (HAVE_REGISTRY(ec)) {
@@ -1271,7 +1263,6 @@ void Transliterator::_registerInstance(Transliterator* adoptedPrototype) {
 
 void U_EXPORT2 Transliterator::registerAlias(const UnicodeString& aliasID,
                                              const UnicodeString& realID) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
     UErrorCode ec = U_ZERO_ERROR;
     if (HAVE_REGISTRY(ec)) {
@@ -1294,7 +1285,6 @@ void Transliterator::_registerAlias(const UnicodeString& aliasID,
 
  */
 void U_EXPORT2 Transliterator::unregister(const UnicodeString& ID) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
     UErrorCode ec = U_ZERO_ERROR;
     if (HAVE_REGISTRY(ec)) {
@@ -1310,7 +1300,6 @@ void U_EXPORT2 Transliterator::unregister(const UnicodeString& ID) {
  */
 int32_t U_EXPORT2 Transliterator::countAvailableIDs(void) {
     int32_t retVal = 0;
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
     UErrorCode ec = U_ZERO_ERROR;
     if (HAVE_REGISTRY(ec)) {
@@ -1327,7 +1316,6 @@ 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);
     UErrorCode ec = U_ZERO_ERROR;
     if (HAVE_REGISTRY(ec)) {
@@ -1341,7 +1329,6 @@ 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(ec)) {
         result = registry->getAvailableIDs();
@@ -1354,7 +1341,6 @@ StringEnumeration* U_EXPORT2 Transliterator::getAvailableIDs(UErrorCode& ec) {
 }
 
 int32_t U_EXPORT2 Transliterator::countAvailableSources(void) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
     UErrorCode ec = U_ZERO_ERROR;
     return HAVE_REGISTRY(ec) ? _countAvailableSources() : 0;
@@ -1362,7 +1348,6 @@ int32_t U_EXPORT2 Transliterator::countAvailableSources(void) {
 
 UnicodeString& U_EXPORT2 Transliterator::getAvailableSource(int32_t index,
                                                   UnicodeString& result) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
     UErrorCode ec = U_ZERO_ERROR;
     if (HAVE_REGISTRY(ec)) {
@@ -1372,7 +1357,6 @@ UnicodeString& U_EXPORT2 Transliterator::getAvailableSource(int32_t index,
 }
 
 int32_t U_EXPORT2 Transliterator::countAvailableTargets(const UnicodeString& source) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
     UErrorCode ec = U_ZERO_ERROR;
     return HAVE_REGISTRY(ec) ? _countAvailableTargets(source) : 0;
@@ -1381,7 +1365,6 @@ int32_t U_EXPORT2 Transliterator::countAvailableTargets(const UnicodeString& sou
 UnicodeString& U_EXPORT2 Transliterator::getAvailableTarget(int32_t index,
                                                   const UnicodeString& source,
                                                   UnicodeString& result) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
     UErrorCode ec = U_ZERO_ERROR;
     if (HAVE_REGISTRY(ec)) {
@@ -1392,7 +1375,6 @@ 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);
     UErrorCode ec = U_ZERO_ERROR;
     return HAVE_REGISTRY(ec) ? _countAvailableVariants(source, target) : 0;
@@ -1402,7 +1384,6 @@ UnicodeString& U_EXPORT2 Transliterator::getAvailableVariant(int32_t index,
                                                    const UnicodeString& source,
                                                    const UnicodeString& target,
                                                    UnicodeString& result) {
-    umtx_init(&registryMutex);
     Mutex lock(&registryMutex);
     UErrorCode ec = U_ZERO_ERROR;
     if (HAVE_REGISTRY(ec)) {
@@ -1464,7 +1445,7 @@ 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.
@@ -1631,7 +1612,7 @@ UBool Transliterator::initializeRegistry(UErrorCode &status) {
     _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;
 }
@@ -1645,14 +1626,13 @@ U_NAMESPACE_END
  * 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;
 }