11cb0ef41Sopenharmony_ci// © 2016 and later: Unicode, Inc. and others.
21cb0ef41Sopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html
31cb0ef41Sopenharmony_ci/*
41cb0ef41Sopenharmony_ci*******************************************************************************
51cb0ef41Sopenharmony_ci* Copyright (C) 2014, International Business Machines
61cb0ef41Sopenharmony_ci* Corporation and others.  All Rights Reserved.
71cb0ef41Sopenharmony_ci*******************************************************************************
81cb0ef41Sopenharmony_ci* loadednormalizer2impl.cpp
91cb0ef41Sopenharmony_ci*
101cb0ef41Sopenharmony_ci* created on: 2014sep03
111cb0ef41Sopenharmony_ci* created by: Markus W. Scherer
121cb0ef41Sopenharmony_ci*/
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci#include "unicode/utypes.h"
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci#if !UCONFIG_NO_NORMALIZATION
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci#include "unicode/udata.h"
191cb0ef41Sopenharmony_ci#include "unicode/localpointer.h"
201cb0ef41Sopenharmony_ci#include "unicode/normalizer2.h"
211cb0ef41Sopenharmony_ci#include "unicode/ucptrie.h"
221cb0ef41Sopenharmony_ci#include "unicode/unistr.h"
231cb0ef41Sopenharmony_ci#include "unicode/unorm.h"
241cb0ef41Sopenharmony_ci#include "cstring.h"
251cb0ef41Sopenharmony_ci#include "mutex.h"
261cb0ef41Sopenharmony_ci#include "norm2allmodes.h"
271cb0ef41Sopenharmony_ci#include "normalizer2impl.h"
281cb0ef41Sopenharmony_ci#include "uassert.h"
291cb0ef41Sopenharmony_ci#include "ucln_cmn.h"
301cb0ef41Sopenharmony_ci#include "uhash.h"
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ciU_NAMESPACE_BEGIN
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ciclass LoadedNormalizer2Impl : public Normalizer2Impl {
351cb0ef41Sopenharmony_cipublic:
361cb0ef41Sopenharmony_ci    LoadedNormalizer2Impl() : memory(nullptr), ownedTrie(nullptr) {}
371cb0ef41Sopenharmony_ci    virtual ~LoadedNormalizer2Impl();
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci    void load(const char *packageName, const char *name, UErrorCode &errorCode);
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ciprivate:
421cb0ef41Sopenharmony_ci    static UBool U_CALLCONV
431cb0ef41Sopenharmony_ci    isAcceptable(void *context, const char *type, const char *name, const UDataInfo *pInfo);
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci    UDataMemory *memory;
461cb0ef41Sopenharmony_ci    UCPTrie *ownedTrie;
471cb0ef41Sopenharmony_ci};
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ciLoadedNormalizer2Impl::~LoadedNormalizer2Impl() {
501cb0ef41Sopenharmony_ci    udata_close(memory);
511cb0ef41Sopenharmony_ci    ucptrie_close(ownedTrie);
521cb0ef41Sopenharmony_ci}
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ciUBool U_CALLCONV
551cb0ef41Sopenharmony_ciLoadedNormalizer2Impl::isAcceptable(void * /*context*/,
561cb0ef41Sopenharmony_ci                                    const char * /* type */, const char * /*name*/,
571cb0ef41Sopenharmony_ci                                    const UDataInfo *pInfo) {
581cb0ef41Sopenharmony_ci    if(
591cb0ef41Sopenharmony_ci        pInfo->size>=20 &&
601cb0ef41Sopenharmony_ci        pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
611cb0ef41Sopenharmony_ci        pInfo->charsetFamily==U_CHARSET_FAMILY &&
621cb0ef41Sopenharmony_ci        pInfo->dataFormat[0]==0x4e &&    /* dataFormat="Nrm2" */
631cb0ef41Sopenharmony_ci        pInfo->dataFormat[1]==0x72 &&
641cb0ef41Sopenharmony_ci        pInfo->dataFormat[2]==0x6d &&
651cb0ef41Sopenharmony_ci        pInfo->dataFormat[3]==0x32 &&
661cb0ef41Sopenharmony_ci        pInfo->formatVersion[0]==4
671cb0ef41Sopenharmony_ci    ) {
681cb0ef41Sopenharmony_ci        // Normalizer2Impl *me=(Normalizer2Impl *)context;
691cb0ef41Sopenharmony_ci        // uprv_memcpy(me->dataVersion, pInfo->dataVersion, 4);
701cb0ef41Sopenharmony_ci        return true;
711cb0ef41Sopenharmony_ci    } else {
721cb0ef41Sopenharmony_ci        return false;
731cb0ef41Sopenharmony_ci    }
741cb0ef41Sopenharmony_ci}
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_civoid
771cb0ef41Sopenharmony_ciLoadedNormalizer2Impl::load(const char *packageName, const char *name, UErrorCode &errorCode) {
781cb0ef41Sopenharmony_ci    if(U_FAILURE(errorCode)) {
791cb0ef41Sopenharmony_ci        return;
801cb0ef41Sopenharmony_ci    }
811cb0ef41Sopenharmony_ci    memory=udata_openChoice(packageName, "nrm", name, isAcceptable, this, &errorCode);
821cb0ef41Sopenharmony_ci    if(U_FAILURE(errorCode)) {
831cb0ef41Sopenharmony_ci        return;
841cb0ef41Sopenharmony_ci    }
851cb0ef41Sopenharmony_ci    const uint8_t *inBytes=(const uint8_t *)udata_getMemory(memory);
861cb0ef41Sopenharmony_ci    const int32_t *inIndexes=(const int32_t *)inBytes;
871cb0ef41Sopenharmony_ci    int32_t indexesLength=inIndexes[IX_NORM_TRIE_OFFSET]/4;
881cb0ef41Sopenharmony_ci    if(indexesLength<=IX_MIN_LCCC_CP) {
891cb0ef41Sopenharmony_ci        errorCode=U_INVALID_FORMAT_ERROR;  // Not enough indexes.
901cb0ef41Sopenharmony_ci        return;
911cb0ef41Sopenharmony_ci    }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci    int32_t offset=inIndexes[IX_NORM_TRIE_OFFSET];
941cb0ef41Sopenharmony_ci    int32_t nextOffset=inIndexes[IX_EXTRA_DATA_OFFSET];
951cb0ef41Sopenharmony_ci    ownedTrie=ucptrie_openFromBinary(UCPTRIE_TYPE_FAST, UCPTRIE_VALUE_BITS_16,
961cb0ef41Sopenharmony_ci                                     inBytes+offset, nextOffset-offset, nullptr,
971cb0ef41Sopenharmony_ci                                     &errorCode);
981cb0ef41Sopenharmony_ci    if(U_FAILURE(errorCode)) {
991cb0ef41Sopenharmony_ci        return;
1001cb0ef41Sopenharmony_ci    }
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci    offset=nextOffset;
1031cb0ef41Sopenharmony_ci    nextOffset=inIndexes[IX_SMALL_FCD_OFFSET];
1041cb0ef41Sopenharmony_ci    const uint16_t *inExtraData=(const uint16_t *)(inBytes+offset);
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci    // smallFCD: new in formatVersion 2
1071cb0ef41Sopenharmony_ci    offset=nextOffset;
1081cb0ef41Sopenharmony_ci    const uint8_t *inSmallFCD=inBytes+offset;
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci    init(inIndexes, ownedTrie, inExtraData, inSmallFCD);
1111cb0ef41Sopenharmony_ci}
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci// instance cache ---------------------------------------------------------- ***
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ciNorm2AllModes *
1161cb0ef41Sopenharmony_ciNorm2AllModes::createInstance(const char *packageName,
1171cb0ef41Sopenharmony_ci                              const char *name,
1181cb0ef41Sopenharmony_ci                              UErrorCode &errorCode) {
1191cb0ef41Sopenharmony_ci    if(U_FAILURE(errorCode)) {
1201cb0ef41Sopenharmony_ci        return nullptr;
1211cb0ef41Sopenharmony_ci    }
1221cb0ef41Sopenharmony_ci    LoadedNormalizer2Impl *impl=new LoadedNormalizer2Impl;
1231cb0ef41Sopenharmony_ci    if(impl==nullptr) {
1241cb0ef41Sopenharmony_ci        errorCode=U_MEMORY_ALLOCATION_ERROR;
1251cb0ef41Sopenharmony_ci        return nullptr;
1261cb0ef41Sopenharmony_ci    }
1271cb0ef41Sopenharmony_ci    impl->load(packageName, name, errorCode);
1281cb0ef41Sopenharmony_ci    return createInstance(impl, errorCode);
1291cb0ef41Sopenharmony_ci}
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ciU_CDECL_BEGIN
1321cb0ef41Sopenharmony_cistatic UBool U_CALLCONV uprv_loaded_normalizer2_cleanup();
1331cb0ef41Sopenharmony_ciU_CDECL_END
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci#if !NORM2_HARDCODE_NFC_DATA
1361cb0ef41Sopenharmony_cistatic Norm2AllModes *nfcSingleton;
1371cb0ef41Sopenharmony_cistatic icu::UInitOnce nfcInitOnce {};
1381cb0ef41Sopenharmony_ci#endif
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_cistatic Norm2AllModes *nfkcSingleton;
1411cb0ef41Sopenharmony_cistatic icu::UInitOnce nfkcInitOnce {};
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_cistatic Norm2AllModes *nfkc_cfSingleton;
1441cb0ef41Sopenharmony_cistatic icu::UInitOnce nfkc_cfInitOnce {};
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_cistatic Norm2AllModes *nfkc_scfSingleton;
1471cb0ef41Sopenharmony_cistatic icu::UInitOnce nfkc_scfInitOnce {};
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_cistatic UHashtable    *cache=nullptr;
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci// UInitOnce singleton initialization function
1521cb0ef41Sopenharmony_cistatic void U_CALLCONV initSingletons(const char *what, UErrorCode &errorCode) {
1531cb0ef41Sopenharmony_ci#if !NORM2_HARDCODE_NFC_DATA
1541cb0ef41Sopenharmony_ci    if (uprv_strcmp(what, "nfc") == 0) {
1551cb0ef41Sopenharmony_ci        nfcSingleton    = Norm2AllModes::createInstance(nullptr, "nfc", errorCode);
1561cb0ef41Sopenharmony_ci    } else
1571cb0ef41Sopenharmony_ci#endif
1581cb0ef41Sopenharmony_ci    if (uprv_strcmp(what, "nfkc") == 0) {
1591cb0ef41Sopenharmony_ci        nfkcSingleton    = Norm2AllModes::createInstance(nullptr, "nfkc", errorCode);
1601cb0ef41Sopenharmony_ci    } else if (uprv_strcmp(what, "nfkc_cf") == 0) {
1611cb0ef41Sopenharmony_ci        nfkc_cfSingleton = Norm2AllModes::createInstance(nullptr, "nfkc_cf", errorCode);
1621cb0ef41Sopenharmony_ci    } else if (uprv_strcmp(what, "nfkc_scf") == 0) {
1631cb0ef41Sopenharmony_ci        nfkc_scfSingleton = Norm2AllModes::createInstance(nullptr, "nfkc_scf", errorCode);
1641cb0ef41Sopenharmony_ci    } else {
1651cb0ef41Sopenharmony_ci        UPRV_UNREACHABLE_EXIT;   // Unknown singleton
1661cb0ef41Sopenharmony_ci    }
1671cb0ef41Sopenharmony_ci    ucln_common_registerCleanup(UCLN_COMMON_LOADED_NORMALIZER2, uprv_loaded_normalizer2_cleanup);
1681cb0ef41Sopenharmony_ci}
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ciU_CDECL_BEGIN
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_cistatic void U_CALLCONV deleteNorm2AllModes(void *allModes) {
1731cb0ef41Sopenharmony_ci    delete (Norm2AllModes *)allModes;
1741cb0ef41Sopenharmony_ci}
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_cistatic UBool U_CALLCONV uprv_loaded_normalizer2_cleanup() {
1771cb0ef41Sopenharmony_ci#if !NORM2_HARDCODE_NFC_DATA
1781cb0ef41Sopenharmony_ci    delete nfcSingleton;
1791cb0ef41Sopenharmony_ci    nfcSingleton = nullptr;
1801cb0ef41Sopenharmony_ci    nfcInitOnce.reset();
1811cb0ef41Sopenharmony_ci#endif
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci    delete nfkcSingleton;
1841cb0ef41Sopenharmony_ci    nfkcSingleton = nullptr;
1851cb0ef41Sopenharmony_ci    nfkcInitOnce.reset();
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci    delete nfkc_cfSingleton;
1881cb0ef41Sopenharmony_ci    nfkc_cfSingleton = nullptr;
1891cb0ef41Sopenharmony_ci    nfkc_cfInitOnce.reset();
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci    delete nfkc_scfSingleton;
1921cb0ef41Sopenharmony_ci    nfkc_scfSingleton = nullptr;
1931cb0ef41Sopenharmony_ci    nfkc_scfInitOnce.reset();
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci    uhash_close(cache);
1961cb0ef41Sopenharmony_ci    cache=nullptr;
1971cb0ef41Sopenharmony_ci    return true;
1981cb0ef41Sopenharmony_ci}
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ciU_CDECL_END
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci#if !NORM2_HARDCODE_NFC_DATA
2031cb0ef41Sopenharmony_ciconst Norm2AllModes *
2041cb0ef41Sopenharmony_ciNorm2AllModes::getNFCInstance(UErrorCode &errorCode) {
2051cb0ef41Sopenharmony_ci    if(U_FAILURE(errorCode)) { return nullptr; }
2061cb0ef41Sopenharmony_ci    umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode);
2071cb0ef41Sopenharmony_ci    return nfcSingleton;
2081cb0ef41Sopenharmony_ci}
2091cb0ef41Sopenharmony_ci#endif
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ciconst Norm2AllModes *
2121cb0ef41Sopenharmony_ciNorm2AllModes::getNFKCInstance(UErrorCode &errorCode) {
2131cb0ef41Sopenharmony_ci    if(U_FAILURE(errorCode)) { return nullptr; }
2141cb0ef41Sopenharmony_ci    umtx_initOnce(nfkcInitOnce, &initSingletons, "nfkc", errorCode);
2151cb0ef41Sopenharmony_ci    return nfkcSingleton;
2161cb0ef41Sopenharmony_ci}
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ciconst Norm2AllModes *
2191cb0ef41Sopenharmony_ciNorm2AllModes::getNFKC_CFInstance(UErrorCode &errorCode) {
2201cb0ef41Sopenharmony_ci    if(U_FAILURE(errorCode)) { return nullptr; }
2211cb0ef41Sopenharmony_ci    umtx_initOnce(nfkc_cfInitOnce, &initSingletons, "nfkc_cf", errorCode);
2221cb0ef41Sopenharmony_ci    return nfkc_cfSingleton;
2231cb0ef41Sopenharmony_ci}
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ciconst Norm2AllModes *
2261cb0ef41Sopenharmony_ciNorm2AllModes::getNFKC_SCFInstance(UErrorCode &errorCode) {
2271cb0ef41Sopenharmony_ci    if(U_FAILURE(errorCode)) { return nullptr; }
2281cb0ef41Sopenharmony_ci    umtx_initOnce(nfkc_scfInitOnce, &initSingletons, "nfkc_scf", errorCode);
2291cb0ef41Sopenharmony_ci    return nfkc_scfSingleton;
2301cb0ef41Sopenharmony_ci}
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci#if !NORM2_HARDCODE_NFC_DATA
2331cb0ef41Sopenharmony_ciconst Normalizer2 *
2341cb0ef41Sopenharmony_ciNormalizer2::getNFCInstance(UErrorCode &errorCode) {
2351cb0ef41Sopenharmony_ci    const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode);
2361cb0ef41Sopenharmony_ci    return allModes!=nullptr ? &allModes->comp : nullptr;
2371cb0ef41Sopenharmony_ci}
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ciconst Normalizer2 *
2401cb0ef41Sopenharmony_ciNormalizer2::getNFDInstance(UErrorCode &errorCode) {
2411cb0ef41Sopenharmony_ci    const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode);
2421cb0ef41Sopenharmony_ci    return allModes!=nullptr ? &allModes->decomp : nullptr;
2431cb0ef41Sopenharmony_ci}
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ciconst Normalizer2 *Normalizer2Factory::getFCDInstance(UErrorCode &errorCode) {
2461cb0ef41Sopenharmony_ci    const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode);
2471cb0ef41Sopenharmony_ci    return allModes!=nullptr ? &allModes->fcd : nullptr;
2481cb0ef41Sopenharmony_ci}
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ciconst Normalizer2 *Normalizer2Factory::getFCCInstance(UErrorCode &errorCode) {
2511cb0ef41Sopenharmony_ci    const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode);
2521cb0ef41Sopenharmony_ci    return allModes!=nullptr ? &allModes->fcc : nullptr;
2531cb0ef41Sopenharmony_ci}
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ciconst Normalizer2Impl *
2561cb0ef41Sopenharmony_ciNormalizer2Factory::getNFCImpl(UErrorCode &errorCode) {
2571cb0ef41Sopenharmony_ci    const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode);
2581cb0ef41Sopenharmony_ci    return allModes!=nullptr ? allModes->impl : nullptr;
2591cb0ef41Sopenharmony_ci}
2601cb0ef41Sopenharmony_ci#endif
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ciconst Normalizer2 *
2631cb0ef41Sopenharmony_ciNormalizer2::getNFKCInstance(UErrorCode &errorCode) {
2641cb0ef41Sopenharmony_ci    const Norm2AllModes *allModes=Norm2AllModes::getNFKCInstance(errorCode);
2651cb0ef41Sopenharmony_ci    return allModes!=nullptr ? &allModes->comp : nullptr;
2661cb0ef41Sopenharmony_ci}
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ciconst Normalizer2 *
2691cb0ef41Sopenharmony_ciNormalizer2::getNFKDInstance(UErrorCode &errorCode) {
2701cb0ef41Sopenharmony_ci    const Norm2AllModes *allModes=Norm2AllModes::getNFKCInstance(errorCode);
2711cb0ef41Sopenharmony_ci    return allModes!=nullptr ? &allModes->decomp : nullptr;
2721cb0ef41Sopenharmony_ci}
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ciconst Normalizer2 *
2751cb0ef41Sopenharmony_ciNormalizer2::getNFKCCasefoldInstance(UErrorCode &errorCode) {
2761cb0ef41Sopenharmony_ci    const Norm2AllModes *allModes=Norm2AllModes::getNFKC_CFInstance(errorCode);
2771cb0ef41Sopenharmony_ci    return allModes!=nullptr ? &allModes->comp : nullptr;
2781cb0ef41Sopenharmony_ci}
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_ciconst Normalizer2 *
2811cb0ef41Sopenharmony_ciNormalizer2::getNFKCSimpleCasefoldInstance(UErrorCode &errorCode) {
2821cb0ef41Sopenharmony_ci    const Norm2AllModes *allModes=Norm2AllModes::getNFKC_SCFInstance(errorCode);
2831cb0ef41Sopenharmony_ci    return allModes!=nullptr ? &allModes->comp : nullptr;
2841cb0ef41Sopenharmony_ci}
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ciconst Normalizer2 *
2871cb0ef41Sopenharmony_ciNormalizer2::getInstance(const char *packageName,
2881cb0ef41Sopenharmony_ci                         const char *name,
2891cb0ef41Sopenharmony_ci                         UNormalization2Mode mode,
2901cb0ef41Sopenharmony_ci                         UErrorCode &errorCode) {
2911cb0ef41Sopenharmony_ci    if(U_FAILURE(errorCode)) {
2921cb0ef41Sopenharmony_ci        return nullptr;
2931cb0ef41Sopenharmony_ci    }
2941cb0ef41Sopenharmony_ci    if(name==nullptr || *name==0) {
2951cb0ef41Sopenharmony_ci        errorCode=U_ILLEGAL_ARGUMENT_ERROR;
2961cb0ef41Sopenharmony_ci        return nullptr;
2971cb0ef41Sopenharmony_ci    }
2981cb0ef41Sopenharmony_ci    const Norm2AllModes *allModes=nullptr;
2991cb0ef41Sopenharmony_ci    if(packageName==nullptr) {
3001cb0ef41Sopenharmony_ci        if(0==uprv_strcmp(name, "nfc")) {
3011cb0ef41Sopenharmony_ci            allModes=Norm2AllModes::getNFCInstance(errorCode);
3021cb0ef41Sopenharmony_ci        } else if(0==uprv_strcmp(name, "nfkc")) {
3031cb0ef41Sopenharmony_ci            allModes=Norm2AllModes::getNFKCInstance(errorCode);
3041cb0ef41Sopenharmony_ci        } else if(0==uprv_strcmp(name, "nfkc_cf")) {
3051cb0ef41Sopenharmony_ci            allModes=Norm2AllModes::getNFKC_CFInstance(errorCode);
3061cb0ef41Sopenharmony_ci        } else if(0==uprv_strcmp(name, "nfkc_scf")) {
3071cb0ef41Sopenharmony_ci            allModes=Norm2AllModes::getNFKC_SCFInstance(errorCode);
3081cb0ef41Sopenharmony_ci        }
3091cb0ef41Sopenharmony_ci    }
3101cb0ef41Sopenharmony_ci    if(allModes==nullptr && U_SUCCESS(errorCode)) {
3111cb0ef41Sopenharmony_ci        {
3121cb0ef41Sopenharmony_ci            Mutex lock;
3131cb0ef41Sopenharmony_ci            if(cache!=nullptr) {
3141cb0ef41Sopenharmony_ci                allModes=(Norm2AllModes *)uhash_get(cache, name);
3151cb0ef41Sopenharmony_ci            }
3161cb0ef41Sopenharmony_ci        }
3171cb0ef41Sopenharmony_ci        if(allModes==nullptr) {
3181cb0ef41Sopenharmony_ci            ucln_common_registerCleanup(UCLN_COMMON_LOADED_NORMALIZER2, uprv_loaded_normalizer2_cleanup);
3191cb0ef41Sopenharmony_ci            LocalPointer<Norm2AllModes> localAllModes(
3201cb0ef41Sopenharmony_ci                Norm2AllModes::createInstance(packageName, name, errorCode));
3211cb0ef41Sopenharmony_ci            if(U_SUCCESS(errorCode)) {
3221cb0ef41Sopenharmony_ci                Mutex lock;
3231cb0ef41Sopenharmony_ci                if(cache==nullptr) {
3241cb0ef41Sopenharmony_ci                    cache=uhash_open(uhash_hashChars, uhash_compareChars, nullptr, &errorCode);
3251cb0ef41Sopenharmony_ci                    if(U_FAILURE(errorCode)) {
3261cb0ef41Sopenharmony_ci                        return nullptr;
3271cb0ef41Sopenharmony_ci                    }
3281cb0ef41Sopenharmony_ci                    uhash_setKeyDeleter(cache, uprv_free);
3291cb0ef41Sopenharmony_ci                    uhash_setValueDeleter(cache, deleteNorm2AllModes);
3301cb0ef41Sopenharmony_ci                }
3311cb0ef41Sopenharmony_ci                void *temp=uhash_get(cache, name);
3321cb0ef41Sopenharmony_ci                if(temp==nullptr) {
3331cb0ef41Sopenharmony_ci                    int32_t keyLength= static_cast<int32_t>(uprv_strlen(name)+1);
3341cb0ef41Sopenharmony_ci                    char *nameCopy=(char *)uprv_malloc(keyLength);
3351cb0ef41Sopenharmony_ci                    if(nameCopy==nullptr) {
3361cb0ef41Sopenharmony_ci                        errorCode=U_MEMORY_ALLOCATION_ERROR;
3371cb0ef41Sopenharmony_ci                        return nullptr;
3381cb0ef41Sopenharmony_ci                    }
3391cb0ef41Sopenharmony_ci                    uprv_memcpy(nameCopy, name, keyLength);
3401cb0ef41Sopenharmony_ci                    allModes=localAllModes.getAlias();
3411cb0ef41Sopenharmony_ci                    uhash_put(cache, nameCopy, localAllModes.orphan(), &errorCode);
3421cb0ef41Sopenharmony_ci                } else {
3431cb0ef41Sopenharmony_ci                    // race condition
3441cb0ef41Sopenharmony_ci                    allModes=(Norm2AllModes *)temp;
3451cb0ef41Sopenharmony_ci                }
3461cb0ef41Sopenharmony_ci            }
3471cb0ef41Sopenharmony_ci        }
3481cb0ef41Sopenharmony_ci    }
3491cb0ef41Sopenharmony_ci    if(allModes!=nullptr && U_SUCCESS(errorCode)) {
3501cb0ef41Sopenharmony_ci        switch(mode) {
3511cb0ef41Sopenharmony_ci        case UNORM2_COMPOSE:
3521cb0ef41Sopenharmony_ci            return &allModes->comp;
3531cb0ef41Sopenharmony_ci        case UNORM2_DECOMPOSE:
3541cb0ef41Sopenharmony_ci            return &allModes->decomp;
3551cb0ef41Sopenharmony_ci        case UNORM2_FCD:
3561cb0ef41Sopenharmony_ci            return &allModes->fcd;
3571cb0ef41Sopenharmony_ci        case UNORM2_COMPOSE_CONTIGUOUS:
3581cb0ef41Sopenharmony_ci            return &allModes->fcc;
3591cb0ef41Sopenharmony_ci        default:
3601cb0ef41Sopenharmony_ci            break;  // do nothing
3611cb0ef41Sopenharmony_ci        }
3621cb0ef41Sopenharmony_ci    }
3631cb0ef41Sopenharmony_ci    return nullptr;
3641cb0ef41Sopenharmony_ci}
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ciconst Normalizer2 *
3671cb0ef41Sopenharmony_ciNormalizer2Factory::getInstance(UNormalizationMode mode, UErrorCode &errorCode) {
3681cb0ef41Sopenharmony_ci    if(U_FAILURE(errorCode)) {
3691cb0ef41Sopenharmony_ci        return nullptr;
3701cb0ef41Sopenharmony_ci    }
3711cb0ef41Sopenharmony_ci    switch(mode) {
3721cb0ef41Sopenharmony_ci    case UNORM_NFD:
3731cb0ef41Sopenharmony_ci        return Normalizer2::getNFDInstance(errorCode);
3741cb0ef41Sopenharmony_ci    case UNORM_NFKD:
3751cb0ef41Sopenharmony_ci        return Normalizer2::getNFKDInstance(errorCode);
3761cb0ef41Sopenharmony_ci    case UNORM_NFC:
3771cb0ef41Sopenharmony_ci        return Normalizer2::getNFCInstance(errorCode);
3781cb0ef41Sopenharmony_ci    case UNORM_NFKC:
3791cb0ef41Sopenharmony_ci        return Normalizer2::getNFKCInstance(errorCode);
3801cb0ef41Sopenharmony_ci    case UNORM_FCD:
3811cb0ef41Sopenharmony_ci        return getFCDInstance(errorCode);
3821cb0ef41Sopenharmony_ci    default:  // UNORM_NONE
3831cb0ef41Sopenharmony_ci        return getNoopInstance(errorCode);
3841cb0ef41Sopenharmony_ci    }
3851cb0ef41Sopenharmony_ci}
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ciconst Normalizer2Impl *
3881cb0ef41Sopenharmony_ciNormalizer2Factory::getNFKCImpl(UErrorCode &errorCode) {
3891cb0ef41Sopenharmony_ci    const Norm2AllModes *allModes=Norm2AllModes::getNFKCInstance(errorCode);
3901cb0ef41Sopenharmony_ci    return allModes!=nullptr ? allModes->impl : nullptr;
3911cb0ef41Sopenharmony_ci}
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ciconst Normalizer2Impl *
3941cb0ef41Sopenharmony_ciNormalizer2Factory::getNFKC_CFImpl(UErrorCode &errorCode) {
3951cb0ef41Sopenharmony_ci    const Norm2AllModes *allModes=Norm2AllModes::getNFKC_CFInstance(errorCode);
3961cb0ef41Sopenharmony_ci    return allModes!=nullptr ? allModes->impl : nullptr;
3971cb0ef41Sopenharmony_ci}
3981cb0ef41Sopenharmony_ci
3991cb0ef41Sopenharmony_ciU_NAMESPACE_END
4001cb0ef41Sopenharmony_ci
4011cb0ef41Sopenharmony_ci// C API ------------------------------------------------------------------- ***
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ciU_NAMESPACE_USE
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ciU_CAPI const UNormalizer2 * U_EXPORT2
4061cb0ef41Sopenharmony_ciunorm2_getNFKCInstance(UErrorCode *pErrorCode) {
4071cb0ef41Sopenharmony_ci    return (const UNormalizer2 *)Normalizer2::getNFKCInstance(*pErrorCode);
4081cb0ef41Sopenharmony_ci}
4091cb0ef41Sopenharmony_ci
4101cb0ef41Sopenharmony_ciU_CAPI const UNormalizer2 * U_EXPORT2
4111cb0ef41Sopenharmony_ciunorm2_getNFKDInstance(UErrorCode *pErrorCode) {
4121cb0ef41Sopenharmony_ci    return (const UNormalizer2 *)Normalizer2::getNFKDInstance(*pErrorCode);
4131cb0ef41Sopenharmony_ci}
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ciU_CAPI const UNormalizer2 * U_EXPORT2
4161cb0ef41Sopenharmony_ciunorm2_getNFKCCasefoldInstance(UErrorCode *pErrorCode) {
4171cb0ef41Sopenharmony_ci    return (const UNormalizer2 *)Normalizer2::getNFKCCasefoldInstance(*pErrorCode);
4181cb0ef41Sopenharmony_ci}
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_ciU_CAPI const UNormalizer2 * U_EXPORT2
4211cb0ef41Sopenharmony_ciunorm2_getNFKCSimpleCasefoldInstance(UErrorCode *pErrorCode) {
4221cb0ef41Sopenharmony_ci    return (const UNormalizer2 *)Normalizer2::getNFKCSimpleCasefoldInstance(*pErrorCode);
4231cb0ef41Sopenharmony_ci}
4241cb0ef41Sopenharmony_ci
4251cb0ef41Sopenharmony_ciU_CAPI const UNormalizer2 * U_EXPORT2
4261cb0ef41Sopenharmony_ciunorm2_getInstance(const char *packageName,
4271cb0ef41Sopenharmony_ci                   const char *name,
4281cb0ef41Sopenharmony_ci                   UNormalization2Mode mode,
4291cb0ef41Sopenharmony_ci                   UErrorCode *pErrorCode) {
4301cb0ef41Sopenharmony_ci    return (const UNormalizer2 *)Normalizer2::getInstance(packageName, name, mode, *pErrorCode);
4311cb0ef41Sopenharmony_ci}
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_ciU_CFUNC UNormalizationCheckResult
4341cb0ef41Sopenharmony_ciunorm_getQuickCheck(UChar32 c, UNormalizationMode mode) {
4351cb0ef41Sopenharmony_ci    if(mode<=UNORM_NONE || UNORM_FCD<=mode) {
4361cb0ef41Sopenharmony_ci        return UNORM_YES;
4371cb0ef41Sopenharmony_ci    }
4381cb0ef41Sopenharmony_ci    UErrorCode errorCode=U_ZERO_ERROR;
4391cb0ef41Sopenharmony_ci    const Normalizer2 *norm2=Normalizer2Factory::getInstance(mode, errorCode);
4401cb0ef41Sopenharmony_ci    if(U_SUCCESS(errorCode)) {
4411cb0ef41Sopenharmony_ci        return ((const Normalizer2WithImpl *)norm2)->getQuickCheck(c);
4421cb0ef41Sopenharmony_ci    } else {
4431cb0ef41Sopenharmony_ci        return UNORM_MAYBE;
4441cb0ef41Sopenharmony_ci    }
4451cb0ef41Sopenharmony_ci}
4461cb0ef41Sopenharmony_ci
4471cb0ef41Sopenharmony_ci#endif  // !UCONFIG_NO_NORMALIZATION
448