]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/usprep.cpp
ICU-461.18.tar.gz
[apple/icu.git] / icuSources / common / usprep.cpp
index ec98ad01187a4918ce71ef1d53b64a2bc2cf1f98..415253c332e31277d29873f41f0da0a3e47a4558 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *******************************************************************************
  *
- *   Copyright (C) 2003-2006, International Business Machines
+ *   Copyright (C) 2003-2010, International Business Machines
  *   Corporation and others.  All Rights Reserved.
  *
  *******************************************************************************
 #include "cstring.h"
 #include "udataswp.h"
 #include "ucln_cmn.h"
-#include "unormimp.h"
 #include "ubidi_props.h"
 
+U_NAMESPACE_USE
+
 U_CDECL_BEGIN
 
 /*
@@ -50,6 +51,24 @@ static uint8_t formatVersion[4]={ 0, 0, 0, 0 };
 /* the Unicode version of the sprep data */
 static UVersionInfo dataVersion={ 0, 0, 0, 0 };
 
+/* Profile names must be aligned to UStringPrepProfileType */
+static const char *PROFILE_NAMES[] = {
+    "rfc3491",      /* USPREP_RFC3491_NAMEPREP */
+    "rfc3530cs",    /* USPREP_RFC3530_NFS4_CS_PREP */
+    "rfc3530csci",  /* USPREP_RFC3530_NFS4_CS_PREP_CI */
+    "rfc3491",      /* USPREP_RFC3530_NSF4_CIS_PREP */
+    "rfc3530mixp",  /* USPREP_RFC3530_NSF4_MIXED_PREP_PREFIX */
+    "rfc3491",      /* USPREP_RFC3530_NSF4_MIXED_PREP_SUFFIX */
+    "rfc3722",      /* USPREP_RFC3722_ISCSI */
+    "rfc3920node",  /* USPREP_RFC3920_NODEPREP */
+    "rfc3920res",   /* USPREP_RFC3920_RESOURCEPREP */
+    "rfc4011",      /* USPREP_RFC4011_MIB */
+    "rfc4013",      /* USPREP_RFC4013_SASLPREP */
+    "rfc4505",      /* USPREP_RFC4505_TRACE */
+    "rfc4518",      /* USPREP_RFC4518_LDAP */
+    "rfc4518ci",    /* USPREP_RFC4518_LDAP_CI */
+};
+
 static UBool U_CALLCONV
 isSPrepAcceptable(void * /* context */,
              const char * /* type */, 
@@ -184,18 +203,12 @@ static UBool U_CALLCONV usprep_cleanup(void){
 }
 U_CDECL_END
 
-static void 
-usprep_init() {
-    umtx_init(&usprepMutex);
-}
 
 /** Initializes the cache for resources */
 static void 
 initCache(UErrorCode *status) {
-    UBool makeCache = FALSE;
-    umtx_lock(&usprepMutex);
-    makeCache = (SHARED_DATA_HASHTABLE ==  NULL);
-    umtx_unlock(&usprepMutex);
+    UBool makeCache;
+    UMTX_CHECK(&usprepMutex, (SHARED_DATA_HASHTABLE ==  NULL), makeCache);
     if(makeCache) {
         UHashtable *newCache = uhash_open(hashEntry, compareEntries, NULL, status);
         if (U_SUCCESS(*status)) {
@@ -206,9 +219,9 @@ initCache(UErrorCode *status) {
                 newCache = NULL;
             }
             umtx_unlock(&usprepMutex);
-            if(newCache != NULL) {
-                uhash_close(newCache);
-            }
+        }
+        if(newCache != NULL) {
+            uhash_close(newCache);
         }
     }
 }
@@ -263,7 +276,7 @@ loadData(UStringPrepProfile* profile,
     /* initialize some variables */
     profile->mappingData=(uint16_t *)((uint8_t *)(p+_SPREP_INDEX_TOP)+profile->indexes[_SPREP_INDEX_TRIE_SIZE]);
     
-    unorm_getUnicodeVersion(&normUnicodeVersion, errorCode);
+    u_getUnicodeVersion(normUnicodeVersion);
     normUniVer = (normUnicodeVersion[0] << 24) + (normUnicodeVersion[1] << 16) + 
                  (normUnicodeVersion[2] << 8 ) + (normUnicodeVersion[3]);
     sprepUniVer = (dataVersion[0] << 24) + (dataVersion[1] << 16) + 
@@ -318,89 +331,68 @@ usprep_getProfile(const char* path,
     /* fetch the data from the cache */
     umtx_lock(&usprepMutex);
     profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey));
+    if(profile != NULL) {
+        profile->refCount++;
+    }
     umtx_unlock(&usprepMutex);
     
-    if(profile == NULL){
-        UStringPrepKey* key   = (UStringPrepKey*) uprv_malloc(sizeof(UStringPrepKey));
-        if(key == NULL){
-            *status = U_MEMORY_ALLOCATION_ERROR;
-            return NULL;
-        }
+    if(profile == NULL) {
         /* else load the data and put the data in the cache */
-        profile = (UStringPrepProfile*) uprv_malloc(sizeof(UStringPrepProfile));
-        if(profile == NULL){
+        LocalMemory<UStringPrepProfile> newProfile;
+        if(newProfile.allocateInsteadAndReset() == NULL) {
             *status = U_MEMORY_ALLOCATION_ERROR;
-            uprv_free(key);
             return NULL;
         }
 
-        /* initialize the data struct members */
-        uprv_memset(profile->indexes,0,sizeof(profile->indexes));
-        profile->mappingData = NULL;
-        profile->sprepData   = NULL;
-        profile->refCount    = 0;
-    
-        /* initialize the  key memebers */
-        key->name  = (char*) uprv_malloc(uprv_strlen(name)+1);
-        if(key->name == NULL){
-            *status = U_MEMORY_ALLOCATION_ERROR;
-            uprv_free(key);
-            uprv_free(profile);
+        /* load the data */
+        if(!loadData(newProfile.getAlias(), path, name, _SPREP_DATA_TYPE, status) || U_FAILURE(*status) ){
             return NULL;
         }
 
-        uprv_strcpy(key->name, name);
-        
-        key->path=NULL;
+        /* get the options */
+        newProfile->doNFKC = (UBool)((newProfile->indexes[_SPREP_OPTIONS] & _SPREP_NORMALIZATION_ON) > 0);
+        newProfile->checkBiDi = (UBool)((newProfile->indexes[_SPREP_OPTIONS] & _SPREP_CHECK_BIDI_ON) > 0);
 
-        if(path != NULL){
-            key->path      = (char*) uprv_malloc(uprv_strlen(path)+1);
-            if(key->path == NULL){
-                *status = U_MEMORY_ALLOCATION_ERROR;
-                uprv_free(key->name);
-                uprv_free(key);
-                uprv_free(profile);
-                return NULL;
-            }
-            uprv_strcpy(key->path, path);
-        }        
+        if(newProfile->checkBiDi) {
+            newProfile->bdp = ubidi_getSingleton();
+        }
 
-        /* load the data */
-        if(!loadData(profile, path, name, _SPREP_DATA_TYPE, status) || U_FAILURE(*status) ){
-            uprv_free(key->path);
-            uprv_free(key->name);
-            uprv_free(key);
-            uprv_free(profile);
+        LocalMemory<UStringPrepKey> key;
+        LocalMemory<char> keyName;
+        LocalMemory<char> keyPath;
+        if( key.allocateInsteadAndReset() == NULL ||
+            keyName.allocateInsteadAndCopy(uprv_strlen(name)+1) == NULL ||
+            (path != NULL &&
+             keyPath.allocateInsteadAndCopy(uprv_strlen(path)+1) == NULL)
+         ) {
+            *status = U_MEMORY_ALLOCATION_ERROR;
+            usprep_unload(newProfile.getAlias());
             return NULL;
         }
-        
-        /* get the options */
-        profile->doNFKC            = (UBool)((profile->indexes[_SPREP_OPTIONS] & _SPREP_NORMALIZATION_ON) > 0);
-        profile->checkBiDi         = (UBool)((profile->indexes[_SPREP_OPTIONS] & _SPREP_CHECK_BIDI_ON) > 0);
 
-        if(profile->checkBiDi) {
-            profile->bdp = ubidi_getSingleton(status);
-            if(U_FAILURE(*status)) {
-                usprep_unload(profile);
-                uprv_free(key->path);
-                uprv_free(key->name);
-                uprv_free(key);
-                uprv_free(profile);
-                return NULL;
-            }
-        } else {
-            profile->bdp = NULL;
-        }
-        
         umtx_lock(&usprepMutex);
-        /* add the data object to the cache */
-        uhash_put(SHARED_DATA_HASHTABLE, key, profile, status);
+        // If another thread already inserted the same key/value, refcount and cleanup our thread data
+        profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey));
+        if(profile != NULL) {
+            profile->refCount++;
+            usprep_unload(newProfile.getAlias());
+        }
+        else {
+            /* initialize the key members */
+            key->name = keyName.orphan();
+            uprv_strcpy(key->name, name);
+            if(path != NULL){
+                key->path = keyPath.orphan();
+                uprv_strcpy(key->path, path);
+            }        
+            profile = newProfile.orphan();
+    
+            /* add the data object to the cache */
+            profile->refCount = 1;
+            uhash_put(SHARED_DATA_HASHTABLE, key.orphan(), profile, status);
+        }
         umtx_unlock(&usprepMutex);
     }
-    umtx_lock(&usprepMutex);
-    /* increment the refcount */
-    profile->refCount++;
-    umtx_unlock(&usprepMutex);
 
     return profile;
 }
@@ -413,13 +405,25 @@ usprep_open(const char* path,
     if(status == NULL || U_FAILURE(*status)){
         return NULL;
     }
-    /* initialize the mutex */
-    usprep_init();
        
     /* initialize the profile struct members */
     return usprep_getProfile(path,name,status);
 }
 
+U_CAPI UStringPrepProfile* U_EXPORT2
+usprep_openByType(UStringPrepProfileType type,
+                                 UErrorCode* status) {
+    if(status == NULL || U_FAILURE(*status)){
+        return NULL;
+    }
+    int32_t index = (int32_t)type;
+    if (index < 0 || index >= (int32_t)(sizeof(PROFILE_NAMES)/sizeof(PROFILE_NAMES[0]))) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return NULL;
+    }
+    return usprep_open(NULL, PROFILE_NAMES[index], status);
+}
+
 U_CAPI void U_EXPORT2
 usprep_close(UStringPrepProfile* profile){
     if(profile==NULL){
@@ -447,7 +451,7 @@ uprv_syntaxError(const UChar* rules,
     parseError->line = 0 ; // we are not using line numbers 
     
     // for pre-context
-    int32_t start = (pos <=U_PARSE_CONTEXT_LEN)? 0 : (pos - (U_PARSE_CONTEXT_LEN-1));
+    int32_t start = (pos < U_PARSE_CONTEXT_LEN)? 0 : (pos - (U_PARSE_CONTEXT_LEN-1));
     int32_t limit = pos;
     
     u_memcpy(parseError->preContext,rules+start,limit-start);
@@ -608,20 +612,9 @@ static int32_t
 usprep_normalize(   const UChar* src, int32_t srcLength, 
                     UChar* dest, int32_t destCapacity,
                     UErrorCode* status ){
-    /*
-     * Option UNORM_BEFORE_PRI_29:
-     *
-     * IDNA as interpreted by IETF members (see unicode mailing list 2004H1)
-     * requires strict adherence to Unicode 3.2 normalization,
-     * including buggy composition from before fixing Public Review Issue #29.
-     * Note that this results in some valid but nonsensical text to be
-     * either corrupted or rejected, depending on the text.
-     * See http://www.unicode.org/review/resolved-pri.html#pri29
-     * See unorm.cpp and cnormtst.c
-     */
     return unorm_normalize(
         src, srcLength,
-        UNORM_NFKC, UNORM_UNICODE_3_2|UNORM_BEFORE_PRI_29,
+        UNORM_NFKC, UNORM_UNICODE_3_2,
         dest, destCapacity,
         status);
 }