X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/73c04bcfe1096173b00431f0cdc742894b15eef0..b25be06635768807f8f693286fa73bb2297bb06c:/icuSources/common/usprep.cpp diff --git a/icuSources/common/usprep.cpp b/icuSources/common/usprep.cpp index ec98ad01..415253c3 100644 --- a/icuSources/common/usprep.cpp +++ b/icuSources/common/usprep.cpp @@ -1,7 +1,7 @@ /* ******************************************************************************* * - * Copyright (C) 2003-2006, International Business Machines + * Copyright (C) 2003-2010, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* @@ -32,9 +32,10 @@ #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 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 key; + LocalMemory keyName; + LocalMemory 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); }