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