ICU-551.24.tar.gz
[apple/icu.git] / icuSources / i18n / identifier_info.cpp
index 369a0678c59f41579cbfbf5423d3786bbbef35d7..0c0706f1ccdb1273f1ce84ea182b77e8444e065b 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2012-2013, International Business Machines
+*   Copyright (C) 2012-2014, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 */
 
 U_NAMESPACE_BEGIN
 
-#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+static UnicodeSet *ASCII;
+static ScriptSet *JAPANESE;
+static ScriptSet *CHINESE;
+static ScriptSet *KOREAN;
+static ScriptSet *CONFUSABLE_WITH_LATIN;
+static UInitOnce gIdentifierInfoInitOnce = U_INITONCE_INITIALIZER;
 
-static UMutex gInitMutex = U_MUTEX_INITIALIZER;
-static UBool gStaticsAreInitialized = FALSE;
 
-UnicodeSet *IdentifierInfo::ASCII;
-ScriptSet *IdentifierInfo::JAPANESE;
-ScriptSet *IdentifierInfo::CHINESE;
-ScriptSet *IdentifierInfo::KOREAN;
-ScriptSet *IdentifierInfo::CONFUSABLE_WITH_LATIN;
-
-UBool IdentifierInfo::cleanup() {
+U_CDECL_BEGIN
+static UBool U_CALLCONV
+IdentifierInfo_cleanup(void) {
     delete ASCII;
     ASCII = NULL;
     delete JAPANESE;
@@ -40,14 +39,30 @@ UBool IdentifierInfo::cleanup() {
     KOREAN = NULL;
     delete CONFUSABLE_WITH_LATIN;
     CONFUSABLE_WITH_LATIN = NULL;
-    gStaticsAreInitialized = FALSE;
+    gIdentifierInfoInitOnce.reset(); 
     return TRUE;
 }
 
-U_CDECL_BEGIN
-static UBool U_CALLCONV
-IdentifierInfo_cleanup(void) {
-    return IdentifierInfo::cleanup();
+static void U_CALLCONV
+IdentifierInfo_init(UErrorCode &status) {
+    ASCII    = new UnicodeSet(0, 0x7f);
+    JAPANESE = new ScriptSet();
+    CHINESE  = new ScriptSet();
+    KOREAN   = new ScriptSet();
+    CONFUSABLE_WITH_LATIN = new ScriptSet();
+    if (ASCII == NULL || JAPANESE == NULL || CHINESE == NULL || KOREAN == NULL 
+            || CONFUSABLE_WITH_LATIN == NULL) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return;
+    }
+    ASCII->freeze();
+    JAPANESE->set(USCRIPT_LATIN, status).set(USCRIPT_HAN, status).set(USCRIPT_HIRAGANA, status)
+             .set(USCRIPT_KATAKANA, status);
+    CHINESE->set(USCRIPT_LATIN, status).set(USCRIPT_HAN, status).set(USCRIPT_BOPOMOFO, status);
+    KOREAN->set(USCRIPT_LATIN, status).set(USCRIPT_HAN, status).set(USCRIPT_HANGUL, status);
+    CONFUSABLE_WITH_LATIN->set(USCRIPT_CYRILLIC, status).set(USCRIPT_GREEK, status)
+              .set(USCRIPT_CHEROKEE, status);
+    ucln_i18n_registerCleanup(UCLN_I18N_IDENTIFIER_INFO, IdentifierInfo_cleanup);
 }
 U_CDECL_END
 
@@ -55,33 +70,11 @@ U_CDECL_END
 IdentifierInfo::IdentifierInfo(UErrorCode &status):
          fIdentifier(NULL), fRequiredScripts(NULL), fScriptSetSet(NULL), 
          fCommonAmongAlternates(NULL), fNumerics(NULL), fIdentifierProfile(NULL) {
+    umtx_initOnce(gIdentifierInfoInitOnce, &IdentifierInfo_init, status);
     if (U_FAILURE(status)) {
         return;
     }
-    {
-        Mutex lock(&gInitMutex);
-        if (!gStaticsAreInitialized) {
-            ASCII    = new UnicodeSet(0, 0x7f);
-            JAPANESE = new ScriptSet();
-            CHINESE  = new ScriptSet();
-            KOREAN   = new ScriptSet();
-            CONFUSABLE_WITH_LATIN = new ScriptSet();
-            if (ASCII == NULL || JAPANESE == NULL || CHINESE == NULL || KOREAN == NULL 
-                    || CONFUSABLE_WITH_LATIN == NULL) {
-                status = U_MEMORY_ALLOCATION_ERROR;
-                return;
-            }
-            ASCII->freeze();
-            JAPANESE->set(USCRIPT_LATIN, status).set(USCRIPT_HAN, status).set(USCRIPT_HIRAGANA, status)
-                     .set(USCRIPT_KATAKANA, status);
-            CHINESE->set(USCRIPT_LATIN, status).set(USCRIPT_HAN, status).set(USCRIPT_BOPOMOFO, status);
-            KOREAN->set(USCRIPT_LATIN, status).set(USCRIPT_HAN, status).set(USCRIPT_HANGUL, status);
-            CONFUSABLE_WITH_LATIN->set(USCRIPT_CYRILLIC, status).set(USCRIPT_GREEK, status)
-                      .set(USCRIPT_CHEROKEE, status);
-            ucln_i18n_registerCleanup(UCLN_I18N_IDENTIFIER_INFO, IdentifierInfo_cleanup);
-            gStaticsAreInitialized = TRUE;
-        }
-    }
+    
     fIdentifier = new UnicodeString();
     fRequiredScripts = new ScriptSet();
     fScriptSetSet = uhash_open(uhash_hashScriptSet, uhash_compareScriptSet, NULL, &status);
@@ -142,7 +135,7 @@ IdentifierInfo &IdentifierInfo::setIdentifier(const UnicodeString &identifier, U
             fNumerics->add(cp - (UChar32)u_getNumericValue(cp));
         }
         UScriptCode extensions[500];
-        int32_t extensionsCount = uscript_getScriptExtensions(cp, extensions, LENGTHOF(extensions), &status);
+        int32_t extensionsCount = uscript_getScriptExtensions(cp, extensions, UPRV_LENGTHOF(extensions), &status);
         if (U_FAILURE(status)) {
             return *this;
         }
@@ -174,7 +167,7 @@ IdentifierInfo &IdentifierInfo::setIdentifier(const UnicodeString &identifier, U
     // We also compute any commonalities among the alternates.
     if (uhash_count(fScriptSetSet) > 0) {
         fCommonAmongAlternates->setAll();
-        for (int32_t it = -1;;) {
+        for (int32_t it = UHASH_FIRST;;) {
             const UHashElement *nextHashEl = uhash_nextElement(fScriptSetSet, &it);
             if (nextHashEl == NULL) {
                 break;
@@ -186,7 +179,7 @@ IdentifierInfo &IdentifierInfo::setIdentifier(const UnicodeString &identifier, U
             } else {
                 fCommonAmongAlternates->intersect(*next);
                 // [[Arab Syrc Thaa]; [Arab Syrc]] => [[Arab Syrc]]
-                for (int32_t otherIt = -1;;) {
+                for (int32_t otherIt = UHASH_FIRST;;) {
                     const UHashElement *otherHashEl = uhash_nextElement(fScriptSetSet, &otherIt);
                     if (otherHashEl == NULL) {
                         break;
@@ -247,7 +240,7 @@ URestrictionLevel IdentifierInfo::getRestrictionLevel(UErrorCode &status) const
     int32_t cardinalityPlus = fRequiredScripts->countMembers() + 
             (fCommonAmongAlternates->countMembers() == 0 ? uhash_count(fScriptSetSet) : 1);
     if (cardinalityPlus < 2) {
-        return USPOOF_HIGHLY_RESTRICTIVE;
+        return USPOOF_SINGLE_SCRIPT_RESTRICTIVE;
     }
     if (containsWithAlternates(*JAPANESE, *fRequiredScripts) || containsWithAlternates(*CHINESE, *fRequiredScripts)
             || containsWithAlternates(*KOREAN, *fRequiredScripts)) {
@@ -276,7 +269,7 @@ UBool IdentifierInfo::containsWithAlternates(const ScriptSet &container, const S
     if (!container.contains(containee)) {
         return FALSE;
     }
-    for (int32_t iter = -1; ;) {
+    for (int32_t iter = UHASH_FIRST; ;) {
         const UHashElement *hashEl = uhash_nextElement(fScriptSetSet, &iter);
         if (hashEl == NULL) {
             break;
@@ -294,7 +287,7 @@ UnicodeString &IdentifierInfo::displayAlternates(UnicodeString &dest, const UHas
     if (U_FAILURE(status)) {
         return dest;
     }
-    for (int32_t pos = -1; ;) {
+    for (int32_t pos = UHASH_FIRST; ;) {
         const UHashElement *el = uhash_nextElement(alternates, &pos);
         if (el == NULL) {
             break;