]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/tridpars.cpp
ICU-461.18.tar.gz
[apple/icu.git] / icuSources / i18n / tridpars.cpp
index 33c5b263fb5dda02f76e99258f8ef935f5b45378..cf9fd3fb5b6eefd67aa0f24797d9677637f8ea80 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2002-2003, International Business Machines Corporation
+*   Copyright (c) 2002-2009, International Business Machines Corporation
 *   and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -33,7 +33,7 @@ static const UChar VARIANT_SEP = 0x002F; // /
 static const UChar OPEN_REV    = 0x0028; // (
 static const UChar CLOSE_REV   = 0x0029; // )
 
-static const UChar EMPTY[]     = {0}; // ""
+//static const UChar EMPTY[]     = {0}; // ""
 static const UChar ANY[]       = {65,110,121,0}; // "Any"
 static const UChar ANY_NULL[]  = {65,110,121,45,78,117,108,108,0}; // "Any-Null"
 
@@ -105,7 +105,7 @@ Transliterator* TransliteratorIDParser::SingleID::createInstance() {
  */
 TransliteratorIDParser::SingleID*
 TransliteratorIDParser::parseSingleID(const UnicodeString& id, int32_t& pos,
-                                      int32_t dir) {
+                                      int32_t dir, UErrorCode& status) {
 
     int32_t start = pos;
 
@@ -146,6 +146,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 +162,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) {
@@ -167,11 +181,16 @@ TransliteratorIDParser::parseSingleID(const UnicodeString& id, int32_t& pos,
         if (dir == FORWARD) {
             single = specsToID(specsA, FORWARD);
         } else {
-            single = specsToSpecialInverse(*specsA);
+            single = specsToSpecialInverse(*specsA, status);
             if (single == NULL) {
                 single = specsToID(specsA, REVERSE);
             }
         }
+        // Check for NULL pointer
+        if (single == NULL) {
+               status = U_MEMORY_ALLOCATION_ERROR;
+               return NULL;
+        }
         single->filter = specsA->filter;
     }
 
@@ -203,7 +222,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;
 }
@@ -251,7 +272,7 @@ UnicodeSet* TransliteratorIDParser::parseGlobalFilter(const UnicodeString& id, i
     if (UnicodeSet::resemblesPattern(id, pos)) {
         ParsePosition ppos(pos);
         UErrorCode ec = U_ZERO_ERROR;
-        filter = new UnicodeSet(id, ppos, USET_IGNORE_SPACE, ec);
+        filter = new UnicodeSet(id, ppos, USET_IGNORE_SPACE, NULL, ec);
         /* test for NULL */
         if (filter == 0) {
             pos = start;
@@ -301,7 +322,7 @@ static void U_CALLCONV _deleteSingleID(void* obj) {
     delete (TransliteratorIDParser::SingleID*) obj;
 }
 
-static void U_CALLCONV _deleteTransliterator(void* obj) {
+static void U_CALLCONV _deleteTransliteratorTrIDPars(void* obj) {
     delete (Transliterator*) obj;
 }
 U_CDECL_END
@@ -360,7 +381,7 @@ UBool TransliteratorIDParser::parseCompoundID(const UnicodeString& id, int32_t d
 
     UBool sawDelimiter = TRUE;
     for (;;) {
-        SingleID* single = parseSingleID(id, pos, dir);
+        SingleID* single = parseSingleID(id, pos, dir, ec);
         if (single == NULL) {
             break;
         }
@@ -437,41 +458,23 @@ UBool TransliteratorIDParser::parseCompoundID(const UnicodeString& id, int32_t d
  * the reverse.  THIS MAY RESULT IN AN EMPTY VECTOR.  Convert
  * SingleID entries to actual transliterators.
  *
- * Also, optionally, insert the given transliterator at the given
- * position.  This effectively happens before anything else.
- *
  * @param list vector of SingleID objects.  On exit, vector
  * of one or more Transliterators.
- * @param insert Transliterator to insert, or NULL if none.
- * Adopted.
- * @param insertIndex index from 0..list.size()-1, at which
- * to place 'insert', or -1 if none.
  * @return new value of insertIndex.  The index will shift if
  * there are empty items, like "(Lower)", with indices less than
  * insertIndex.
  */
-int32_t TransliteratorIDParser::instantiateList(UVector& list,
-                                                Transliterator* insert,
-                                                int32_t insertIndex,
+void TransliteratorIDParser::instantiateList(UVector& list,
                                                 UErrorCode& ec) {
     UVector tlist(ec);
     if (U_FAILURE(ec)) {
         goto RETURN;
     }
-    tlist.setDeleter(_deleteTransliterator);
+    tlist.setDeleter(_deleteTransliteratorTrIDPars);
 
     Transliterator* t;
     int32_t i;
     for (i=0; i<=list.size(); ++i) { // [sic]: i<=list.size()
-        if (insertIndex == i) {
-            insertIndex = tlist.size();
-            tlist.addElement(insert, ec);
-            if (U_FAILURE(ec)) {
-                goto RETURN;
-            }
-            insert = NULL;
-        }
-
         // We run the loop too long by one, so we can
         // do an insert after the last element
         if (i==list.size()) {
@@ -512,7 +515,7 @@ int32_t TransliteratorIDParser::instantiateList(UVector& list,
     list.removeAllElements();
 
     if (U_SUCCESS(ec)) {
-        list.setDeleter(_deleteTransliterator);
+        list.setDeleter(_deleteTransliteratorTrIDPars);
 
         while (tlist.size() > 0) {
             t = (Transliterator*) tlist.orphanElementAt(0);
@@ -525,9 +528,7 @@ int32_t TransliteratorIDParser::instantiateList(UVector& list,
         }
     }
 
-    delete insert; // Clean up in case of failure
     list.setDeleter(save);
-    return insertIndex;
 }
 
 /**
@@ -601,6 +602,10 @@ void TransliteratorIDParser::STVtoID(const UnicodeString& source,
     if (variant.length() != 0) {
         id.append(VARIANT_SEP).append(variant);
     }
+    // NUL-terminate the ID string for getTerminatedBuffer.
+    // This prevents valgrind and Purify warnings.
+    id.append((UChar)0);
+    id.truncate(id.length()-1);
 }
 
 /**
@@ -637,21 +642,33 @@ void TransliteratorIDParser::STVtoID(const UnicodeString& source,
  */
 void TransliteratorIDParser::registerSpecialInverse(const UnicodeString& target,
                                                     const UnicodeString& inverseTarget,
-                                                    UBool bidirectional) {
-    init();
+                                                    UBool bidirectional,
+                                                    UErrorCode &status) {
+    init(status);
+    if (U_FAILURE(status)) {
+        return;
+    }
 
     // If target == inverseTarget then force bidirectional => FALSE
     if (bidirectional && 0==target.caseCompare(inverseTarget, U_FOLD_CASE_DEFAULT)) {
         bidirectional = FALSE;
     }
 
-    umtx_init(&LOCK);
     Mutex lock(&LOCK);
 
-    UErrorCode ec = U_ZERO_ERROR;
-    SPECIAL_INVERSES->put(target, new UnicodeString(inverseTarget), ec);
+    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), ec);
+       tempus = new UnicodeString(target);
+       if (tempus == NULL) {
+               status = U_MEMORY_ALLOCATION_ERROR;
+               return;
+       }
+        SPECIAL_INVERSES->put(inverseTarget, tempus, status);
     }
 }
 
@@ -705,7 +722,7 @@ TransliteratorIDParser::parseFilterID(const UnicodeString& id, int32_t& pos,
 
             ParsePosition ppos(pos);
             UErrorCode ec = U_ZERO_ERROR;
-            UnicodeSet set(id, ppos, USET_IGNORE_SPACE, ec);
+            UnicodeSet set(id, ppos, USET_IGNORE_SPACE, NULL, ec);
             if (U_FAILURE(ec)) {
                 pos = start;
                 return NULL;
@@ -830,15 +847,14 @@ TransliteratorIDParser::specsToID(const Specs* specs, int32_t dir) {
  * 'filter' field of NULL.
  */
 TransliteratorIDParser::SingleID*
-TransliteratorIDParser::specsToSpecialInverse(const Specs& specs) {
+TransliteratorIDParser::specsToSpecialInverse(const Specs& specs, UErrorCode &status) {
     if (0!=specs.source.caseCompare(ANY, U_FOLD_CASE_DEFAULT)) {
         return NULL;
     }
-    init();
+    init(status);
 
     UnicodeString* inverseTarget;
 
-    umtx_init(&LOCK);
     umtx_lock(&LOCK);
     inverseTarget = (UnicodeString*) SPECIAL_INVERSES->get(specs.target);
     umtx_unlock(&LOCK);
@@ -880,24 +896,28 @@ Transliterator* TransliteratorIDParser::createBasicInstance(const UnicodeString&
 /**
  * Initialize static memory.
  */
-void TransliteratorIDParser::init() {
+void TransliteratorIDParser::init(UErrorCode &status) {
     if (SPECIAL_INVERSES != NULL) {
         return;
     }
 
-    Hashtable* special_inverses = new Hashtable(TRUE);
+    Hashtable* special_inverses = new Hashtable(TRUE, status);
+    // Null pointer check
+    if (special_inverses == NULL) {
+       status = U_MEMORY_ALLOCATION_ERROR;
+       return;
+    }
     special_inverses->setValueDeleter(uhash_deleteUnicodeString);
 
-    umtx_init(&LOCK);
     umtx_lock(&LOCK);
     if (SPECIAL_INVERSES == NULL) {
         SPECIAL_INVERSES = special_inverses;
         special_inverses = NULL;
     }
     umtx_unlock(&LOCK);
-    delete special_inverses;
+    delete special_inverses; /*null instance*/
 
-    ucln_i18n_registerCleanup();
+    ucln_i18n_registerCleanup(UCLN_I18N_TRANSLITERATOR, utrans_transliterator_cleanup);
 }
 
 /**