/* get the UBiDiProps singleton, or else its dummy, once and for all */ static const UBiDiProps * getBiDiProps() { /* * This lazy intialization with double-checked locking (without mutex protection for * the initial check) is transiently unsafe under certain circumstances. * Check the readme and use u_init() if necessary. */ /* the initial check is performed by the GET_BIDI_PROPS() macro */ const UBiDiProps *bdp; UErrorCode errorCode=U_ZERO_ERROR; bdp=ubidi_getSingleton(&errorCode); #if !UBIDI_HARDCODE_DATA if(U_FAILURE(errorCode)) { errorCode=U_ZERO_ERROR; bdp=ubidi_getDummy(&errorCode); if(U_FAILURE(errorCode)) { return NULL; } } #endif umtx_lock(NULL); if(gBdp==NULL) { gBdp=bdp; ucln_common_registerCleanup(UCLN_COMMON_UPROPS, uprops_cleanup); } umtx_unlock(NULL); return gBdp; }
U_CAPI UChar32 U_EXPORT2 u_charMirror(UChar32 c) { UErrorCode errorCode=U_ZERO_ERROR; const UBiDiProps *bdp=ubidi_getSingleton(&errorCode); if(bdp!=NULL) { return ubidi_getMirror(bdp, c); } else { return c; } }
U_CAPI UCharDirection U_EXPORT2 u_charDirection(UChar32 c) { UErrorCode errorCode=U_ZERO_ERROR; const UBiDiProps *bdp=ubidi_getSingleton(&errorCode); if(bdp!=NULL) { return ubidi_getClass(bdp, c); } else { return U_LEFT_TO_RIGHT; } }
static UStringPrepProfile* usprep_getProfile(const char* path, const char* name, UErrorCode *status){ UStringPrepProfile* profile = NULL; initCache(status); if(U_FAILURE(*status)){ return NULL; } UStringPrepKey stackKey; /* * const is cast way to save malloc, strcpy and free calls * we use the passed in pointers for fetching the data from the * hash table which is safe */ stackKey.name = (char*) name; stackKey.path = (char*) path; /* fetch the data from the cache */ profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey)); if(profile == NULL){ UStringPrepKey* key = (UStringPrepKey*) uprv_malloc(sizeof(UStringPrepKey)); if(key == NULL){ *status = U_MEMORY_ALLOCATION_ERROR; return NULL; } /* else load the data and put the data in the cache */ profile = (UStringPrepProfile*) uprv_malloc(sizeof(UStringPrepProfile)); if(profile == 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); return NULL; } uprv_strcpy(key->name, name); key->path=NULL; if(path != NULL){ key->path = (char*) uprv_malloc(uprv_strlen(path)+1); if(key->path == NULL){ *status = U_MEMORY_ALLOCATION_ERROR; uprv_free(key->path); uprv_free(key); uprv_free(profile); return NULL; } uprv_strcpy(key->path, path); } /* load the data */ if(!loadData(profile, path, name, _SPREP_DATA_TYPE, status) || U_FAILURE(*status) ){ 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); 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); umtx_unlock(&usprepMutex); } umtx_lock(&usprepMutex); /* increment the refcount */ profile->refCount++; umtx_unlock(&usprepMutex); return profile; }
/* * This function shapes European digits to Arabic-Indic digits * in-place, writing over the input characters. * Since we know that we are only looking for BMP code points, * we can safely just work with code units (again, at least UTF-16). */ static void _shapeToArabicDigitsWithContext(UChar *s, int32_t length, UChar digitBase, UBool isLogical, UBool lastStrongWasAL) { const UBiDiProps *bdp; UErrorCode errorCode; int32_t i; UChar c; errorCode=U_ZERO_ERROR; bdp=ubidi_getSingleton(&errorCode); if(U_FAILURE(errorCode)) { return; } digitBase-=0x30; /* the iteration direction depends on the type of input */ if(isLogical) { for(i=0; i<length; ++i) { c=s[i]; switch(ubidi_getClass(bdp, c)) { case U_LEFT_TO_RIGHT: /* L */ case U_RIGHT_TO_LEFT: /* R */ lastStrongWasAL=FALSE; break; case U_RIGHT_TO_LEFT_ARABIC: /* AL */ lastStrongWasAL=TRUE; break; case U_EUROPEAN_NUMBER: /* EN */ if(lastStrongWasAL && (uint32_t)(c-0x30)<10) { s[i]=(UChar)(digitBase+c); /* digitBase+(c-0x30) - digitBase was modified above */ } break; default : break; } } } else { for(i=length; i>0; /* pre-decrement in the body */) { c=s[--i]; switch(ubidi_getClass(bdp, c)) { case U_LEFT_TO_RIGHT: /* L */ case U_RIGHT_TO_LEFT: /* R */ lastStrongWasAL=FALSE; break; case U_RIGHT_TO_LEFT_ARABIC: /* AL */ lastStrongWasAL=TRUE; break; case U_EUROPEAN_NUMBER: /* EN */ if(lastStrongWasAL && (uint32_t)(c-0x30)<10) { s[i]=(UChar)(digitBase+c); /* digitBase+(c-0x30) - digitBase was modified above */ } break; default : break; } } } }
U_CDECL_END U_NAMESPACE_BEGIN /* Reduce excessive reallocation, and make it easier to detect initialization problems. Usually you don't see smaller sets than this for Unicode 5.0. */ #define DEFAULT_INCLUSION_CAPACITY 3072 void U_CALLCONV UnicodeSet_initInclusion(int32_t src, UErrorCode &status) { // This function is invoked only via umtx_initOnce(). // This function is a friend of class UnicodeSet. U_ASSERT(src >=0 && src<UPROPS_SRC_COUNT); UnicodeSet * &incl = gInclusions[src].fSet; U_ASSERT(incl == NULL); incl = new UnicodeSet(); if (incl == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return; } USetAdder sa = { (USet *)incl, _set_add, _set_addRange, _set_addString, NULL, // don't need remove() NULL // don't need removeRange() }; incl->ensureCapacity(DEFAULT_INCLUSION_CAPACITY, status); switch(src) { case UPROPS_SRC_CHAR: uchar_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_PROPSVEC: upropsvec_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_CHAR_AND_PROPSVEC: uchar_addPropertyStarts(&sa, &status); upropsvec_addPropertyStarts(&sa, &status); break; #if !UCONFIG_NO_NORMALIZATION case UPROPS_SRC_CASE_AND_NORM: { const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(status); if(U_SUCCESS(status)) { impl->addPropertyStarts(&sa, status); } ucase_addPropertyStarts(&sa, &status); break; } case UPROPS_SRC_NFC: { const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(status); if(U_SUCCESS(status)) { impl->addPropertyStarts(&sa, status); } break; } case UPROPS_SRC_NFKC: { const Normalizer2Impl *impl=Normalizer2Factory::getNFKCImpl(status); if(U_SUCCESS(status)) { impl->addPropertyStarts(&sa, status); } break; } case UPROPS_SRC_NFKC_CF: { const Normalizer2Impl *impl=Normalizer2Factory::getNFKC_CFImpl(status); if(U_SUCCESS(status)) { impl->addPropertyStarts(&sa, status); } break; } case UPROPS_SRC_NFC_CANON_ITER: { const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(status); if(U_SUCCESS(status)) { impl->addCanonIterPropertyStarts(&sa, status); } break; } #endif case UPROPS_SRC_CASE: ucase_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_BIDI: ubidi_addPropertyStarts(ubidi_getSingleton(), &sa, &status); break; default: status = U_INTERNAL_PROGRAM_ERROR; break; } if (U_FAILURE(status)) { delete incl; incl = NULL; return; } // Compact for caching incl->compact(); ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup); }
U_CDECL_END U_NAMESPACE_BEGIN /* Reduce excessive reallocation, and make it easier to detect initialization problems. Usually you don't see smaller sets than this for Unicode 5.0. */ #define DEFAULT_INCLUSION_CAPACITY 3072 const UnicodeSet* UnicodeSet::getInclusions(int32_t src, UErrorCode &status) { UBool needInit; UMTX_CHECK(NULL, (INCLUSIONS[src] == NULL), needInit); if (needInit) { UnicodeSet* incl = new UnicodeSet(); USetAdder sa = { (USet *)incl, _set_add, _set_addRange, _set_addString, NULL, // don't need remove() NULL // don't need removeRange() }; incl->ensureCapacity(DEFAULT_INCLUSION_CAPACITY, status); if (incl != NULL) { switch(src) { case UPROPS_SRC_CHAR: uchar_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_PROPSVEC: upropsvec_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_CHAR_AND_PROPSVEC: uchar_addPropertyStarts(&sa, &status); upropsvec_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_HST: uhst_addPropertyStarts(&sa, &status); break; #if !UCONFIG_NO_NORMALIZATION case UPROPS_SRC_NORM: unorm_addPropertyStarts(&sa, &status); break; #endif case UPROPS_SRC_CASE: ucase_addPropertyStarts(ucase_getSingleton(&status), &sa, &status); break; case UPROPS_SRC_BIDI: ubidi_addPropertyStarts(ubidi_getSingleton(&status), &sa, &status); break; default: status = U_INTERNAL_PROGRAM_ERROR; break; } if (U_SUCCESS(status)) { // Compact for caching incl->compact(); umtx_lock(NULL); if (INCLUSIONS[src] == NULL) { INCLUSIONS[src] = incl; incl = NULL; ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup); } umtx_unlock(NULL); } delete incl; } else { status = U_MEMORY_ALLOCATION_ERROR; } } return INCLUSIONS[src]; }
static UStringPrepProfile* usprep_getProfile(const char* path, const char* name, UErrorCode *status){ UStringPrepProfile* profile = NULL; initCache(status); if(U_FAILURE(*status)){ return NULL; } UStringPrepKey stackKey; /* * const is cast way to save malloc, strcpy and free calls * we use the passed in pointers for fetching the data from the * hash table which is safe */ stackKey.name = (char*) name; stackKey.path = (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) { /* else load the data and put the data in the cache */ LocalMemory<UStringPrepProfile> newProfile; if(newProfile.allocateInsteadAndReset() == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; return NULL; } /* load the data */ if(!loadData(newProfile.getAlias(), path, name, _SPREP_DATA_TYPE, status) || U_FAILURE(*status) ){ return 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(newProfile->checkBiDi) { newProfile->bdp = ubidi_getSingleton(); } 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; } umtx_lock(&usprepMutex); // 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); } return profile; }
U_CDECL_END U_NAMESPACE_BEGIN #define DEFAULT_INCLUSION_CAPACITY 3072 const UnicodeSet* UnicodeSet::getInclusions(int32_t src, UErrorCode &status) { UBool needInit; UMTX_CHECK(NULL, (INCLUSIONS[src] == NULL), needInit); if (needInit) { UnicodeSet* incl = new UnicodeSet(); USetAdder sa = { (USet *)incl, _set_add, _set_addRange, _set_addString, NULL, // don't need remove() NULL // don't need removeRange() }; incl->ensureCapacity(DEFAULT_INCLUSION_CAPACITY, status); if (incl != NULL) { switch(src) { case UPROPS_SRC_CHAR: uchar_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_PROPSVEC: upropsvec_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_CHAR_AND_PROPSVEC: uchar_addPropertyStarts(&sa, &status); upropsvec_addPropertyStarts(&sa, &status); break; #if !UCONFIG_NO_NORMALIZATION case UPROPS_SRC_NORM: unorm_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_CASE_AND_NORM: ucase_addPropertyStarts(ucase_getSingleton(&status), &sa, &status); unorm_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_NFC: { const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(status); if(U_SUCCESS(status)) { impl->addPropertyStarts(&sa, status); } break; } case UPROPS_SRC_NFKC: { const Normalizer2Impl *impl=Normalizer2Factory::getNFKCImpl(status); if(U_SUCCESS(status)) { impl->addPropertyStarts(&sa, status); } break; } case UPROPS_SRC_NFKC_CF: { const Normalizer2Impl *impl=Normalizer2Factory::getNFKC_CFImpl(status); if(U_SUCCESS(status)) { impl->addPropertyStarts(&sa, status); } break; } #endif case UPROPS_SRC_CASE: ucase_addPropertyStarts(ucase_getSingleton(&status), &sa, &status); break; case UPROPS_SRC_BIDI: ubidi_addPropertyStarts(ubidi_getSingleton(&status), &sa, &status); break; default: status = U_INTERNAL_PROGRAM_ERROR; break; } if (U_SUCCESS(status)) { // Compact for caching incl->compact(); umtx_lock(NULL); if (INCLUSIONS[src] == NULL) { INCLUSIONS[src] = incl; incl = NULL; ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup); } umtx_unlock(NULL); } delete incl; } else { status = U_MEMORY_ALLOCATION_ERROR; } } return INCLUSIONS[src]; }
U_CAPI UBool U_EXPORT2 u_isMirrored(UChar32 c) { UErrorCode errorCode=U_ZERO_ERROR; const UBiDiProps *bdp=ubidi_getSingleton(&errorCode); return (UBool)(bdp!=NULL && ubidi_isMirrored(bdp, c)); }
U_CDECL_END const UnicodeSet* UnicodeSet::getInclusions(int32_t src, UErrorCode &status) { umtx_lock(NULL); UBool f = (INCLUSIONS[src] == NULL); umtx_unlock(NULL); if (f) { UnicodeSet* incl = new UnicodeSet(); USetAdder sa = { (USet *)incl, _set_add, _set_addRange, _set_addString, NULL // don't need remove() }; if (incl != NULL) { switch(src) { case UPROPS_SRC_CHAR: uchar_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_PROPSVEC: upropsvec_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_CHAR_AND_PROPSVEC: uchar_addPropertyStarts(&sa, &status); upropsvec_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_HST: uhst_addPropertyStarts(&sa, &status); break; #if !UCONFIG_NO_NORMALIZATION case UPROPS_SRC_NORM: unorm_addPropertyStarts(&sa, &status); break; #endif case UPROPS_SRC_CASE: ucase_addPropertyStarts(ucase_getSingleton(&status), &sa, &status); break; case UPROPS_SRC_BIDI: ubidi_addPropertyStarts(ubidi_getSingleton(&status), &sa, &status); break; default: status = U_INTERNAL_PROGRAM_ERROR; break; } if (U_SUCCESS(status)) { umtx_lock(NULL); if (INCLUSIONS[src] == NULL) { INCLUSIONS[src] = incl; incl = NULL; ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup); } umtx_unlock(NULL); } delete incl; } else { status = U_MEMORY_ALLOCATION_ERROR; } } return INCLUSIONS[src]; }