1ca0551cfSopenharmony_ci/*
2ca0551cfSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
3ca0551cfSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4ca0551cfSopenharmony_ci * you may not use this file except in compliance with the License.
5ca0551cfSopenharmony_ci * You may obtain a copy of the License at
6ca0551cfSopenharmony_ci *
7ca0551cfSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8ca0551cfSopenharmony_ci *
9ca0551cfSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10ca0551cfSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11ca0551cfSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12ca0551cfSopenharmony_ci * See the License for the specific language governing permissions and
13ca0551cfSopenharmony_ci * limitations under the License.
14ca0551cfSopenharmony_ci */
15ca0551cfSopenharmony_ci
16ca0551cfSopenharmony_ci#include "util/string_pool.h"
17ca0551cfSopenharmony_ci#include "securec.h"
18ca0551cfSopenharmony_ci#include "util/logger.h"
19ca0551cfSopenharmony_ci
20ca0551cfSopenharmony_cinamespace OHOS {
21ca0551cfSopenharmony_cinamespace Idl {
22ca0551cfSopenharmony_ciconst char* StringPool::TAG = "StringPool";
23ca0551cfSopenharmony_ci
24ca0551cfSopenharmony_ciStringPool::StringPool()
25ca0551cfSopenharmony_ci{
26ca0551cfSopenharmony_ci    data_ = reinterpret_cast<uint8_t *>(calloc(1, dataCapacity_));
27ca0551cfSopenharmony_ci    if (data_ == nullptr) {
28ca0551cfSopenharmony_ci        Logger::E(TAG, "Out of memory.");
29ca0551cfSopenharmony_ci    }
30ca0551cfSopenharmony_ci}
31ca0551cfSopenharmony_ci
32ca0551cfSopenharmony_ciStringPool::~StringPool()
33ca0551cfSopenharmony_ci{
34ca0551cfSopenharmony_ci    if (data_ != nullptr) {
35ca0551cfSopenharmony_ci        free(data_);
36ca0551cfSopenharmony_ci    }
37ca0551cfSopenharmony_ci}
38ca0551cfSopenharmony_ci
39ca0551cfSopenharmony_civoid StringPool::Add(const std::string& string)
40ca0551cfSopenharmony_ci{
41ca0551cfSopenharmony_ci    if (string.empty() || stringOffsets_.find(string) != stringOffsets_.end()) {
42ca0551cfSopenharmony_ci        return;
43ca0551cfSopenharmony_ci    }
44ca0551cfSopenharmony_ci
45ca0551cfSopenharmony_ci    ptrdiff_t offset = AddInternal(string);
46ca0551cfSopenharmony_ci    if (offset != -1) {
47ca0551cfSopenharmony_ci        stringOffsets_[string] = offset;
48ca0551cfSopenharmony_ci    }
49ca0551cfSopenharmony_ci}
50ca0551cfSopenharmony_ci
51ca0551cfSopenharmony_ciptrdiff_t StringPool::GetOffset(const std::string& string)
52ca0551cfSopenharmony_ci{
53ca0551cfSopenharmony_ci    return stringOffsets_[string];
54ca0551cfSopenharmony_ci}
55ca0551cfSopenharmony_ci
56ca0551cfSopenharmony_ciptrdiff_t StringPool::AddInternal(const std::string& string)
57ca0551cfSopenharmony_ci{
58ca0551cfSopenharmony_ci    if (!Grow(string.length() + 1)) {
59ca0551cfSopenharmony_ci        return -1;
60ca0551cfSopenharmony_ci    }
61ca0551cfSopenharmony_ci
62ca0551cfSopenharmony_ci    uint8_t* addr = data_ + dataOffset_;
63ca0551cfSopenharmony_ci    if (strcpy_s(reinterpret_cast<char *>(addr), dataCapacity_ - dataOffset_, string.c_str())) {
64ca0551cfSopenharmony_ci        Logger::E(TAG, "Error to copy str");
65ca0551cfSopenharmony_ci        return -1;
66ca0551cfSopenharmony_ci    }
67ca0551cfSopenharmony_ci    dataOffset_ += static_cast<ptrdiff_t>(string.length()) + 1;
68ca0551cfSopenharmony_ci    return addr - data_;
69ca0551cfSopenharmony_ci}
70ca0551cfSopenharmony_ci
71ca0551cfSopenharmony_cibool StringPool::Grow(size_t expand)
72ca0551cfSopenharmony_ci{
73ca0551cfSopenharmony_ci    size_t newSize = dataOffset_ + expand;
74ca0551cfSopenharmony_ci    if (newSize < dataCapacity_) {
75ca0551cfSopenharmony_ci        return true;
76ca0551cfSopenharmony_ci    }
77ca0551cfSopenharmony_ci    // 3->3x capacity expansion
78ca0551cfSopenharmony_ci    size_t step = dataCapacity_ * 3;
79ca0551cfSopenharmony_ci    newSize = step > newSize ? step : step + newSize;
80ca0551cfSopenharmony_ci    uint8_t* newData = reinterpret_cast<uint8_t *>(calloc(1, newSize));
81ca0551cfSopenharmony_ci    if (newData == nullptr) {
82ca0551cfSopenharmony_ci        Logger::E(TAG, "Out of memory.");
83ca0551cfSopenharmony_ci        return false;
84ca0551cfSopenharmony_ci    }
85ca0551cfSopenharmony_ci    errno_t ret = memcpy_s(newData, newSize, data_, dataOffset_);
86ca0551cfSopenharmony_ci    if (ret != EOK) {
87ca0551cfSopenharmony_ci        free(newData);
88ca0551cfSopenharmony_ci        newData = nullptr;
89ca0551cfSopenharmony_ci        return false;
90ca0551cfSopenharmony_ci    }
91ca0551cfSopenharmony_ci    free(data_);
92ca0551cfSopenharmony_ci    data_ = newData;
93ca0551cfSopenharmony_ci    dataCapacity_ = newSize;
94ca0551cfSopenharmony_ci    return true;
95ca0551cfSopenharmony_ci}
96ca0551cfSopenharmony_ci}
97ca0551cfSopenharmony_ci}
98