]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/tridpars.cpp
ICU-57131.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / tridpars.cpp
index f0338de254f621667b82d82e5ad879f4d0020f18..4b48d5f8d621cfef6cabdab683cadfabcab5f143 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2002-2006, International Business Machines Corporation
+*   Copyright (c) 2002-2014, International Business Machines Corporation
 *   and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -15,6 +15,8 @@
 #include "tridpars.h"
 #include "hash.h"
 #include "mutex.h"
+#include "transreg.h"
+#include "uassert.h"
 #include "ucln_in.h"
 #include "unicode/parsepos.h"
 #include "unicode/translit.h"
@@ -41,11 +43,12 @@ static const int32_t FORWARD = UTRANS_FORWARD;
 static const int32_t REVERSE = UTRANS_REVERSE;
 
 static Hashtable* SPECIAL_INVERSES = NULL;
+static UInitOnce gSpecialInversesInitOnce = U_INITONCE_INITIALIZER;
 
 /**
  * The mutex controlling access to SPECIAL_INVERSES
  */
-static UMTX LOCK = 0;
+static UMutex LOCK = U_MUTEX_INITIALIZER;
 
 TransliteratorIDParser::Specs::Specs(const UnicodeString& s, const UnicodeString& t,
                                      const UnicodeString& v, UBool sawS,
@@ -72,7 +75,7 @@ TransliteratorIDParser::SingleID::SingleID(const UnicodeString& c, const Unicode
 Transliterator* TransliteratorIDParser::SingleID::createInstance() {
     Transliterator* t;
     if (basicID.length() == 0) {
-        t = createBasicInstance(ANY_NULL, &canonID);
+        t = createBasicInstance(UnicodeString(TRUE, ANY_NULL, 8), &canonID);
     } else {
         t = createBasicInstance(basicID, &canonID);
     }
@@ -146,6 +149,13 @@ TransliteratorIDParser::parseSingleID(const UnicodeString& id, int32_t& pos,
         if (dir == FORWARD) {
             SingleID* b = specsToID(specsB, FORWARD);
             single = specsToID(specsA, FORWARD);
+            // Null pointers check
+            if (b == NULL || single == NULL) {
+               delete b;
+               delete single;
+               status = U_MEMORY_ALLOCATION_ERROR;
+               return NULL;
+            }
             single->canonID.append(OPEN_REV)
                 .append(b->canonID).append(CLOSE_REV);
             if (specsA != NULL) {
@@ -155,6 +165,13 @@ TransliteratorIDParser::parseSingleID(const UnicodeString& id, int32_t& pos,
         } else {
             SingleID* a = specsToID(specsA, FORWARD);
             single = specsToID(specsB, FORWARD);
+            // Check for null pointer.
+            if (a == NULL || single == NULL) {
+               delete a;
+               delete single;
+               status = U_MEMORY_ALLOCATION_ERROR;
+               return NULL;
+            }
             single->canonID.append(OPEN_REV)
                 .append(a->canonID).append(CLOSE_REV);
             if (specsB != NULL) {
@@ -172,6 +189,11 @@ TransliteratorIDParser::parseSingleID(const UnicodeString& id, int32_t& pos,
                 single = specsToID(specsA, REVERSE);
             }
         }
+        // Check for NULL pointer
+        if (single == NULL) {
+               status = U_MEMORY_ALLOCATION_ERROR;
+               return NULL;
+        }
         single->filter = specsA->filter;
     }
 
@@ -203,7 +225,9 @@ TransliteratorIDParser::parseFilterID(const UnicodeString& id, int32_t& pos) {
 
     // Assemble return results
     SingleID* single = specsToID(specs, FORWARD);
-    single->filter = specs->filter;
+    if (single != NULL) {
+        single->filter = specs->filter;
+    }
     delete specs;
     return single;
 }
@@ -477,7 +501,7 @@ void TransliteratorIDParser::instantiateList(UVector& list,
 
     // An empty list is equivalent to a NULL transliterator.
     if (tlist.size() == 0) {
-        t = createBasicInstance(ANY_NULL, NULL);
+        t = createBasicInstance(UnicodeString(TRUE, ANY_NULL, 8), NULL);
         if (t == NULL) {
             // Should never happen
             ec = U_INTERNAL_TRANSLITERATOR_ERROR;
@@ -526,7 +550,7 @@ void TransliteratorIDParser::IDtoSTV(const UnicodeString& id,
                                      UnicodeString& target,
                                      UnicodeString& variant,
                                      UBool& isSourcePresent) {
-    source = ANY;
+    source.setTo(ANY, 3);
     target.truncate(0);
     variant.truncate(0);
 
@@ -575,7 +599,7 @@ void TransliteratorIDParser::STVtoID(const UnicodeString& source,
                                      UnicodeString& id) {
     id = source;
     if (id.length() == 0) {
-        id = ANY;
+        id.setTo(ANY, 3);
     }
     id.append(TARGET_SEP).append(target);
     if (variant.length() != 0) {
@@ -623,7 +647,7 @@ void TransliteratorIDParser::registerSpecialInverse(const UnicodeString& target,
                                                     const UnicodeString& inverseTarget,
                                                     UBool bidirectional,
                                                     UErrorCode &status) {
-    init(status);
+    umtx_initOnce(gSpecialInversesInitOnce, init, status);
     if (U_FAILURE(status)) {
         return;
     }
@@ -633,12 +657,21 @@ void TransliteratorIDParser::registerSpecialInverse(const UnicodeString& target,
         bidirectional = FALSE;
     }
 
-    umtx_init(&LOCK);
     Mutex lock(&LOCK);
 
-    SPECIAL_INVERSES->put(target, new UnicodeString(inverseTarget), status);
+    UnicodeString *tempus = new UnicodeString(inverseTarget);  // Used for null pointer check before usage.
+    if (tempus == NULL) {
+       status = U_MEMORY_ALLOCATION_ERROR;
+       return;
+    }
+    SPECIAL_INVERSES->put(target, tempus, status);
     if (bidirectional) {
-        SPECIAL_INVERSES->put(inverseTarget, new UnicodeString(target), status);
+       tempus = new UnicodeString(target);
+       if (tempus == NULL) {
+               status = U_MEMORY_ALLOCATION_ERROR;
+               return;
+       }
+        SPECIAL_INVERSES->put(inverseTarget, tempus, status);
     }
 }
 
@@ -761,11 +794,11 @@ TransliteratorIDParser::parseFilterID(const UnicodeString& id, int32_t& pos,
     // Empty source or target defaults to ANY
     UBool sawSource = TRUE;
     if (source.length() == 0) {
-        source = ANY;
+        source.setTo(ANY, 3);
         sawSource = FALSE;
     }
     if (target.length() == 0) {
-        target = ANY;
+        target.setTo(ANY, 3);
     }
 
     return new Specs(source, target, variant, sawSource, filter);
@@ -818,14 +851,16 @@ TransliteratorIDParser::specsToID(const Specs* specs, int32_t dir) {
  */
 TransliteratorIDParser::SingleID*
 TransliteratorIDParser::specsToSpecialInverse(const Specs& specs, UErrorCode &status) {
-    if (0!=specs.source.caseCompare(ANY, U_FOLD_CASE_DEFAULT)) {
+    if (0!=specs.source.caseCompare(ANY, 3, U_FOLD_CASE_DEFAULT)) {
+        return NULL;
+    }
+    umtx_initOnce(gSpecialInversesInitOnce, init, status);
+    if (U_FAILURE(status)) {
         return NULL;
     }
-    init(status);
 
     UnicodeString* inverseTarget;
 
-    umtx_init(&LOCK);
     umtx_lock(&LOCK);
     inverseTarget = (UnicodeString*) SPECIAL_INVERSES->get(specs.target);
     umtx_unlock(&LOCK);
@@ -839,11 +874,11 @@ TransliteratorIDParser::specsToSpecialInverse(const Specs& specs, UErrorCode &st
             buf.append(specs.filter);
         }
         if (specs.sawSource) {
-            buf.append(ANY).append(TARGET_SEP);
+            buf.append(ANY, 3).append(TARGET_SEP);
         }
         buf.append(*inverseTarget);
 
-        UnicodeString basicID(ANY);
+        UnicodeString basicID(TRUE, ANY, 3);
         basicID.append(TARGET_SEP).append(*inverseTarget);
 
         if (specs.variant.length() != 0) {
@@ -865,26 +900,18 @@ Transliterator* TransliteratorIDParser::createBasicInstance(const UnicodeString&
 }
 
 /**
- * Initialize static memory.
+ * Initialize static memory. Called through umtx_initOnce only.
  */
 void TransliteratorIDParser::init(UErrorCode &status) {
-    if (SPECIAL_INVERSES != NULL) {
-        return;
-    }
-
-    Hashtable* special_inverses = new Hashtable(TRUE, status);
-    special_inverses->setValueDeleter(uhash_deleteUnicodeString);
+    U_ASSERT(SPECIAL_INVERSES == NULL);
+    ucln_i18n_registerCleanup(UCLN_I18N_TRANSLITERATOR, utrans_transliterator_cleanup);
 
-    umtx_init(&LOCK);
-    umtx_lock(&LOCK);
+    SPECIAL_INVERSES = new Hashtable(TRUE, status);
     if (SPECIAL_INVERSES == NULL) {
-        SPECIAL_INVERSES = special_inverses;
-        special_inverses = NULL;
+       status = U_MEMORY_ALLOCATION_ERROR;
+       return;
     }
-    umtx_unlock(&LOCK);
-    delete special_inverses; /*null instance*/
-
-    ucln_i18n_registerCleanup(UCLN_I18N_TRANSLITERATOR, transliterator_cleanup);
+    SPECIAL_INVERSES->setValueDeleter(uprv_deleteUObject);
 }
 
 /**
@@ -895,7 +922,7 @@ void TransliteratorIDParser::cleanup() {
         delete SPECIAL_INVERSES;
         SPECIAL_INVERSES = NULL;
     }
-    umtx_destroy(&LOCK);
+    gSpecialInversesInitOnce.reset();
 }
 
 U_NAMESPACE_END