X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/729e4ab9bc6618bc3d8a898e575df7f4019e29ca..ef6cf650f4a75c3f97de06b51fa104f2069b9ea2:/icuSources/common/normalizer2.cpp diff --git a/icuSources/common/normalizer2.cpp b/icuSources/common/normalizer2.cpp index fd0048c5..c345c06e 100644 --- a/icuSources/common/normalizer2.cpp +++ b/icuSources/common/normalizer2.cpp @@ -1,7 +1,7 @@ /* ******************************************************************************* * -* Copyright (C) 2009-2010, International Business Machines +* Copyright (C) 2009-2016, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* @@ -18,23 +18,47 @@ #if !UCONFIG_NO_NORMALIZATION -#include "unicode/localpointer.h" #include "unicode/normalizer2.h" #include "unicode/unistr.h" #include "unicode/unorm.h" -#include "cpputils.h" #include "cstring.h" #include "mutex.h" +#include "norm2allmodes.h" #include "normalizer2impl.h" +#include "uassert.h" #include "ucln_cmn.h" -#include "uhash.h" + +using icu::Normalizer2Impl; + +// NFC/NFD data machine-generated by gennorm2 --csource +#define INCLUDED_FROM_NORMALIZER2_CPP +#include "norm2_nfc_data.h" U_NAMESPACE_BEGIN // Public API dispatch via Normalizer2 subclasses -------------------------- *** +Normalizer2::~Normalizer2() {} + +UBool +Normalizer2::getRawDecomposition(UChar32, UnicodeString &) const { + return FALSE; +} + +UChar32 +Normalizer2::composePair(UChar32, UChar32) const { + return U_SENTINEL; +} + +uint8_t +Normalizer2::getCombiningClass(UChar32 /*c*/) const { + return 0; +} + // Normalizer2 implementation for the old UNORM_NONE. class NoopNormalizer2 : public Normalizer2 { + virtual ~NoopNormalizer2(); + virtual UnicodeString & normalize(const UnicodeString &src, UnicodeString &dest, @@ -78,6 +102,7 @@ class NoopNormalizer2 : public Normalizer2 { getDecomposition(UChar32, UnicodeString &) const { return FALSE; } + // No need to override the default getRawDecomposition(). virtual UBool isNormalized(const UnicodeString &, UErrorCode &) const { return TRUE; @@ -95,437 +120,133 @@ class NoopNormalizer2 : public Normalizer2 { virtual UBool isInert(UChar32) const { return TRUE; } }; -// Intermediate class: -// Has Normalizer2Impl and does boilerplate argument checking and setup. -class Normalizer2WithImpl : public Normalizer2 { -public: - Normalizer2WithImpl(const Normalizer2Impl &ni) : impl(ni) {} +NoopNormalizer2::~NoopNormalizer2() {} - // normalize - virtual UnicodeString & - normalize(const UnicodeString &src, - UnicodeString &dest, - UErrorCode &errorCode) const { - if(U_FAILURE(errorCode)) { - dest.setToBogus(); - return dest; - } - const UChar *sArray=src.getBuffer(); - if(&dest==&src || sArray==NULL) { - errorCode=U_ILLEGAL_ARGUMENT_ERROR; - dest.setToBogus(); - return dest; - } - dest.remove(); - ReorderingBuffer buffer(impl, dest); - if(buffer.init(src.length(), errorCode)) { - normalize(sArray, sArray+src.length(), buffer, errorCode); - } - return dest; - } - virtual void - normalize(const UChar *src, const UChar *limit, - ReorderingBuffer &buffer, UErrorCode &errorCode) const = 0; +Normalizer2WithImpl::~Normalizer2WithImpl() {} - // normalize and append - virtual UnicodeString & - normalizeSecondAndAppend(UnicodeString &first, - const UnicodeString &second, - UErrorCode &errorCode) const { - return normalizeSecondAndAppend(first, second, TRUE, errorCode); - } - virtual UnicodeString & - append(UnicodeString &first, - const UnicodeString &second, - UErrorCode &errorCode) const { - return normalizeSecondAndAppend(first, second, FALSE, errorCode); - } - UnicodeString & - normalizeSecondAndAppend(UnicodeString &first, - const UnicodeString &second, - UBool doNormalize, - UErrorCode &errorCode) const { - uprv_checkCanGetBuffer(first, errorCode); - if(U_FAILURE(errorCode)) { - return first; - } - const UChar *secondArray=second.getBuffer(); - if(&first==&second || secondArray==NULL) { - errorCode=U_ILLEGAL_ARGUMENT_ERROR; - return first; - } - ReorderingBuffer buffer(impl, first); - if(buffer.init(first.length()+second.length(), errorCode)) { - normalizeAndAppend(secondArray, secondArray+second.length(), doNormalize, - buffer, errorCode); - } - return first; - } - virtual void - normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, - ReorderingBuffer &buffer, UErrorCode &errorCode) const = 0; - virtual UBool - getDecomposition(UChar32 c, UnicodeString &decomposition) const { - UChar buffer[4]; - int32_t length; - const UChar *d=impl.getDecomposition(c, buffer, length); - if(d==NULL) { - return FALSE; - } - if(d==buffer) { - decomposition.setTo(buffer, length); // copy the string (Jamos from Hangul syllable c) - } else { - decomposition.setTo(FALSE, d, length); // read-only alias - } - return TRUE; - } +DecomposeNormalizer2::~DecomposeNormalizer2() {} - // quick checks - virtual UBool - isNormalized(const UnicodeString &s, UErrorCode &errorCode) const { - if(U_FAILURE(errorCode)) { - return FALSE; - } - const UChar *sArray=s.getBuffer(); - if(sArray==NULL) { - errorCode=U_ILLEGAL_ARGUMENT_ERROR; - return FALSE; - } - const UChar *sLimit=sArray+s.length(); - return sLimit==spanQuickCheckYes(sArray, sLimit, errorCode); - } - virtual UNormalizationCheckResult - quickCheck(const UnicodeString &s, UErrorCode &errorCode) const { - return Normalizer2WithImpl::isNormalized(s, errorCode) ? UNORM_YES : UNORM_NO; - } - virtual int32_t - spanQuickCheckYes(const UnicodeString &s, UErrorCode &errorCode) const { - if(U_FAILURE(errorCode)) { - return 0; - } - const UChar *sArray=s.getBuffer(); - if(sArray==NULL) { - errorCode=U_ILLEGAL_ARGUMENT_ERROR; - return 0; - } - return (int32_t)(spanQuickCheckYes(sArray, sArray+s.length(), errorCode)-sArray); - } - virtual const UChar * - spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const = 0; +ComposeNormalizer2::~ComposeNormalizer2() {} - virtual UNormalizationCheckResult getQuickCheck(UChar32) const { - return UNORM_YES; - } - - const Normalizer2Impl &impl; -}; - -class DecomposeNormalizer2 : public Normalizer2WithImpl { -public: - DecomposeNormalizer2(const Normalizer2Impl &ni) : Normalizer2WithImpl(ni) {} - -private: - virtual void - normalize(const UChar *src, const UChar *limit, - ReorderingBuffer &buffer, UErrorCode &errorCode) const { - impl.decompose(src, limit, &buffer, errorCode); - } - using Normalizer2WithImpl::normalize; // Avoid warning about hiding base class function. - virtual void - normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, - ReorderingBuffer &buffer, UErrorCode &errorCode) const { - impl.decomposeAndAppend(src, limit, doNormalize, buffer, errorCode); - } - virtual const UChar * - spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const { - return impl.decompose(src, limit, NULL, errorCode); - } - using Normalizer2WithImpl::spanQuickCheckYes; // Avoid warning about hiding base class function. - virtual UNormalizationCheckResult getQuickCheck(UChar32 c) const { - return impl.isDecompYes(impl.getNorm16(c)) ? UNORM_YES : UNORM_NO; - } - virtual UBool hasBoundaryBefore(UChar32 c) const { return impl.hasDecompBoundary(c, TRUE); } - virtual UBool hasBoundaryAfter(UChar32 c) const { return impl.hasDecompBoundary(c, FALSE); } - virtual UBool isInert(UChar32 c) const { return impl.isDecompInert(c); } -}; +FCDNormalizer2::~FCDNormalizer2() {} -class ComposeNormalizer2 : public Normalizer2WithImpl { -public: - ComposeNormalizer2(const Normalizer2Impl &ni, UBool fcc) : - Normalizer2WithImpl(ni), onlyContiguous(fcc) {} +// instance cache ---------------------------------------------------------- *** -private: - virtual void - normalize(const UChar *src, const UChar *limit, - ReorderingBuffer &buffer, UErrorCode &errorCode) const { - impl.compose(src, limit, onlyContiguous, TRUE, buffer, errorCode); - } - using Normalizer2WithImpl::normalize; // Avoid warning about hiding base class function. - virtual void - normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, - ReorderingBuffer &buffer, UErrorCode &errorCode) const { - impl.composeAndAppend(src, limit, doNormalize, onlyContiguous, buffer, errorCode); - } +Norm2AllModes::~Norm2AllModes() { + delete impl; +} - virtual UBool - isNormalized(const UnicodeString &s, UErrorCode &errorCode) const { - if(U_FAILURE(errorCode)) { - return FALSE; - } - const UChar *sArray=s.getBuffer(); - if(sArray==NULL) { - errorCode=U_ILLEGAL_ARGUMENT_ERROR; - return FALSE; - } - UnicodeString temp; - ReorderingBuffer buffer(impl, temp); - if(!buffer.init(5, errorCode)) { // small destCapacity for substring normalization - return FALSE; - } - return impl.compose(sArray, sArray+s.length(), onlyContiguous, FALSE, buffer, errorCode); - } - virtual UNormalizationCheckResult - quickCheck(const UnicodeString &s, UErrorCode &errorCode) const { - if(U_FAILURE(errorCode)) { - return UNORM_MAYBE; - } - const UChar *sArray=s.getBuffer(); - if(sArray==NULL) { - errorCode=U_ILLEGAL_ARGUMENT_ERROR; - return UNORM_MAYBE; - } - UNormalizationCheckResult qcResult=UNORM_YES; - impl.composeQuickCheck(sArray, sArray+s.length(), onlyContiguous, &qcResult); - return qcResult; - } - virtual const UChar * - spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &) const { - return impl.composeQuickCheck(src, limit, onlyContiguous, NULL); - } - using Normalizer2WithImpl::spanQuickCheckYes; // Avoid warning about hiding base class function. - virtual UNormalizationCheckResult getQuickCheck(UChar32 c) const { - return impl.getCompQuickCheck(impl.getNorm16(c)); - } - virtual UBool hasBoundaryBefore(UChar32 c) const { - return impl.hasCompBoundaryBefore(c); - } - virtual UBool hasBoundaryAfter(UChar32 c) const { - return impl.hasCompBoundaryAfter(c, onlyContiguous, FALSE); +Norm2AllModes * +Norm2AllModes::createInstance(Normalizer2Impl *impl, UErrorCode &errorCode) { + if(U_FAILURE(errorCode)) { + delete impl; + return NULL; } - virtual UBool isInert(UChar32 c) const { - return impl.hasCompBoundaryAfter(c, onlyContiguous, TRUE); + Norm2AllModes *allModes=new Norm2AllModes(impl); + if(allModes==NULL) { + errorCode=U_MEMORY_ALLOCATION_ERROR; + delete impl; + return NULL; } - - const UBool onlyContiguous; -}; - -class FCDNormalizer2 : public Normalizer2WithImpl { -public: - FCDNormalizer2(const Normalizer2Impl &ni) : Normalizer2WithImpl(ni) {} - -private: - virtual void - normalize(const UChar *src, const UChar *limit, - ReorderingBuffer &buffer, UErrorCode &errorCode) const { - impl.makeFCD(src, limit, &buffer, errorCode); - } - using Normalizer2WithImpl::normalize; // Avoid warning about hiding base class function. - virtual void - normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, - ReorderingBuffer &buffer, UErrorCode &errorCode) const { - impl.makeFCDAndAppend(src, limit, doNormalize, buffer, errorCode); - } - virtual const UChar * - spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const { - return impl.makeFCD(src, limit, NULL, errorCode); - } - using Normalizer2WithImpl::spanQuickCheckYes; // Avoid warning about hiding base class function. - virtual UBool hasBoundaryBefore(UChar32 c) const { return impl.hasFCDBoundaryBefore(c); } - virtual UBool hasBoundaryAfter(UChar32 c) const { return impl.hasFCDBoundaryAfter(c); } - virtual UBool isInert(UChar32 c) const { return impl.isFCDInert(c); } -}; - -// instance cache ---------------------------------------------------------- *** - -struct Norm2AllModes : public UMemory { - static Norm2AllModes *createInstance(const char *packageName, - const char *name, - UErrorCode &errorCode); - Norm2AllModes() : comp(impl, FALSE), decomp(impl), fcd(impl), fcc(impl, TRUE) {} - - Normalizer2Impl impl; - ComposeNormalizer2 comp; - DecomposeNormalizer2 decomp; - FCDNormalizer2 fcd; - ComposeNormalizer2 fcc; -}; + return allModes; +} Norm2AllModes * -Norm2AllModes::createInstance(const char *packageName, - const char *name, - UErrorCode &errorCode) { +Norm2AllModes::createNFCInstance(UErrorCode &errorCode) { if(U_FAILURE(errorCode)) { return NULL; } - LocalPointer allModes(new Norm2AllModes); - if(allModes.isNull()) { + Normalizer2Impl *impl=new Normalizer2Impl; + if(impl==NULL) { errorCode=U_MEMORY_ALLOCATION_ERROR; return NULL; } - allModes->impl.load(packageName, name, errorCode); - return U_SUCCESS(errorCode) ? allModes.orphan() : NULL; + impl->init(norm2_nfc_data_indexes, &norm2_nfc_data_trie, + norm2_nfc_data_extraData, norm2_nfc_data_smallFCD); + return createInstance(impl, errorCode); } U_CDECL_BEGIN static UBool U_CALLCONV uprv_normalizer2_cleanup(); U_CDECL_END -class Norm2AllModesSingleton : public TriStateSingletonWrapper { -public: - Norm2AllModesSingleton(TriStateSingleton &s, const char *n) : - TriStateSingletonWrapper(s), name(n) {} - Norm2AllModes *getInstance(UErrorCode &errorCode) { - return TriStateSingletonWrapper::getInstance(createInstance, name, errorCode); - } -private: - static void *createInstance(const void *context, UErrorCode &errorCode) { - ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanup); - return Norm2AllModes::createInstance(NULL, (const char *)context, errorCode); - } +static Norm2AllModes *nfcSingleton; +static Normalizer2 *noopSingleton; - const char *name; -}; +static icu::UInitOnce nfcInitOnce = U_INITONCE_INITIALIZER; +static icu::UInitOnce noopInitOnce = U_INITONCE_INITIALIZER; -STATIC_TRI_STATE_SINGLETON(nfcSingleton); -STATIC_TRI_STATE_SINGLETON(nfkcSingleton); -STATIC_TRI_STATE_SINGLETON(nfkc_cfSingleton); - -class Norm2Singleton : public SimpleSingletonWrapper { -public: - Norm2Singleton(SimpleSingleton &s) : SimpleSingletonWrapper(s) {} - Normalizer2 *getInstance(UErrorCode &errorCode) { - return SimpleSingletonWrapper::getInstance(createInstance, NULL, errorCode); - } -private: - static void *createInstance(const void *, UErrorCode &errorCode) { - Normalizer2 *noop=new NoopNormalizer2; - if(noop==NULL) { - errorCode=U_MEMORY_ALLOCATION_ERROR; - } - ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanup); - return noop; - } -}; - -STATIC_SIMPLE_SINGLETON(noopSingleton); +// UInitOnce singleton initialization functions +static void U_CALLCONV initNFCSingleton(UErrorCode &errorCode) { + nfcSingleton=Norm2AllModes::createNFCInstance(errorCode); + ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanup); +} -static UHashtable *cache=NULL; +static void U_CALLCONV initNoopSingleton(UErrorCode &errorCode) { + if(U_FAILURE(errorCode)) { + return; + } + noopSingleton=new NoopNormalizer2; + if(noopSingleton==NULL) { + errorCode=U_MEMORY_ALLOCATION_ERROR; + return; + } + ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanup); +} U_CDECL_BEGIN -static void U_CALLCONV deleteNorm2AllModes(void *allModes) { - delete (Norm2AllModes *)allModes; -} - static UBool U_CALLCONV uprv_normalizer2_cleanup() { - Norm2AllModesSingleton(nfcSingleton, NULL).deleteInstance(); - Norm2AllModesSingleton(nfkcSingleton, NULL).deleteInstance(); - Norm2AllModesSingleton(nfkc_cfSingleton, NULL).deleteInstance(); - Norm2Singleton(noopSingleton).deleteInstance(); - uhash_close(cache); - cache=NULL; + delete nfcSingleton; + nfcSingleton = NULL; + delete noopSingleton; + noopSingleton = NULL; + nfcInitOnce.reset(); + noopInitOnce.reset(); return TRUE; } U_CDECL_END -const Normalizer2 *Normalizer2Factory::getNFCInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes=Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); +const Norm2AllModes * +Norm2AllModes::getNFCInstance(UErrorCode &errorCode) { + if(U_FAILURE(errorCode)) { return NULL; } + umtx_initOnce(nfcInitOnce, &initNFCSingleton, errorCode); + return nfcSingleton; +} + +const Normalizer2 * +Normalizer2::getNFCInstance(UErrorCode &errorCode) { + const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); return allModes!=NULL ? &allModes->comp : NULL; } -const Normalizer2 *Normalizer2Factory::getNFDInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes=Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); +const Normalizer2 * +Normalizer2::getNFDInstance(UErrorCode &errorCode) { + const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); return allModes!=NULL ? &allModes->decomp : NULL; } const Normalizer2 *Normalizer2Factory::getFCDInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes=Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); - if(allModes!=NULL) { - allModes->impl.getFCDTrie(errorCode); - return &allModes->fcd; - } else { - return NULL; - } + const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); + return allModes!=NULL ? &allModes->fcd : NULL; } const Normalizer2 *Normalizer2Factory::getFCCInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes=Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); + const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); return allModes!=NULL ? &allModes->fcc : NULL; } -const Normalizer2 *Normalizer2Factory::getNFKCInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfkcSingleton, "nfkc").getInstance(errorCode); - return allModes!=NULL ? &allModes->comp : NULL; -} - -const Normalizer2 *Normalizer2Factory::getNFKDInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfkcSingleton, "nfkc").getInstance(errorCode); - return allModes!=NULL ? &allModes->decomp : NULL; -} - -const Normalizer2 *Normalizer2Factory::getNFKC_CFInstance(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfkc_cfSingleton, "nfkc_cf").getInstance(errorCode); - return allModes!=NULL ? &allModes->comp : NULL; -} - const Normalizer2 *Normalizer2Factory::getNoopInstance(UErrorCode &errorCode) { - return Norm2Singleton(noopSingleton).getInstance(errorCode); -} - -const Normalizer2 * -Normalizer2Factory::getInstance(UNormalizationMode mode, UErrorCode &errorCode) { - if(U_FAILURE(errorCode)) { - return NULL; - } - switch(mode) { - case UNORM_NFD: - return getNFDInstance(errorCode); - case UNORM_NFKD: - return getNFKDInstance(errorCode); - case UNORM_NFC: - return getNFCInstance(errorCode); - case UNORM_NFKC: - return getNFKCInstance(errorCode); - case UNORM_FCD: - return getFCDInstance(errorCode); - default: // UNORM_NONE - return getNoopInstance(errorCode); - } + if(U_FAILURE(errorCode)) { return NULL; } + umtx_initOnce(noopInitOnce, &initNoopSingleton, errorCode); + return noopSingleton; } const Normalizer2Impl * Normalizer2Factory::getNFCImpl(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); - return allModes!=NULL ? &allModes->impl : NULL; -} - -const Normalizer2Impl * -Normalizer2Factory::getNFKCImpl(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfkcSingleton, "nfkc").getInstance(errorCode); - return allModes!=NULL ? &allModes->impl : NULL; -} - -const Normalizer2Impl * -Normalizer2Factory::getNFKC_CFImpl(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfkc_cfSingleton, "nfkc_cf").getInstance(errorCode); - return allModes!=NULL ? &allModes->impl : NULL; + const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); + return allModes!=NULL ? allModes->impl : NULL; } const Normalizer2Impl * @@ -533,115 +254,28 @@ Normalizer2Factory::getImpl(const Normalizer2 *norm2) { return &((Normalizer2WithImpl *)norm2)->impl; } -const UTrie2 * -Normalizer2Factory::getFCDTrie(UErrorCode &errorCode) { - Norm2AllModes *allModes= - Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); - if(allModes!=NULL) { - return allModes->impl.getFCDTrie(errorCode); - } else { - return NULL; - } -} - -const Normalizer2 * -Normalizer2::getInstance(const char *packageName, - const char *name, - UNormalization2Mode mode, - UErrorCode &errorCode) { - if(U_FAILURE(errorCode)) { - return NULL; - } - if(name==NULL || *name==0) { - errorCode=U_ILLEGAL_ARGUMENT_ERROR; - } - Norm2AllModes *allModes=NULL; - if(packageName==NULL) { - if(0==uprv_strcmp(name, "nfc")) { - allModes=Norm2AllModesSingleton(nfcSingleton, "nfc").getInstance(errorCode); - } else if(0==uprv_strcmp(name, "nfkc")) { - allModes=Norm2AllModesSingleton(nfkcSingleton, "nfkc").getInstance(errorCode); - } else if(0==uprv_strcmp(name, "nfkc_cf")) { - allModes=Norm2AllModesSingleton(nfkc_cfSingleton, "nfkc_cf").getInstance(errorCode); - } - } - if(allModes==NULL && U_SUCCESS(errorCode)) { - { - Mutex lock; - if(cache!=NULL) { - allModes=(Norm2AllModes *)uhash_get(cache, name); - } - } - if(allModes==NULL) { - LocalPointer localAllModes( - Norm2AllModes::createInstance(packageName, name, errorCode)); - if(U_SUCCESS(errorCode)) { - Mutex lock; - if(cache==NULL) { - cache=uhash_open(uhash_hashChars, uhash_compareChars, NULL, &errorCode); - if(U_FAILURE(errorCode)) { - return NULL; - } - uhash_setKeyDeleter(cache, uprv_free); - uhash_setValueDeleter(cache, deleteNorm2AllModes); - } - void *temp=uhash_get(cache, name); - if(temp==NULL) { - int32_t keyLength=uprv_strlen(name)+1; - char *nameCopy=(char *)uprv_malloc(keyLength); - if(nameCopy==NULL) { - errorCode=U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - uprv_memcpy(nameCopy, name, keyLength); - uhash_put(cache, nameCopy, allModes=localAllModes.orphan(), &errorCode); - } else { - // race condition - allModes=(Norm2AllModes *)temp; - } - } - } - } - if(allModes!=NULL && U_SUCCESS(errorCode)) { - switch(mode) { - case UNORM2_COMPOSE: - return &allModes->comp; - case UNORM2_DECOMPOSE: - return &allModes->decomp; - case UNORM2_FCD: - allModes->impl.getFCDTrie(errorCode); - return &allModes->fcd; - case UNORM2_COMPOSE_CONTIGUOUS: - return &allModes->fcc; - default: - break; // do nothing - } - } - return NULL; -} - -UOBJECT_DEFINE_NO_RTTI_IMPLEMENTATION(Normalizer2) - U_NAMESPACE_END // C API ------------------------------------------------------------------- *** U_NAMESPACE_USE -U_DRAFT const UNormalizer2 * U_EXPORT2 -unorm2_getInstance(const char *packageName, - const char *name, - UNormalization2Mode mode, - UErrorCode *pErrorCode) { - return (const UNormalizer2 *)Normalizer2::getInstance(packageName, name, mode, *pErrorCode); +U_CAPI const UNormalizer2 * U_EXPORT2 +unorm2_getNFCInstance(UErrorCode *pErrorCode) { + return (const UNormalizer2 *)Normalizer2::getNFCInstance(*pErrorCode); } -U_DRAFT void U_EXPORT2 +U_CAPI const UNormalizer2 * U_EXPORT2 +unorm2_getNFDInstance(UErrorCode *pErrorCode) { + return (const UNormalizer2 *)Normalizer2::getNFDInstance(*pErrorCode); +} + +U_CAPI void U_EXPORT2 unorm2_close(UNormalizer2 *norm2) { delete (Normalizer2 *)norm2; } -U_DRAFT int32_t U_EXPORT2 +U_CAPI int32_t U_EXPORT2 unorm2_normalize(const UNormalizer2 *norm2, const UChar *src, int32_t length, UChar *dest, int32_t capacity, @@ -693,16 +327,31 @@ normalizeSecondAndAppend(const UNormalizer2 *norm2, return 0; } UnicodeString firstString(first, firstLength, firstCapacity); + firstLength=firstString.length(); // In case it was -1. // secondLength==0: Nothing to do, and n2wi->normalizeAndAppend(NULL, NULL, buffer, ...) would crash. if(secondLength!=0) { const Normalizer2 *n2=(const Normalizer2 *)norm2; const Normalizer2WithImpl *n2wi=dynamic_cast(n2); if(n2wi!=NULL) { // Avoid duplicate argument checking and support NUL-terminated src. - ReorderingBuffer buffer(n2wi->impl, firstString); - if(buffer.init(firstLength+secondLength+1, *pErrorCode)) { // destCapacity>=-1 - n2wi->normalizeAndAppend(second, secondLength>=0 ? second+secondLength : NULL, - doNormalize, buffer, *pErrorCode); + UnicodeString safeMiddle; + { + ReorderingBuffer buffer(n2wi->impl, firstString); + if(buffer.init(firstLength+secondLength+1, *pErrorCode)) { // destCapacity>=-1 + n2wi->normalizeAndAppend(second, secondLength>=0 ? second+secondLength : NULL, + doNormalize, safeMiddle, buffer, *pErrorCode); + } + } // The ReorderingBuffer destructor finalizes firstString. + if(U_FAILURE(*pErrorCode) || firstString.length()>firstCapacity) { + // Restore the modified suffix of the first string. + // This does not restore first[] array contents between firstLength and firstCapacity. + // (That might be uninitialized memory, as far as we know.) + if(first!=NULL) { /* don't dereference NULL */ + safeMiddle.extract(0, 0x7fffffff, first+firstLength-safeMiddle.length()); + if(firstLength(norm2)->getRawDecomposition(c, destString)) { + return destString.extract(decomposition, capacity, *pErrorCode); + } else { + return -1; + } +} + +U_CAPI UChar32 U_EXPORT2 +unorm2_composePair(const UNormalizer2 *norm2, UChar32 a, UChar32 b) { + return reinterpret_cast(norm2)->composePair(a, b); +} + +U_CAPI uint8_t U_EXPORT2 +unorm2_getCombiningClass(const UNormalizer2 *norm2, UChar32 c) { + return reinterpret_cast(norm2)->getCombiningClass(c); +} + +U_CAPI UBool U_EXPORT2 unorm2_isNormalized(const UNormalizer2 *norm2, const UChar *s, int32_t length, UErrorCode *pErrorCode) { @@ -772,7 +450,7 @@ unorm2_isNormalized(const UNormalizer2 *norm2, return ((const Normalizer2 *)norm2)->isNormalized(sString, *pErrorCode); } -U_DRAFT UNormalizationCheckResult U_EXPORT2 +U_CAPI UNormalizationCheckResult U_EXPORT2 unorm2_quickCheck(const UNormalizer2 *norm2, const UChar *s, int32_t length, UErrorCode *pErrorCode) { @@ -787,7 +465,7 @@ unorm2_quickCheck(const UNormalizer2 *norm2, return ((const Normalizer2 *)norm2)->quickCheck(sString, *pErrorCode); } -U_DRAFT int32_t U_EXPORT2 +U_CAPI int32_t U_EXPORT2 unorm2_spanQuickCheckYes(const UNormalizer2 *norm2, const UChar *s, int32_t length, UErrorCode *pErrorCode) { @@ -802,45 +480,42 @@ unorm2_spanQuickCheckYes(const UNormalizer2 *norm2, return ((const Normalizer2 *)norm2)->spanQuickCheckYes(sString, *pErrorCode); } -U_DRAFT UBool U_EXPORT2 +U_CAPI UBool U_EXPORT2 unorm2_hasBoundaryBefore(const UNormalizer2 *norm2, UChar32 c) { return ((const Normalizer2 *)norm2)->hasBoundaryBefore(c); } -U_DRAFT UBool U_EXPORT2 +U_CAPI UBool U_EXPORT2 unorm2_hasBoundaryAfter(const UNormalizer2 *norm2, UChar32 c) { return ((const Normalizer2 *)norm2)->hasBoundaryAfter(c); } -U_DRAFT UBool U_EXPORT2 +U_CAPI UBool U_EXPORT2 unorm2_isInert(const UNormalizer2 *norm2, UChar32 c) { return ((const Normalizer2 *)norm2)->isInert(c); } // Some properties APIs ---------------------------------------------------- *** -U_CFUNC UNormalizationCheckResult U_EXPORT2 -unorm_getQuickCheck(UChar32 c, UNormalizationMode mode) { - if(mode<=UNORM_NONE || UNORM_FCD<=mode) { - return UNORM_YES; - } +U_CAPI uint8_t U_EXPORT2 +u_getCombiningClass(UChar32 c) { UErrorCode errorCode=U_ZERO_ERROR; - const Normalizer2 *norm2=Normalizer2Factory::getInstance(mode, errorCode); + const Normalizer2 *nfd=Normalizer2::getNFDInstance(errorCode); if(U_SUCCESS(errorCode)) { - return ((const Normalizer2WithImpl *)norm2)->getQuickCheck(c); + return nfd->getCombiningClass(c); } else { - return UNORM_MAYBE; + return 0; } } -U_CAPI const uint16_t * U_EXPORT2 -unorm_getFCDTrieIndex(UChar32 &fcdHighStart, UErrorCode *pErrorCode) { - const UTrie2 *trie=Normalizer2Factory::getFCDTrie(*pErrorCode); - if(U_SUCCESS(*pErrorCode)) { - fcdHighStart=trie->highStart; - return trie->index; +U_CFUNC uint16_t +unorm_getFCD16(UChar32 c) { + UErrorCode errorCode=U_ZERO_ERROR; + const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(errorCode); + if(U_SUCCESS(errorCode)) { + return impl->getFCD16(c); } else { - return NULL; + return 0; } }