160916893Sopenharmony_ci/*
260916893Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
360916893Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
460916893Sopenharmony_ci * you may not use this file except in compliance with the License.
560916893Sopenharmony_ci * You may obtain a copy of the License at
660916893Sopenharmony_ci *
760916893Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
860916893Sopenharmony_ci *
960916893Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1060916893Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1160916893Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1260916893Sopenharmony_ci * See the License for the specific language governing permissions and
1360916893Sopenharmony_ci * limitations under the License.
1460916893Sopenharmony_ci */
1560916893Sopenharmony_ci
1660916893Sopenharmony_ci#include "data_resource.h"
1760916893Sopenharmony_ci#include <cstring>
1860916893Sopenharmony_ci#include "i18n_memory_adapter.h"
1960916893Sopenharmony_ci#include "securec.h"
2060916893Sopenharmony_ci#include "str_util.h"
2160916893Sopenharmony_ci
2260916893Sopenharmony_ciusing namespace OHOS::I18N;
2360916893Sopenharmony_ciusing namespace std;
2460916893Sopenharmony_ci
2560916893Sopenharmony_ci#ifdef I18N_PRODUCT
2660916893Sopenharmony_cistatic const char *DATA_RESOURCE_PATH = "system/i18n/i18n.dat";
2760916893Sopenharmony_ci#else
2860916893Sopenharmony_cistatic const char *DATA_RESOURCE_PATH = "/storage/data/i18n.dat";
2960916893Sopenharmony_ci#endif
3060916893Sopenharmony_ci
3160916893Sopenharmony_ciDataResource::DataResource(const LocaleInfo *localeInfo)
3260916893Sopenharmony_ci{
3360916893Sopenharmony_ci    uint32_t enMask = LocaleInfo("en", "US").GetMask();
3460916893Sopenharmony_ci    if (localeInfo == nullptr) {
3560916893Sopenharmony_ci        localeMask = enMask;
3660916893Sopenharmony_ci    } else {
3760916893Sopenharmony_ci        localeMask = localeInfo->GetMask();
3860916893Sopenharmony_ci        if (localeInfo->IsDefaultLocale()) {
3960916893Sopenharmony_ci            fallbackMask = 0;
4060916893Sopenharmony_ci        } else {
4160916893Sopenharmony_ci            fallbackMask = GetFallbackMask(*localeInfo);
4260916893Sopenharmony_ci        }
4360916893Sopenharmony_ci        if ((fallbackMask != 0) && (fallbackMask != enMask)) {
4460916893Sopenharmony_ci            defaultMask = enMask;
4560916893Sopenharmony_ci        }
4660916893Sopenharmony_ci    }
4760916893Sopenharmony_ci    for (int i = 0; i < DataResourceType::RESOURCE_TYPE_END; ++i) {
4860916893Sopenharmony_ci        loaded[i] = DataResourceType::RESOURCE_TYPE_END;
4960916893Sopenharmony_ci    }
5060916893Sopenharmony_ci}
5160916893Sopenharmony_ci
5260916893Sopenharmony_ciDataResource::~DataResource()
5360916893Sopenharmony_ci{
5460916893Sopenharmony_ci    if (resourceIndex != nullptr) {
5560916893Sopenharmony_ci        I18nFree(static_cast<void *>(resourceIndex));
5660916893Sopenharmony_ci    }
5760916893Sopenharmony_ci    if (fallbackResourceIndex) {
5860916893Sopenharmony_ci        I18nFree(static_cast<void *>(fallbackResourceIndex));
5960916893Sopenharmony_ci    }
6060916893Sopenharmony_ci    if (defaultResourceIndex) {
6160916893Sopenharmony_ci        I18nFree(static_cast<void *>(defaultResourceIndex));
6260916893Sopenharmony_ci    }
6360916893Sopenharmony_ci    FreeResource();
6460916893Sopenharmony_ci}
6560916893Sopenharmony_ci
6660916893Sopenharmony_civoid DataResource::FreeResource()
6760916893Sopenharmony_ci{
6860916893Sopenharmony_ci    if (resource != nullptr) {
6960916893Sopenharmony_ci        while (resourceCount > 0) {
7060916893Sopenharmony_ci            I18nFree(static_cast<void *>(resource[resourceCount - 1]));
7160916893Sopenharmony_ci            --resourceCount;
7260916893Sopenharmony_ci        }
7360916893Sopenharmony_ci    }
7460916893Sopenharmony_ci    I18nFree(static_cast<void *>(resource));
7560916893Sopenharmony_ci    if (fallbackResource != nullptr) {
7660916893Sopenharmony_ci        while (fallbackResourceCount > 0) {
7760916893Sopenharmony_ci            I18nFree(static_cast<void *>(fallbackResource[fallbackResourceCount - 1]));
7860916893Sopenharmony_ci            --fallbackResourceCount;
7960916893Sopenharmony_ci        }
8060916893Sopenharmony_ci    }
8160916893Sopenharmony_ci    I18nFree(static_cast<void *>(fallbackResource));
8260916893Sopenharmony_ci    if (defaultResource != nullptr) {
8360916893Sopenharmony_ci        while (defaultResourceCount > 0) {
8460916893Sopenharmony_ci            I18nFree(static_cast<void *>(defaultResource[defaultResourceCount - 1]));
8560916893Sopenharmony_ci            --defaultResourceCount;
8660916893Sopenharmony_ci        }
8760916893Sopenharmony_ci    }
8860916893Sopenharmony_ci    I18nFree(static_cast<void *>(defaultResource));
8960916893Sopenharmony_ci}
9060916893Sopenharmony_ci
9160916893Sopenharmony_cichar *DataResource::GetString(DataResourceType type) const
9260916893Sopenharmony_ci{
9360916893Sopenharmony_ci    uint32_t index = static_cast<uint32_t>(type);
9460916893Sopenharmony_ci    return GetString(index);
9560916893Sopenharmony_ci}
9660916893Sopenharmony_ci
9760916893Sopenharmony_cichar *DataResource::GetString(uint32_t index) const
9860916893Sopenharmony_ci{
9960916893Sopenharmony_ci    if (index >= DataResourceType::RESOURCE_TYPE_END) {
10060916893Sopenharmony_ci        return nullptr;
10160916893Sopenharmony_ci    }
10260916893Sopenharmony_ci    uint32_t targetType = loaded[index];
10360916893Sopenharmony_ci    if (targetType == DataResourceType::RESOURCE_TYPE_END) {
10460916893Sopenharmony_ci        return nullptr;
10560916893Sopenharmony_ci    }
10660916893Sopenharmony_ci    switch (targetType) {
10760916893Sopenharmony_ci        case LocaleDataType::RESOURCE: {
10860916893Sopenharmony_ci            return BinarySearchString(resourceIndex, resourceCount, index, resource, resourceCount);
10960916893Sopenharmony_ci        }
11060916893Sopenharmony_ci        case LocaleDataType::FALLBACK_RESOURCE: {
11160916893Sopenharmony_ci            return BinarySearchString(fallbackResourceIndex, fallbackResourceCount, index,
11260916893Sopenharmony_ci                fallbackResource, fallbackResourceCount);
11360916893Sopenharmony_ci        }
11460916893Sopenharmony_ci        default: {
11560916893Sopenharmony_ci            return BinarySearchString(defaultResourceIndex, defaultResourceCount, index,
11660916893Sopenharmony_ci                defaultResource, defaultResourceCount);
11760916893Sopenharmony_ci        }
11860916893Sopenharmony_ci    }
11960916893Sopenharmony_ci}
12060916893Sopenharmony_ci
12160916893Sopenharmony_cichar *DataResource::BinarySearchString(uint32_t *indexArray, uint32_t length, uint32_t target,
12260916893Sopenharmony_ci    char **stringArray, uint32_t stringLength) const
12360916893Sopenharmony_ci{
12460916893Sopenharmony_ci    if ((indexArray == nullptr) || (stringArray == nullptr) || (stringLength == 0) || (length == 0)) {
12560916893Sopenharmony_ci        return nullptr;
12660916893Sopenharmony_ci    }
12760916893Sopenharmony_ci    int32_t low = 0;
12860916893Sopenharmony_ci    int32_t high = static_cast<int32_t>(length - 1);
12960916893Sopenharmony_ci    while (low <= high) {
13060916893Sopenharmony_ci        int32_t mid = low + (high - low) / 2;
13160916893Sopenharmony_ci        if (mid > static_cast<int32_t>(stringLength)) {
13260916893Sopenharmony_ci            return nullptr;
13360916893Sopenharmony_ci        }
13460916893Sopenharmony_ci        uint32_t temp = indexArray[mid];
13560916893Sopenharmony_ci        if (temp == target) {
13660916893Sopenharmony_ci            return stringArray[mid];
13760916893Sopenharmony_ci        } else if (temp < target) {
13860916893Sopenharmony_ci            low = mid + 1;
13960916893Sopenharmony_ci        } else {
14060916893Sopenharmony_ci            high = mid - 1;
14160916893Sopenharmony_ci        }
14260916893Sopenharmony_ci    }
14360916893Sopenharmony_ci    return nullptr;
14460916893Sopenharmony_ci}
14560916893Sopenharmony_ci
14660916893Sopenharmony_cibool DataResource::Init(void)
14760916893Sopenharmony_ci{
14860916893Sopenharmony_ci    int32_t infile = open(DATA_RESOURCE_PATH, O_RDONLY);
14960916893Sopenharmony_ci    if (infile < 0) {
15060916893Sopenharmony_ci        return false;
15160916893Sopenharmony_ci    }
15260916893Sopenharmony_ci    bool ret = ReadHeader(infile);
15360916893Sopenharmony_ci    if (!ret) {
15460916893Sopenharmony_ci        close(infile);
15560916893Sopenharmony_ci        return false;
15660916893Sopenharmony_ci    }
15760916893Sopenharmony_ci    if ((localesCount < 1) || (localesCount > MAX_LOCALE_ITEM_SIZE)) {
15860916893Sopenharmony_ci        close(infile);
15960916893Sopenharmony_ci        return false;
16060916893Sopenharmony_ci    }
16160916893Sopenharmony_ci    ret = PrepareData(infile);
16260916893Sopenharmony_ci    close(infile);
16360916893Sopenharmony_ci    return ret;
16460916893Sopenharmony_ci}
16560916893Sopenharmony_ci
16660916893Sopenharmony_cibool DataResource::ReadHeader(int32_t infile)
16760916893Sopenharmony_ci{
16860916893Sopenharmony_ci    int32_t seekSize = lseek(infile, GLOBAL_RESOURCE_HEADER_SKIP, SEEK_SET);
16960916893Sopenharmony_ci    if (seekSize < 0) {
17060916893Sopenharmony_ci        return false;
17160916893Sopenharmony_ci    }
17260916893Sopenharmony_ci    char cache[GLOBAL_RESOURCE_HEADER_LEFT] = {0};
17360916893Sopenharmony_ci    int32_t readSize = read(infile, cache, GLOBAL_RESOURCE_HEADER_LEFT);
17460916893Sopenharmony_ci    if (readSize != GLOBAL_RESOURCE_HEADER_LEFT) {
17560916893Sopenharmony_ci        return false;
17660916893Sopenharmony_ci    }
17760916893Sopenharmony_ci    localesCount = ((static_cast<unsigned char>(cache[0]) << SHIFT_ONE_BYTE) | (static_cast<unsigned char>(cache[1])));
17860916893Sopenharmony_ci    stringPoolOffset = ((static_cast<unsigned char>(cache[GLOBAL_RESOURCE_INDEX_OFFSET]) << SHIFT_ONE_BYTE) |
17960916893Sopenharmony_ci        (static_cast<unsigned char>(cache[GLOBAL_RESOURCE_INDEX_OFFSET + 1])));
18060916893Sopenharmony_ci    return true;
18160916893Sopenharmony_ci}
18260916893Sopenharmony_ci
18360916893Sopenharmony_cibool DataResource::PrepareData(int32_t infile)
18460916893Sopenharmony_ci{
18560916893Sopenharmony_ci    uint32_t localeSize = localesCount * GLOBAL_LOCALE_MASK_ITEM_SIZE;
18660916893Sopenharmony_ci    char *locales = reinterpret_cast<char *>(I18nMalloc(localeSize));
18760916893Sopenharmony_ci    if (locales == nullptr) {
18860916893Sopenharmony_ci        return false;
18960916893Sopenharmony_ci    }
19060916893Sopenharmony_ci    int32_t readSize = read(infile, locales, localeSize);
19160916893Sopenharmony_ci    if (readSize < 0 || localeSize != static_cast<uint32_t>(readSize)) {
19260916893Sopenharmony_ci        I18nFree(static_cast<void *>(locales));
19360916893Sopenharmony_ci        return false;
19460916893Sopenharmony_ci    }
19560916893Sopenharmony_ci    int32_t localeIndex = BinarySearchLocale(localeMask, reinterpret_cast<unsigned char*>(locales));
19660916893Sopenharmony_ci    int32_t fallbackLocaleIndex = -1;
19760916893Sopenharmony_ci    int32_t defaultLocaleIndex = -1;
19860916893Sopenharmony_ci    GetFallbackAndDefaultLocaleIndex(fallbackLocaleIndex, defaultLocaleIndex, locales);
19960916893Sopenharmony_ci    uint32_t configOffset = 0;
20060916893Sopenharmony_ci    if (localeIndex >= 0) {
20160916893Sopenharmony_ci        configOffset = ConvertUChar(reinterpret_cast<unsigned char*>(locales + GLOBAL_LOCALE_MASK_ITEM_SIZE *
20260916893Sopenharmony_ci            localeIndex + GLOBAL_RESOURCE_MASK_OFFSET));
20360916893Sopenharmony_ci        resourceCount = ConvertUChar(reinterpret_cast<unsigned char*>(locales + GLOBAL_LOCALE_MASK_ITEM_SIZE *
20460916893Sopenharmony_ci            localeIndex + GLOBAL_RESOURCE_MASK_OFFSET + GLOBAL_RESOURCE_INDEX_OFFSET));
20560916893Sopenharmony_ci    }
20660916893Sopenharmony_ci    uint32_t fallbackConfigOffset = 0;
20760916893Sopenharmony_ci    uint32_t defaultConfigOffset = 0;
20860916893Sopenharmony_ci    GetFallbackAndDefaultInfo(fallbackLocaleIndex, defaultLocaleIndex, fallbackConfigOffset, defaultConfigOffset,
20960916893Sopenharmony_ci        locales);
21060916893Sopenharmony_ci    I18nFree(static_cast<void *>(locales));
21160916893Sopenharmony_ci    bool ret = true;
21260916893Sopenharmony_ci    if (IsTypeNeeded(localeIndex, resourceCount)) {
21360916893Sopenharmony_ci        ret = PrepareLocaleData(infile, configOffset, resourceCount, LocaleDataType::RESOURCE);
21460916893Sopenharmony_ci    }
21560916893Sopenharmony_ci    if (IsTypeNeeded(fallbackLocaleIndex, fallbackResourceCount)) {
21660916893Sopenharmony_ci        ret = PrepareLocaleData(infile, fallbackConfigOffset, fallbackResourceCount,
21760916893Sopenharmony_ci            LocaleDataType::FALLBACK_RESOURCE);
21860916893Sopenharmony_ci    }
21960916893Sopenharmony_ci    if (IsTypeNeeded(defaultLocaleIndex, defaultResourceCount)) {
22060916893Sopenharmony_ci        ret = PrepareLocaleData(infile, defaultConfigOffset, defaultResourceCount, LocaleDataType::DEFAULT_RESOURCE);
22160916893Sopenharmony_ci    }
22260916893Sopenharmony_ci    return ret;
22360916893Sopenharmony_ci}
22460916893Sopenharmony_ci
22560916893Sopenharmony_cibool DataResource::IsTypeNeeded(int32_t index, uint32_t count)
22660916893Sopenharmony_ci{
22760916893Sopenharmony_ci    if ((index < 0) || FullLoaded()) {
22860916893Sopenharmony_ci        return false;
22960916893Sopenharmony_ci    }
23060916893Sopenharmony_ci    return (count > 0) && (count <= DataResourceType::RESOURCE_TYPE_END);
23160916893Sopenharmony_ci}
23260916893Sopenharmony_ci
23360916893Sopenharmony_civoid DataResource::GetFallbackAndDefaultLocaleIndex(int32_t &fallbackLocaleIndex, int32_t &defaultLocaleIndex,
23460916893Sopenharmony_ci    char *locales)
23560916893Sopenharmony_ci{
23660916893Sopenharmony_ci    if (fallbackMask != 0) {
23760916893Sopenharmony_ci        fallbackLocaleIndex = BinarySearchLocale(fallbackMask, reinterpret_cast<unsigned char*>(locales));
23860916893Sopenharmony_ci    }
23960916893Sopenharmony_ci    if (defaultMask != 0) {
24060916893Sopenharmony_ci        defaultLocaleIndex = BinarySearchLocale(defaultMask, reinterpret_cast<unsigned char*>(locales));
24160916893Sopenharmony_ci    }
24260916893Sopenharmony_ci}
24360916893Sopenharmony_ci
24460916893Sopenharmony_civoid DataResource::GetFallbackAndDefaultInfo(const int32_t &fallbackLocaleIndex, const int32_t &defaultLocaleIndex,
24560916893Sopenharmony_ci    uint32_t &fallbackConfigOffset, uint32_t &defaultConfigOffset, char* locales)
24660916893Sopenharmony_ci{
24760916893Sopenharmony_ci    if (fallbackLocaleIndex != -1) {
24860916893Sopenharmony_ci        fallbackConfigOffset = ConvertUChar(reinterpret_cast<unsigned char*>(locales + GLOBAL_LOCALE_MASK_ITEM_SIZE *
24960916893Sopenharmony_ci            fallbackLocaleIndex + GLOBAL_RESOURCE_MASK_OFFSET));
25060916893Sopenharmony_ci        fallbackResourceCount = ConvertUChar(reinterpret_cast<unsigned char*>(locales + GLOBAL_LOCALE_MASK_ITEM_SIZE *
25160916893Sopenharmony_ci            fallbackLocaleIndex + GLOBAL_RESOURCE_MASK_OFFSET + GLOBAL_RESOURCE_INDEX_OFFSET));
25260916893Sopenharmony_ci    }
25360916893Sopenharmony_ci    if (defaultLocaleIndex != -1) {
25460916893Sopenharmony_ci        defaultConfigOffset = ConvertUChar(reinterpret_cast<unsigned char*>(locales + GLOBAL_LOCALE_MASK_ITEM_SIZE *
25560916893Sopenharmony_ci            defaultLocaleIndex + GLOBAL_RESOURCE_MASK_OFFSET));
25660916893Sopenharmony_ci        defaultResourceCount = ConvertUChar(reinterpret_cast<unsigned char*>(locales + GLOBAL_LOCALE_MASK_ITEM_SIZE *
25760916893Sopenharmony_ci            defaultLocaleIndex + GLOBAL_RESOURCE_MASK_OFFSET + GLOBAL_RESOURCE_INDEX_OFFSET));
25860916893Sopenharmony_ci    }
25960916893Sopenharmony_ci}
26060916893Sopenharmony_ci
26160916893Sopenharmony_cibool DataResource::PrepareLocaleData(int32_t infile, uint32_t configOffset, uint32_t count, LocaleDataType type)
26260916893Sopenharmony_ci{
26360916893Sopenharmony_ci    currentType = type;
26460916893Sopenharmony_ci    if (count < 1 || count > DataResourceType::RESOURCE_TYPE_END) {
26560916893Sopenharmony_ci        return false;
26660916893Sopenharmony_ci    }
26760916893Sopenharmony_ci    uint32_t resourceSize = count * GLOBAL_RESOURCE_CONFIG_SIZE;
26860916893Sopenharmony_ci    char *configs = reinterpret_cast<char *>(I18nMalloc(resourceSize));
26960916893Sopenharmony_ci    if (configs == nullptr) {
27060916893Sopenharmony_ci        return false;
27160916893Sopenharmony_ci    }
27260916893Sopenharmony_ci    int32_t seekSize = lseek(infile, configOffset, SEEK_SET);
27360916893Sopenharmony_ci    if (configOffset != static_cast<uint32_t>(seekSize)) {
27460916893Sopenharmony_ci        I18nFree(static_cast<void *>(configs));
27560916893Sopenharmony_ci        return false;
27660916893Sopenharmony_ci    }
27760916893Sopenharmony_ci    int32_t readSize = read(infile, configs, resourceSize);
27860916893Sopenharmony_ci    if (readSize != resourceSize) {
27960916893Sopenharmony_ci        I18nFree(static_cast<void *>(configs));
28060916893Sopenharmony_ci        return false;
28160916893Sopenharmony_ci    }
28260916893Sopenharmony_ci    bool ret = GetStringFromStringPool(configs, resourceSize, infile, type);
28360916893Sopenharmony_ci    I18nFree(static_cast<void *>(configs));
28460916893Sopenharmony_ci    return ret;
28560916893Sopenharmony_ci}
28660916893Sopenharmony_ci
28760916893Sopenharmony_ciuint32_t DataResource::GetFinalCount(char *configs, uint32_t configSize, LocaleDataType type)
28860916893Sopenharmony_ci{
28960916893Sopenharmony_ci    uint32_t count = 0;
29060916893Sopenharmony_ci    switch (type) {
29160916893Sopenharmony_ci        case LocaleDataType::RESOURCE: {
29260916893Sopenharmony_ci            count = resourceCount;
29360916893Sopenharmony_ci            break;
29460916893Sopenharmony_ci        }
29560916893Sopenharmony_ci        case LocaleDataType::FALLBACK_RESOURCE: {
29660916893Sopenharmony_ci            count = fallbackResourceCount;
29760916893Sopenharmony_ci            break;
29860916893Sopenharmony_ci        }
29960916893Sopenharmony_ci        default: {
30060916893Sopenharmony_ci            count = defaultResourceCount;
30160916893Sopenharmony_ci        }
30260916893Sopenharmony_ci    }
30360916893Sopenharmony_ci    uint32_t finalCount = 0;
30460916893Sopenharmony_ci    for (uint32_t i = 0; i < count; ++i) {
30560916893Sopenharmony_ci        uint32_t index = ConvertUChar(reinterpret_cast<unsigned char*>(configs + i * GLOBAL_RESOURCE_CONFIG_SIZE));
30660916893Sopenharmony_ci        if (index >= DataResourceType::RESOURCE_TYPE_END) {
30760916893Sopenharmony_ci            return 0;
30860916893Sopenharmony_ci        }
30960916893Sopenharmony_ci        if (loaded[index] != DataResourceType::RESOURCE_TYPE_END) {
31060916893Sopenharmony_ci            continue;
31160916893Sopenharmony_ci        } else {
31260916893Sopenharmony_ci            loaded[index] = type;
31360916893Sopenharmony_ci        }
31460916893Sopenharmony_ci        ++finalCount;
31560916893Sopenharmony_ci    }
31660916893Sopenharmony_ci    return finalCount;
31760916893Sopenharmony_ci}
31860916893Sopenharmony_ci
31960916893Sopenharmony_cibool DataResource::GetStringFromStringPool(char *configs, const uint32_t configsSize, int32_t infile,
32060916893Sopenharmony_ci    LocaleDataType type)
32160916893Sopenharmony_ci{
32260916893Sopenharmony_ci    uint32_t finalCount = GetFinalCount(configs, configsSize, type);
32360916893Sopenharmony_ci    if (finalCount == 0) {
32460916893Sopenharmony_ci        return true;
32560916893Sopenharmony_ci    }
32660916893Sopenharmony_ci    uint32_t **index = nullptr;
32760916893Sopenharmony_ci    char ***wanted = nullptr;
32860916893Sopenharmony_ci    uint32_t originalCount = 0;
32960916893Sopenharmony_ci    switch (type) {
33060916893Sopenharmony_ci        case LocaleDataType::RESOURCE: {
33160916893Sopenharmony_ci            originalCount = resourceCount;
33260916893Sopenharmony_ci            resourceCount = finalCount;
33360916893Sopenharmony_ci            index = &resourceIndex;
33460916893Sopenharmony_ci            wanted = &resource;
33560916893Sopenharmony_ci            break;
33660916893Sopenharmony_ci        }
33760916893Sopenharmony_ci        case LocaleDataType::FALLBACK_RESOURCE: {
33860916893Sopenharmony_ci            originalCount = fallbackResourceCount;
33960916893Sopenharmony_ci            fallbackResourceCount = finalCount;
34060916893Sopenharmony_ci            index = &fallbackResourceIndex;
34160916893Sopenharmony_ci            wanted = &fallbackResource;
34260916893Sopenharmony_ci            break;
34360916893Sopenharmony_ci        }
34460916893Sopenharmony_ci        default: {
34560916893Sopenharmony_ci            originalCount = defaultResourceCount;
34660916893Sopenharmony_ci            defaultResourceCount = finalCount;
34760916893Sopenharmony_ci            index = &defaultResourceIndex;
34860916893Sopenharmony_ci            wanted = &defaultResource;
34960916893Sopenharmony_ci            break;
35060916893Sopenharmony_ci        }
35160916893Sopenharmony_ci    }
35260916893Sopenharmony_ci    if (!ApplyForResource(index, wanted, finalCount)) {
35360916893Sopenharmony_ci        return false;
35460916893Sopenharmony_ci    }
35560916893Sopenharmony_ci    return Retrieve(configs, configsSize, infile, originalCount, type);
35660916893Sopenharmony_ci}
35760916893Sopenharmony_ci
35860916893Sopenharmony_civoid DataResource::GetType(char** &adjustResource, uint32_t* &adjustResourceIndex, uint32_t &count,
35960916893Sopenharmony_ci    LocaleDataType type)
36060916893Sopenharmony_ci{
36160916893Sopenharmony_ci    switch (type) {
36260916893Sopenharmony_ci        case LocaleDataType::RESOURCE: {
36360916893Sopenharmony_ci            adjustResource = resource;
36460916893Sopenharmony_ci            adjustResourceIndex = resourceIndex;
36560916893Sopenharmony_ci            count = resourceCount;
36660916893Sopenharmony_ci            break;
36760916893Sopenharmony_ci        }
36860916893Sopenharmony_ci        case LocaleDataType::FALLBACK_RESOURCE: {
36960916893Sopenharmony_ci            adjustResource = fallbackResource;
37060916893Sopenharmony_ci            adjustResourceIndex = fallbackResourceIndex;
37160916893Sopenharmony_ci            count = fallbackResourceCount;
37260916893Sopenharmony_ci            break;
37360916893Sopenharmony_ci        }
37460916893Sopenharmony_ci        default: {
37560916893Sopenharmony_ci            adjustResource = defaultResource;
37660916893Sopenharmony_ci            adjustResourceIndex = defaultResourceIndex;
37760916893Sopenharmony_ci            count = defaultResourceCount;
37860916893Sopenharmony_ci            break;
37960916893Sopenharmony_ci        }
38060916893Sopenharmony_ci    }
38160916893Sopenharmony_ci}
38260916893Sopenharmony_ci
38360916893Sopenharmony_cibool DataResource::Retrieve(char *configs, uint32_t configsSize, int32_t infile, const uint32_t orginalCount,
38460916893Sopenharmony_ci    LocaleDataType type)
38560916893Sopenharmony_ci{
38660916893Sopenharmony_ci    uint32_t count = 0;
38760916893Sopenharmony_ci    char **adjustResource = nullptr;
38860916893Sopenharmony_ci    uint32_t *adjustResourceIndex = nullptr;
38960916893Sopenharmony_ci    GetType(adjustResource, adjustResourceIndex, count, type);
39060916893Sopenharmony_ci    uint32_t currentIndex = 0;
39160916893Sopenharmony_ci    for (uint32_t i = 0; i < orginalCount; ++i) {
39260916893Sopenharmony_ci        uint32_t index = ConvertUChar(reinterpret_cast<unsigned char*>(configs + i * GLOBAL_RESOURCE_CONFIG_SIZE));
39360916893Sopenharmony_ci        if (loaded[index] != type) {
39460916893Sopenharmony_ci            continue;
39560916893Sopenharmony_ci        }
39660916893Sopenharmony_ci        uint32_t offset = ConvertUChar(reinterpret_cast<unsigned char*>(configs + i *
39760916893Sopenharmony_ci            GLOBAL_RESOURCE_CONFIG_SIZE + GLOBAL_RESOURCE_INDEX_OFFSET));
39860916893Sopenharmony_ci        uint32_t length = ConvertUChar(reinterpret_cast<unsigned char*>(configs + i *
39960916893Sopenharmony_ci            GLOBAL_RESOURCE_CONFIG_SIZE + GLOBAL_RESOURCE_MASK_OFFSET));
40060916893Sopenharmony_ci        int32_t seekSize = lseek(infile, stringPoolOffset + offset, SEEK_SET);
40160916893Sopenharmony_ci        if ((length == 0) || (seekSize != static_cast<uint32_t>(stringPoolOffset + offset))) {
40260916893Sopenharmony_ci            adjustResource[currentIndex] = nullptr;
40360916893Sopenharmony_ci            adjustResourceIndex[currentIndex] = index;
40460916893Sopenharmony_ci        } else {
40560916893Sopenharmony_ci            char *temp = reinterpret_cast<char *>(I18nMalloc(length + 1));
40660916893Sopenharmony_ci            if (temp == nullptr) {
40760916893Sopenharmony_ci                loaded[index] = DataResourceType::RESOURCE_TYPE_END;
40860916893Sopenharmony_ci                return false;
40960916893Sopenharmony_ci            }
41060916893Sopenharmony_ci            int32_t readSize = read(infile, temp, length);
41160916893Sopenharmony_ci            temp[length] = 0;
41260916893Sopenharmony_ci            if ((readSize < 0) || (static_cast<uint32_t>(readSize) != length)) {
41360916893Sopenharmony_ci                I18nFree(static_cast<void *>(temp));
41460916893Sopenharmony_ci                return false;
41560916893Sopenharmony_ci            }
41660916893Sopenharmony_ci            adjustResource[currentIndex] = temp;
41760916893Sopenharmony_ci            adjustResourceIndex[currentIndex] = index;
41860916893Sopenharmony_ci        }
41960916893Sopenharmony_ci        ++currentIndex;
42060916893Sopenharmony_ci    }
42160916893Sopenharmony_ci    return true;
42260916893Sopenharmony_ci}
42360916893Sopenharmony_ci
42460916893Sopenharmony_cibool DataResource::ApplyForResource(uint32_t **index, char ***wanted, uint32_t totalCount)
42560916893Sopenharmony_ci{
42660916893Sopenharmony_ci    if ((index == nullptr) || (wanted == nullptr) || (totalCount == 0)) {
42760916893Sopenharmony_ci        return false;
42860916893Sopenharmony_ci    }
42960916893Sopenharmony_ci    *index = reinterpret_cast<uint32_t *>(I18nMalloc(sizeof(uint32_t) * totalCount));
43060916893Sopenharmony_ci    if (*index == nullptr) {
43160916893Sopenharmony_ci        return false;
43260916893Sopenharmony_ci    }
43360916893Sopenharmony_ci    *wanted = reinterpret_cast<char **>(I18nMalloc(sizeof(char *) * totalCount));
43460916893Sopenharmony_ci    if (*wanted == nullptr) {
43560916893Sopenharmony_ci        return false; // free *index in FreeResource
43660916893Sopenharmony_ci    }
43760916893Sopenharmony_ci    for (uint32_t i = 0; i < totalCount; ++i) {
43860916893Sopenharmony_ci        (*wanted)[i] = nullptr;
43960916893Sopenharmony_ci    }
44060916893Sopenharmony_ci    return true;
44160916893Sopenharmony_ci}
44260916893Sopenharmony_ci
44360916893Sopenharmony_ciint32_t DataResource::BinarySearchLocale(const uint32_t mask, unsigned char *locales)
44460916893Sopenharmony_ci{
44560916893Sopenharmony_ci    if ((locales == nullptr) || (localesCount == 0)) {
44660916893Sopenharmony_ci        return -1;
44760916893Sopenharmony_ci    }
44860916893Sopenharmony_ci    int32_t low = 0;
44960916893Sopenharmony_ci    int32_t high = static_cast<int32_t>(localesCount - 1);
45060916893Sopenharmony_ci    while (low <= high) {
45160916893Sopenharmony_ci        int32_t mid = low + (high - low) / 2;
45260916893Sopenharmony_ci        if (mid > 1024) { // locales count < 1024
45360916893Sopenharmony_ci            return -1;
45460916893Sopenharmony_ci        }
45560916893Sopenharmony_ci        uint32_t midMask = ConvertUint(locales + mid * GLOBAL_LOCALE_MASK_ITEM_SIZE);
45660916893Sopenharmony_ci        if (midMask == mask) {
45760916893Sopenharmony_ci            return mid;
45860916893Sopenharmony_ci        } else if (midMask < mask) {
45960916893Sopenharmony_ci            low = mid + 1;
46060916893Sopenharmony_ci        } else {
46160916893Sopenharmony_ci            high = mid - 1;
46260916893Sopenharmony_ci        }
46360916893Sopenharmony_ci    }
46460916893Sopenharmony_ci    return -1;
46560916893Sopenharmony_ci}
46660916893Sopenharmony_ci
46760916893Sopenharmony_ciuint32_t DataResource::ConvertUint(unsigned char *src)
46860916893Sopenharmony_ci{
46960916893Sopenharmony_ci    if (src == nullptr) {
47060916893Sopenharmony_ci        return 0;
47160916893Sopenharmony_ci    }
47260916893Sopenharmony_ci    uint32_t ret = 0;
47360916893Sopenharmony_ci    ret |= (src[0] << SHIFT_THREE_BYTE); // 0 indicates first byte
47460916893Sopenharmony_ci    ret |= (src[1] << SHIFT_TWO_BYTE); // 1 indicates second byte
47560916893Sopenharmony_ci    ret |= (src[2] << SHIFT_ONE_BYTE); // 2 indicates third byte
47660916893Sopenharmony_ci    ret |= src[3]; // 3 indicates forth byte
47760916893Sopenharmony_ci    return ret;
47860916893Sopenharmony_ci}
47960916893Sopenharmony_ci
48060916893Sopenharmony_ciuint32_t DataResource::ConvertUChar(unsigned char *src)
48160916893Sopenharmony_ci{
48260916893Sopenharmony_ci    if (src == nullptr) {
48360916893Sopenharmony_ci        return 0;
48460916893Sopenharmony_ci    }
48560916893Sopenharmony_ci    uint32_t ret = 0;
48660916893Sopenharmony_ci    ret |= (src[0] << SHIFT_ONE_BYTE);
48760916893Sopenharmony_ci    ret |= src[1];
48860916893Sopenharmony_ci    return ret;
48960916893Sopenharmony_ci}
49060916893Sopenharmony_ci
49160916893Sopenharmony_cibool DataResource::FullLoaded()
49260916893Sopenharmony_ci{
49360916893Sopenharmony_ci    for (uint32_t i = 0; i < DataResourceType::RESOURCE_TYPE_END; ++i) {
49460916893Sopenharmony_ci        if (loaded[i] == DataResourceType::RESOURCE_TYPE_END) {
49560916893Sopenharmony_ci            return false;
49660916893Sopenharmony_ci        }
49760916893Sopenharmony_ci    }
49860916893Sopenharmony_ci    return true;
49960916893Sopenharmony_ci}
50060916893Sopenharmony_ci
50160916893Sopenharmony_ciuint32_t DataResource::GetFallbackMask(const LocaleInfo &src)
50260916893Sopenharmony_ci{
50360916893Sopenharmony_ci    const char *language = src.GetLanguage();
50460916893Sopenharmony_ci    const char *script = src.GetScript();
50560916893Sopenharmony_ci    const char *region = src.GetRegion();
50660916893Sopenharmony_ci    if ((language != nullptr) && (strcmp("en", language) == 0) && (script == nullptr)) {
50760916893Sopenharmony_ci        return LocaleInfo("en", "", "US").GetMask();
50860916893Sopenharmony_ci    }
50960916893Sopenharmony_ci    if (region == nullptr) {
51060916893Sopenharmony_ci        return LocaleInfo("en", "US").GetMask();
51160916893Sopenharmony_ci    }
51260916893Sopenharmony_ci    if (script == nullptr) {
51360916893Sopenharmony_ci        return LocaleInfo(language, "", "").GetMask();
51460916893Sopenharmony_ci    }
51560916893Sopenharmony_ci    return LocaleInfo(language, script, "").GetMask();
51660916893Sopenharmony_ci}
51760916893Sopenharmony_ci
51860916893Sopenharmony_civoid DataResource::GetString(DataResourceType type, std::string &ret) const
51960916893Sopenharmony_ci{
52060916893Sopenharmony_ci    uint32_t index = static_cast<uint32_t>(type);
52160916893Sopenharmony_ci    char *temp = GetString(index);
52260916893Sopenharmony_ci    if (temp == nullptr) {
52360916893Sopenharmony_ci        ret = "";
52460916893Sopenharmony_ci    } else {
52560916893Sopenharmony_ci        ret = temp;
52660916893Sopenharmony_ci    }
52760916893Sopenharmony_ci}
528