]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/ucnv_io.cpp
ICU-531.30.tar.gz
[apple/icu.git] / icuSources / common / ucnv_io.cpp
index 12d2b63f0d8cbbf551e7928305425335cfabccfa..5dd35d8a7026ef4ceb80027b3fd3a7cca3e7e9b4 100644 (file)
@@ -1,7 +1,7 @@
 /*
 ******************************************************************************
 *
-*   Copyright (C) 1999-2012, International Business Machines
+*   Copyright (C) 1999-2013, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 ******************************************************************************
@@ -36,6 +36,7 @@
 
 #include "umutex.h"
 #include "uarrsort.h"
+#include "uassert.h"
 #include "udataswp.h"
 #include "cstring.h"
 #include "cmemory.h"
@@ -172,6 +173,7 @@ static const char DATA_NAME[] = "cnvalias";
 static const char DATA_TYPE[] = "icu";
 
 static UDataMemory *gAliasData=NULL;
+static icu::UInitOnce gAliasDataInitOnce = U_INITONCE_INITIALIZER;
 
 enum {
     tocLengthIndex=0,
@@ -218,113 +220,97 @@ static UBool U_CALLCONV ucnv_io_cleanup(void)
         udata_close(gAliasData);
         gAliasData = NULL;
     }
+    gAliasDataInitOnce.reset();
 
     uprv_memset(&gMainTable, 0, sizeof(gMainTable));
 
     return TRUE;                   /* Everything was cleaned up */
 }
 
-static UBool
-haveAliasData(UErrorCode *pErrorCode) {
-    int needInit;
-
-    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
-        return FALSE;
-    }
+static void U_CALLCONV initAliasData(UErrorCode &errCode) {
+    UDataMemory *data;
+    const uint16_t *table;
+    const uint32_t *sectionSizes;
+    uint32_t tableStart;
+    uint32_t currOffset;
 
-    UMTX_CHECK(NULL, (gAliasData==NULL), needInit);
+    ucln_common_registerCleanup(UCLN_COMMON_UCNV_IO, ucnv_io_cleanup);
 
-    /* load converter alias data from file if necessary */
-    if (needInit) {
-        UDataMemory *data;
-        const uint16_t *table;
-        const uint32_t *sectionSizes;
-        uint32_t tableStart;
-        uint32_t currOffset;
-
-        data = udata_openChoice(NULL, DATA_TYPE, DATA_NAME, isAcceptable, NULL, pErrorCode);
-        if(U_FAILURE(*pErrorCode)) {
-            return FALSE;
-        }
-
-        sectionSizes = (const uint32_t *)udata_getMemory(data);
-        table = (const uint16_t *)sectionSizes;
-
-        tableStart      = sectionSizes[0];
-        if (tableStart < minTocLength) {
-            *pErrorCode = U_INVALID_FORMAT_ERROR;
-            udata_close(data);
-            return FALSE;
-        }
-
-        umtx_lock(NULL);
-        if(gAliasData==NULL) {
-            gMainTable.converterListSize      = sectionSizes[1];
-            gMainTable.tagListSize            = sectionSizes[2];
-            gMainTable.aliasListSize          = sectionSizes[3];
-            gMainTable.untaggedConvArraySize  = sectionSizes[4];
-            gMainTable.taggedAliasArraySize   = sectionSizes[5];
-            gMainTable.taggedAliasListsSize   = sectionSizes[6];
-            gMainTable.optionTableSize        = sectionSizes[7];
-            gMainTable.stringTableSize        = sectionSizes[8];
-
-            if (tableStart > 8) {
-                gMainTable.normalizedStringTableSize = sectionSizes[9];
-            }
+    U_ASSERT(gAliasData == NULL);
+    data = udata_openChoice(NULL, DATA_TYPE, DATA_NAME, isAcceptable, NULL, &errCode);
+    if(U_FAILURE(errCode)) {
+        return;
+    }
 
-            currOffset = tableStart * (sizeof(uint32_t)/sizeof(uint16_t)) + (sizeof(uint32_t)/sizeof(uint16_t));
-            gMainTable.converterList = table + currOffset;
+    sectionSizes = (const uint32_t *)udata_getMemory(data);
+    table = (const uint16_t *)sectionSizes;
 
-            currOffset += gMainTable.converterListSize;
-            gMainTable.tagList = table + currOffset;
+    tableStart      = sectionSizes[0];
+    if (tableStart < minTocLength) {
+        errCode = U_INVALID_FORMAT_ERROR;
+        udata_close(data);
+        return;
+    }
+    gAliasData = data;
+
+    gMainTable.converterListSize      = sectionSizes[1];
+    gMainTable.tagListSize            = sectionSizes[2];
+    gMainTable.aliasListSize          = sectionSizes[3];
+    gMainTable.untaggedConvArraySize  = sectionSizes[4];
+    gMainTable.taggedAliasArraySize   = sectionSizes[5];
+    gMainTable.taggedAliasListsSize   = sectionSizes[6];
+    gMainTable.optionTableSize        = sectionSizes[7];
+    gMainTable.stringTableSize        = sectionSizes[8];
+
+    if (tableStart > 8) {
+        gMainTable.normalizedStringTableSize = sectionSizes[9];
+    }
 
-            currOffset += gMainTable.tagListSize;
-            gMainTable.aliasList = table + currOffset;
+    currOffset = tableStart * (sizeof(uint32_t)/sizeof(uint16_t)) + (sizeof(uint32_t)/sizeof(uint16_t));
+    gMainTable.converterList = table + currOffset;
 
-            currOffset += gMainTable.aliasListSize;
-            gMainTable.untaggedConvArray = table + currOffset;
+    currOffset += gMainTable.converterListSize;
+    gMainTable.tagList = table + currOffset;
 
-            currOffset += gMainTable.untaggedConvArraySize;
-            gMainTable.taggedAliasArray = table + currOffset;
+    currOffset += gMainTable.tagListSize;
+    gMainTable.aliasList = table + currOffset;
 
-            /* aliasLists is a 1's based array, but it has a padding character */
-            currOffset += gMainTable.taggedAliasArraySize;
-            gMainTable.taggedAliasLists = table + currOffset;
+    currOffset += gMainTable.aliasListSize;
+    gMainTable.untaggedConvArray = table + currOffset;
 
-            currOffset += gMainTable.taggedAliasListsSize;
-            if (gMainTable.optionTableSize > 0
-                && ((const UConverterAliasOptions *)(table + currOffset))->stringNormalizationType < UCNV_IO_NORM_TYPE_COUNT)
-            {
-                /* Faster table */
-                gMainTable.optionTable = (const UConverterAliasOptions *)(table + currOffset);
-            }
-            else {
-                /* Smaller table, or I can't handle this normalization mode!
-                Use the original slower table lookup. */
-                gMainTable.optionTable = &defaultTableOptions;
-            }
+    currOffset += gMainTable.untaggedConvArraySize;
+    gMainTable.taggedAliasArray = table + currOffset;
 
-            currOffset += gMainTable.optionTableSize;
-            gMainTable.stringTable = table + currOffset;
+    /* aliasLists is a 1's based array, but it has a padding character */
+    currOffset += gMainTable.taggedAliasArraySize;
+    gMainTable.taggedAliasLists = table + currOffset;
 
-            currOffset += gMainTable.stringTableSize;
-            gMainTable.normalizedStringTable = ((gMainTable.optionTable->stringNormalizationType == UCNV_IO_UNNORMALIZED)
-                ? gMainTable.stringTable : (table + currOffset));
+    currOffset += gMainTable.taggedAliasListsSize;
+    if (gMainTable.optionTableSize > 0
+        && ((const UConverterAliasOptions *)(table + currOffset))->stringNormalizationType < UCNV_IO_NORM_TYPE_COUNT)
+    {
+        /* Faster table */
+        gMainTable.optionTable = (const UConverterAliasOptions *)(table + currOffset);
+    }
+    else {
+        /* Smaller table, or I can't handle this normalization mode!
+        Use the original slower table lookup. */
+        gMainTable.optionTable = &defaultTableOptions;
+    }
 
-            ucln_common_registerCleanup(UCLN_COMMON_UCNV_IO, ucnv_io_cleanup);
+    currOffset += gMainTable.optionTableSize;
+    gMainTable.stringTable = table + currOffset;
 
-            gAliasData = data;
-            data=NULL;
-        }
-        umtx_unlock(NULL);
+    currOffset += gMainTable.stringTableSize;
+    gMainTable.normalizedStringTable = ((gMainTable.optionTable->stringNormalizationType == UCNV_IO_UNNORMALIZED)
+        ? gMainTable.stringTable : (table + currOffset));
+}
 
-        /* if a different thread set it first, then close the extra data */
-        if(data!=NULL) {
-            udata_close(data); /* NULL if it was set correctly */
-        }
-    }
 
-    return TRUE;
+static UBool
+haveAliasData(UErrorCode *pErrorCode) {
+    umtx_initOnce(gAliasDataInitOnce, &initAliasData, *pErrorCode);
+    return U_SUCCESS(*pErrorCode);
 }
 
 static inline UBool
@@ -351,7 +337,7 @@ static uint32_t getTagNumber(const char *tagname) {
 
 /* character types relevant for ucnv_compareNames() */
 enum {
-    IGNORE,
+    UIGNORE,
     ZERO,
     NONZERO,
     MINLETTER /* any values from here on are lowercase letter mappings */
@@ -369,7 +355,7 @@ static const uint8_t asciiTypes[128] = {
     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0, 0, 0, 0, 0
 };
 
-#define GET_ASCII_TYPE(c) ((int8_t)(c) >= 0 ? asciiTypes[(uint8_t)c] : (uint8_t)IGNORE)
+#define GET_ASCII_TYPE(c) ((int8_t)(c) >= 0 ? asciiTypes[(uint8_t)c] : (uint8_t)UIGNORE)
 
 /* character types for EBCDIC 80..FF */
 static const uint8_t ebcdicTypes[128] = {
@@ -383,7 +369,7 @@ static const uint8_t ebcdicTypes[128] = {
     ZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, 0, 0, 0, 0, 0, 0
 };
 
-#define GET_EBCDIC_TYPE(c) ((int8_t)(c) < 0 ? ebcdicTypes[(c)&0x7f] : (uint8_t)IGNORE)
+#define GET_EBCDIC_TYPE(c) ((int8_t)(c) < 0 ? ebcdicTypes[(c)&0x7f] : (uint8_t)UIGNORE)
 
 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
 #   define GET_CHAR_TYPE(c) GET_ASCII_TYPE(c)
@@ -404,7 +390,7 @@ ucnv_io_stripASCIIForCompare(char *dst, const char *name) {
     while ((c1 = *name++) != 0) {
         type = GET_ASCII_TYPE(c1);
         switch (type) {
-        case IGNORE:
+        case UIGNORE:
             afterDigit = FALSE;
             continue; /* ignore all but letters and digits */
         case ZERO:
@@ -439,7 +425,7 @@ ucnv_io_stripEBCDICForCompare(char *dst, const char *name) {
     while ((c1 = *name++) != 0) {
         type = GET_EBCDIC_TYPE(c1);
         switch (type) {
-        case IGNORE:
+        case UIGNORE:
             afterDigit = FALSE;
             continue; /* ignore all but letters and digits */
         case ZERO:
@@ -496,7 +482,7 @@ ucnv_compareNames(const char *name1, const char *name2) {
         while ((c1 = *name1++) != 0) {
             type = GET_CHAR_TYPE(c1);
             switch (type) {
-            case IGNORE:
+            case UIGNORE:
                 afterDigit1 = FALSE;
                 continue; /* ignore all but letters and digits */
             case ZERO:
@@ -520,7 +506,7 @@ ucnv_compareNames(const char *name1, const char *name2) {
         while ((c2 = *name2++) != 0) {
             type = GET_CHAR_TYPE(c2);
             switch (type) {
-            case IGNORE:
+            case UIGNORE:
                 afterDigit2 = FALSE;
                 continue; /* ignore all but letters and digits */
             case ZERO:
@@ -1350,6 +1336,7 @@ ucnv_swapAliases(const UDataSwapper *ds,
 
 #endif
 
+
 /*
  * Hey, Emacs, please set the following:
  *