tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

collationroot.cpp (4599B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 *******************************************************************************
      5 * Copyright (C) 2012-2014, International Business Machines
      6 * Corporation and others.  All Rights Reserved.
      7 *******************************************************************************
      8 * collationroot.cpp
      9 *
     10 * created on: 2012dec17
     11 * created by: Markus W. Scherer
     12 */
     13 
     14 #include "unicode/utypes.h"
     15 
     16 #if !UCONFIG_NO_COLLATION
     17 
     18 #include "unicode/coll.h"
     19 #include "unicode/udata.h"
     20 #include "collation.h"
     21 #include "collationdata.h"
     22 #include "collationdatareader.h"
     23 #include "collationroot.h"
     24 #include "collationsettings.h"
     25 #include "collationtailoring.h"
     26 #include "normalizer2impl.h"
     27 #include "ucln_in.h"
     28 #include "udatamem.h"
     29 #include "umutex.h"
     30 #include "umapfile.h"
     31 
     32 U_NAMESPACE_BEGIN
     33 
     34 namespace {
     35 
     36 const CollationCacheEntry *rootSingleton = nullptr;
     37 UInitOnce initOnce{};
     38 
     39 }  // namespace
     40 
     41 U_CDECL_BEGIN
     42 
     43 static UBool U_CALLCONV uprv_collation_root_cleanup() {
     44    SharedObject::clearPtr(rootSingleton);
     45    initOnce.reset();
     46    return true;
     47 }
     48 
     49 U_CDECL_END
     50 
     51 UDataMemory*
     52 CollationRoot::loadFromFile(const char* ucadataPath, UErrorCode &errorCode) {
     53    UDataMemory dataMemory;
     54    UDataMemory  *rDataMem = nullptr;
     55    if (U_FAILURE(errorCode)) {
     56        return nullptr;
     57    }
     58    if (uprv_mapFile(&dataMemory, ucadataPath, &errorCode)) {
     59        if (dataMemory.pHeader->dataHeader.magic1 == 0xda &&
     60            dataMemory.pHeader->dataHeader.magic2 == 0x27 &&
     61            CollationDataReader::isAcceptable(nullptr, "icu", "ucadata", &dataMemory.pHeader->info)) {
     62            rDataMem = UDataMemory_createNewInstance(&errorCode);
     63            if (U_FAILURE(errorCode)) {
     64                return nullptr;
     65            }
     66            rDataMem->pHeader = dataMemory.pHeader;
     67            rDataMem->mapAddr = dataMemory.mapAddr;
     68            rDataMem->map = dataMemory.map;
     69            return rDataMem;
     70        }
     71        errorCode = U_INVALID_FORMAT_ERROR;
     72        return nullptr;
     73    }
     74    errorCode = U_MISSING_RESOURCE_ERROR;
     75    return nullptr;
     76 }
     77 
     78 void U_CALLCONV
     79 CollationRoot::load(const char* ucadataPath, UErrorCode &errorCode) {
     80    if(U_FAILURE(errorCode)) { return; }
     81    LocalPointer<CollationTailoring> t(new CollationTailoring(nullptr));
     82    if(t.isNull() || t->isBogus()) {
     83        errorCode = U_MEMORY_ALLOCATION_ERROR;
     84        return;
     85    }
     86    t->memory = ucadataPath ? CollationRoot::loadFromFile(ucadataPath, errorCode) :
     87                              udata_openChoice(U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "coll",
     88                                               "icu", "ucadata",
     89                                               CollationDataReader::isAcceptable,
     90                                               t->version, &errorCode);
     91    if(U_FAILURE(errorCode)) { return; }
     92    const uint8_t *inBytes = static_cast<const uint8_t *>(udata_getMemory(t->memory));
     93    CollationDataReader::read(nullptr, inBytes, udata_getLength(t->memory), *t, errorCode);
     94    if(U_FAILURE(errorCode)) { return; }
     95    ucln_i18n_registerCleanup(UCLN_I18N_COLLATION_ROOT, uprv_collation_root_cleanup);
     96    CollationCacheEntry *entry = new CollationCacheEntry(Locale::getRoot(), t.getAlias());
     97    if(entry != nullptr) {
     98        t.orphan();  // The rootSingleton took ownership of the tailoring.
     99        entry->addRef();
    100        rootSingleton = entry;
    101    }
    102 }
    103 
    104 const CollationCacheEntry *
    105 CollationRoot::getRootCacheEntry(UErrorCode &errorCode) {
    106    umtx_initOnce(initOnce, CollationRoot::load, static_cast<const char*>(nullptr), errorCode);
    107    if(U_FAILURE(errorCode)) { return nullptr; }
    108    return rootSingleton;
    109 }
    110 
    111 const CollationTailoring *
    112 CollationRoot::getRoot(UErrorCode &errorCode) {
    113    umtx_initOnce(initOnce, CollationRoot::load, static_cast<const char*>(nullptr), errorCode);
    114    if(U_FAILURE(errorCode)) { return nullptr; }
    115    return rootSingleton->tailoring;
    116 }
    117 
    118 const CollationData *
    119 CollationRoot::getData(UErrorCode &errorCode) {
    120    const CollationTailoring *root = getRoot(errorCode);
    121    if(U_FAILURE(errorCode)) { return nullptr; }
    122    return root->data;
    123 }
    124 
    125 const CollationSettings *
    126 CollationRoot::getSettings(UErrorCode &errorCode) {
    127    const CollationTailoring *root = getRoot(errorCode);
    128    if(U_FAILURE(errorCode)) { return nullptr; }
    129    return root->settings;
    130 }
    131 
    132 void
    133 CollationRoot::forceLoadFromFile(const char* ucadataPath, UErrorCode &errorCode) {
    134    umtx_initOnce(initOnce, CollationRoot::load, ucadataPath, errorCode);
    135 }
    136 
    137 
    138 U_NAMESPACE_END
    139 
    140 #endif  // !UCONFIG_NO_COLLATION