1 /*
2  * Copyright (c) 2023 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 #ifndef MEMPOOL_INCLUDE_MAPLE_STRING_H
17 #define MEMPOOL_INCLUDE_MAPLE_STRING_H
18 #include <cstring>
19 #include <climits>
20 #include "mempool.h"
21 #include "securec.h"
22 #include "mpl_logging.h"
23 
24 namespace maple {
25 class MapleString {
26 public:
27     MapleString() = default;
MapleString(MemPool *currMp)28     explicit MapleString(MemPool *currMp) : memPool(currMp) {}
29     MapleString(const MapleString &str);
30     MapleString(const char *str, MemPool *memPool);
31     MapleString(const char *str, size_t size, MemPool *memPool);  // copyin
32     MapleString(size_t size, MemPool *memPool);
33     MapleString(const MapleString &str, MemPool *memPool);
34     MapleString(const std::string &str, MemPool *memPool);
35     ~MapleString() = default;
36 
length() const37     size_t length() const
38     {
39         return dataLength;
40     }
41 
c_str()42     char *c_str()
43     {
44         return data;
45     }
46 
c_str() const47     const char *c_str() const
48     {
49         if (dataLength <= 0) {
50             return nullptr;
51         }
52         return data;
53     }
54 
operator [](const size_t x)55     char &operator[](const size_t x)
56     {
57         return data[x];
58     }
59 
operator [](const size_t x) const60     const char &operator[](const size_t x) const
61     {
62         return data[x];
63     }
64 
operator =(const char c)65     MapleString &operator=(const char c)
66     {
67         data = static_cast<char *>(memPool->Malloc(sizeof(char) << 1));
68         CHECK_FATAL(data != nullptr, "nullptr check");
69         data[0] = c;
70         data[1] = '\0';
71         dataLength = 1;
72         return *this;
73     }
74 
operator =(const char *str)75     MapleString &operator=(const char *str)
76     {
77         if (str == nullptr) {
78             return *this;
79         }
80         size_t size = strlen(str);
81         CHECK_FATAL(size <= UINT_MAX - 1, "str too large");
82 
83         // if data is null, old_size = 0, else +1
84         size_t oldSize = ((data == nullptr) ? 0 : (dataLength + 1));
85         if (oldSize < (1 + size)) {
86             data = static_cast<char *>(memPool->Realloc(data, oldSize * sizeof(char), (1 + size) * sizeof(char)));
87         }
88         CHECK_FATAL(data != nullptr, "null ptr check ");
89         if (size == 0) {
90             data[0] = '\0';
91             return *this;
92         }
93         errno_t eNum = memcpy_s(data, size + 1, str, size);
94         CHECK_FATAL(eNum == EOK, "memcpy_s failed");
95         dataLength = size;
96         CHECK_FATAL(data != nullptr, "null ptr check ");
97         data[dataLength] = '\0';
98         return *this;
99     }
100 
operator =(const std::string &str)101     MapleString &operator=(const std::string &str)
102     {
103         size_t size = str.length();
104         CHECK_FATAL(size <= UINT_MAX - 1, "str too large");
105 
106         size_t oldSize = (data == nullptr) ? 0 : (dataLength + 1);
107         if (oldSize < (1 + size)) {
108             data = static_cast<char *>(memPool->Realloc(data, oldSize * sizeof(char), (1 + size) * sizeof(char)));
109         }
110         CHECK_FATAL(data != nullptr, "null ptr check ");
111         if (size == 0) {
112             data[0] = '\0';
113             return *this;
114         }
115         errno_t eNum = memcpy_s(data, size, str.data(), size);
116         CHECK_FATAL(eNum == EOK, "memcpy_s failed");
117         dataLength = size;
118         data[dataLength] = '\0';
119         return *this;
120     }
121 
operator =(const MapleString &str)122     MapleString &operator=(const MapleString &str)
123     {
124         if (&str == this) {
125             return *this;
126         }
127         size_t size = str.dataLength;
128         CHECK_FATAL(size <= UINT_MAX - 1, "str too large");
129 
130         size_t oldSize = (data == nullptr) ? 0 : (dataLength + 1);
131         data = static_cast<char *>(memPool->Realloc(data, oldSize * sizeof(char), (1 + size) * sizeof(char)));
132         CHECK_FATAL(data != nullptr, "null ptr check");
133         if (size == 0) {
134             data[0] = '\0';
135             return *this;
136         }
137         errno_t eNum = memcpy_s(data, size, str.data, size);
138         CHECK_FATAL(eNum == EOK, "memcpy_s failed");
139         dataLength = size;
140         data[dataLength] = '\0';
141         return *this;
142     }
143 
operator +=(const char c)144     MapleString &operator+=(const char c)
145     {
146         size_t oldSize = ((data == nullptr) ? 0 : (dataLength + 1));
147         CHECK_FATAL(oldSize <= UINT_MAX - 1, "str too large");
148 
149         data = static_cast<char *>(memPool->Realloc(data, oldSize * sizeof(char), (dataLength + 1 + 1) * sizeof(char)));
150         ++dataLength;
151         data[dataLength - 1] = c;
152         data[dataLength] = '\0';
153         return *this;
154     }
155 
operator +=(const char *str)156     MapleString &operator+=(const char *str)
157     {
158         if (str == nullptr) {
159             return *this;
160         }
161         size_t size = strlen(str);
162         size_t oldSize = ((data == nullptr) ? 0 : (dataLength + 1));
163         CHECK_FATAL(size <= UINT_MAX - oldSize, "str too large");
164 
165         data =
166             static_cast<char *>(memPool->Realloc(data, oldSize * sizeof(char), (dataLength + size + 1) * sizeof(char)));
167         CHECK_FATAL(data != nullptr, "null ptr check");
168         errno_t eNum = memcpy_s(data + dataLength, size, str, size);
169         CHECK_FATAL(eNum == EOK, "memcpy_s failed");
170         dataLength += size;
171         data[dataLength] = '\0';
172         return *this;
173     }
174 
operator +=(const MapleString &str)175     MapleString &operator+=(const MapleString &str)
176     {
177         size_t oldSize = ((data == nullptr) ? 0 : (dataLength + 1));
178         CHECK_FATAL(str.dataLength <= UINT_MAX - oldSize, "str too large");
179 
180         data = static_cast<char *>(
181             memPool->Realloc(data, oldSize * sizeof(char), (dataLength + str.dataLength + 1) * sizeof(char)));
182         errno_t eNum = memcpy_s(data + dataLength, str.dataLength, str.data, str.dataLength);
183         CHECK_FATAL(eNum == EOK, "memcpy_s failed");
184         dataLength += str.dataLength;
185         data[dataLength] = '\0';
186         return *this;
187     }
188 
operator +=(const std::string &str)189     MapleString &operator+=(const std::string &str)
190     {
191         size_t size = str.length();
192         size_t oldSize = ((data == nullptr) ? 0 : (dataLength + 1));
193         CHECK_FATAL(size <= UINT_MAX - oldSize, "str too large");
194 
195         data =
196             static_cast<char *>(memPool->Realloc(data, oldSize * sizeof(char), (dataLength + size + 1) * sizeof(char)));
197         CHECK_FATAL(data != nullptr, " null ptr check");
198         errno_t eNum = memcpy_s(data + dataLength, size, str.data(), size);
199         CHECK_FATAL(eNum == EOK, "memcpy_s failed");
200         dataLength += size;
201         data[dataLength] = '\0';
202         return *this;
203     }
204 
205     void clear();
empty() const206     bool empty() const
207     {
208         if (dataLength <= 0 || data == nullptr) {
209             return true;
210         } else {
211             return false;
212         }
213     }
214 
215     MapleString &push_back(const char c);
216     MapleString &append(const MapleString &str);
217     MapleString &append(const MapleString &str, size_t subPos, size_t subLen);
218     MapleString &append(const char *s);
219     MapleString &append(const char *s, size_t n);
220     MapleString &append(size_t n, char c);
221     MapleString &append(const std::string &str);
222     size_t find(const MapleString &str, size_t pos = 0) const;
223     size_t find(const char *s, size_t pos = 0) const;
224     size_t find(const char *s, size_t pos, size_t n) const;
225     size_t find(char c, size_t pos = 0) const;
226     size_t find_last_of(const char *, size_t pos = 0) const;
227     MapleString substr(size_t pos, size_t len) const;
228     MapleString &insert(size_t pos, const MapleString &str);
229     MapleString &insert(size_t pos, const MapleString &str, size_t subPos, size_t subLen);
230     MapleString &insert(size_t pos, const char *s);
231     MapleString &insert(size_t pos, const char *s, size_t n);
232     MapleString &insert(size_t pos, size_t n, char c);
233     MapleString &assign(const MapleString &str);
234     MapleString &assign(const MapleString &str, size_t subPos, size_t subLen);
235     MapleString &assign(const char *s);
236     MapleString &assign(const char *s, size_t n);
237     MapleString &assign(size_t n, char c);
238 
239 private:
StrLen(const char *s)240     inline static size_t StrLen(const char *s)
241     {
242         if (s == nullptr) {
243             return 0;
244         }
245         return ::strlen(s);
246     }
247 
248     inline static char *NewData(MemPool *memPool, const char *source, size_t len);
249 
250     friend bool operator==(const MapleString &, const MapleString &);
251     friend bool operator==(const MapleString &, const char *);
252     friend bool operator==(const char *, const MapleString &);
253     friend bool operator<(const MapleString &str1, const MapleString &str2);
254 
255     char *data = nullptr;
256     MemPool *memPool = nullptr;
257     size_t dataLength = 0;
258 };
259 
260 template <typename OS>
operator <<(OS &os, const MapleString &data)261 inline OS &operator<<(OS &os, const MapleString &data)
262 {
263     os << data.c_str();
264     return os;
265 }
266 
267 // global operators
268 bool operator==(const MapleString &str1, const MapleString &str2);
269 bool operator==(const MapleString &str1, const char *str2);
270 bool operator==(const char *str1, const MapleString &str2);
271 bool operator!=(const MapleString &str1, const MapleString &str2);
272 bool operator!=(const MapleString &str1, const char *str2);
273 bool operator!=(const char *str1, const MapleString &str2);
274 bool operator<(const MapleString &str1, const MapleString &str2);
275 }  // namespace maple
276 #endif  // MEMPOOL_INCLUDE_MAPLE_STRING_H
277