1 /*
2 * Copyright (c) 2025 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 #ifndef RUNTIME_INCLUDE_TAIHE_STRING_HPP_
16 #define RUNTIME_INCLUDE_TAIHE_STRING_HPP_
17 // NOLINTBEGIN
18
19 #include <taihe/string.abi.h>
20 #include <taihe/common.hpp>
21
22 #include <algorithm>
23 #include <charconv>
24 #include <cstddef>
25 #include <cstdint>
26 #include <cstring>
27 #include <iostream>
28 #include <stdexcept>
29 #include <string>
30 #include <string_view>
31 #include <utility>
32
33 namespace taihe {
34 struct string_view;
35 struct string;
36
37 struct string_view {
38 using value_type = char;
39 using size_type = std::size_t;
40 using const_reference = value_type const &;
41 using const_pointer = value_type const *;
42 using const_iterator = const_pointer;
43 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
44
string_viewtaihe::string_view45 explicit string_view(struct TString handle) : m_handle(handle) {}
46
string_viewtaihe::string_view47 string_view(char const *value TH_NONNULL) : string_view(tstr_new_ref(value, std::strlen(value))) {}
48
string_viewtaihe::string_view49 string_view(char const *value TH_NONNULL, size_type size) : string_view(tstr_new_ref(value, size)) {}
50
string_viewtaihe::string_view51 string_view(std::initializer_list<char> value) : string_view(value.begin(), value.size()) {}
52
string_viewtaihe::string_view53 string_view(std::string_view value) : string_view(value.data(), value.size()) {}
54
string_viewtaihe::string_view55 string_view(std::string const &value) : string_view(value.data(), value.size()) {}
56
operator std::string_viewtaihe::string_view57 operator std::string_view() const noexcept
58 {
59 return {tstr_buf(m_handle), tstr_len(m_handle)};
60 }
61
62 // methods
operator []taihe::string_view63 const_reference operator[](size_type pos) const
64 {
65 if (pos >= size()) {
66 TH_THROW(std::out_of_range, "Index out of range");
67 }
68 return tstr_buf(m_handle)[pos];
69 }
70
emptytaihe::string_view71 bool empty() const noexcept
72 {
73 return tstr_len(m_handle) == 0;
74 }
75
sizetaihe::string_view76 size_type size() const noexcept
77 {
78 return tstr_len(m_handle);
79 }
80
fronttaihe::string_view81 const_reference front() const
82 {
83 if (empty()) {
84 TH_THROW(std::out_of_range, "Empty string");
85 }
86 return tstr_buf(m_handle)[0];
87 }
88
backtaihe::string_view89 const_reference back() const
90 {
91 if (empty()) {
92 TH_THROW(std::out_of_range, "Empty string");
93 }
94 return tstr_buf(m_handle)[size() - 1];
95 }
96
c_strtaihe::string_view97 const_pointer c_str() const noexcept
98 {
99 return tstr_buf(m_handle);
100 }
101
datataihe::string_view102 const_pointer data() const noexcept
103 {
104 return tstr_buf(m_handle);
105 }
106
begintaihe::string_view107 const_iterator begin() const noexcept
108 {
109 return tstr_buf(m_handle);
110 }
111
cbegintaihe::string_view112 const_iterator cbegin() const noexcept
113 {
114 return begin();
115 }
116
endtaihe::string_view117 const_iterator end() const noexcept
118 {
119 return tstr_buf(m_handle) + tstr_len(m_handle);
120 }
121
cendtaihe::string_view122 const_iterator cend() const noexcept
123 {
124 return end();
125 }
126
rbegintaihe::string_view127 const_reverse_iterator rbegin() const noexcept
128 {
129 return const_reverse_iterator(end());
130 }
131
crbegintaihe::string_view132 const_reverse_iterator crbegin() const noexcept
133 {
134 return rbegin();
135 }
136
rendtaihe::string_view137 const_reverse_iterator rend() const noexcept
138 {
139 return const_reverse_iterator(begin());
140 }
141
crendtaihe::string_view142 const_reverse_iterator crend() const noexcept
143 {
144 return rend();
145 }
146
147 friend struct string;
148
149 friend string concat(std::initializer_list<string_view> sv_list);
150 friend string_view substr(string_view sv, std::size_t pos, std::size_t len);
151 friend string operator+(string_view left, string_view right);
152 string_view substr(std::size_t pos, std::size_t len) const;
153
154 protected:
155 struct TString m_handle;
156 };
157
158 struct string : public string_view {
stringtaihe::string159 explicit string(struct TString handle) : string_view(handle) {}
160
stringtaihe::string161 string(char const *value TH_NONNULL) : string(tstr_new(value, std::strlen(value))) {}
162
stringtaihe::string163 string(char const *value TH_NONNULL, size_type size) : string(tstr_new(value, size)) {}
164
stringtaihe::string165 string(std::initializer_list<char> value) : string(value.begin(), value.size()) {}
166
stringtaihe::string167 string(std::string_view value) : string(value.data(), value.size()) {}
168
stringtaihe::string169 string(std::string const &value) : string(value.data(), value.size()) {}
170
171 // constructors
stringtaihe::string172 string(string_view const &other) : string(tstr_dup(other.m_handle)) {}
173
stringtaihe::string174 string(string const &other) : string(tstr_dup(other.m_handle)) {}
175
stringtaihe::string176 string(string &&other) noexcept : string(other.m_handle)
177 {
178 other.m_handle.ptr = NULL;
179 }
180
181 // assignment
operator =taihe::string182 string &operator=(string other)
183 {
184 std::swap(this->m_handle, other.m_handle);
185 return *this;
186 }
187
188 // destructor
~stringtaihe::string189 ~string()
190 {
191 if (m_handle.ptr != NULL) {
192 tstr_drop(m_handle);
193 }
194 }
195
196 string &operator+=(string_view other);
197 };
198
concat(std::initializer_list<string_view> sv_list)199 inline string concat(std::initializer_list<string_view> sv_list)
200 {
201 static_assert(alignof(string_view) == alignof(struct TString));
202 return string(tstr_concat(sv_list.size(), reinterpret_cast<struct TString const *>(sv_list.begin())));
203 }
204
operator +(string_view left,string_view right)205 inline string operator+(string_view left, string_view right)
206 {
207 return concat({left, right});
208 }
209
operator +=(string_view other)210 inline string &string::operator+=(string_view other)
211 {
212 return *this = *this + other;
213 }
214
substr(string_view sv,std::size_t pos,std::size_t len)215 inline string_view substr(string_view sv, std::size_t pos, std::size_t len)
216 {
217 return string_view(tstr_substr(sv.m_handle, pos, len));
218 }
219
substr(std::size_t pos,std::size_t len) const220 inline string_view string_view::substr(std::size_t pos, std::size_t len) const
221 {
222 return string_view(tstr_substr(this->m_handle, pos, len));
223 }
224
operator ==(string_view lhs,string_view rhs)225 inline bool operator==(string_view lhs, string_view rhs)
226 {
227 return std::string_view(lhs) == std::string_view(rhs);
228 }
229
operator !=(string_view lhs,string_view rhs)230 inline bool operator!=(string_view lhs, string_view rhs)
231 {
232 return std::string_view(lhs) != std::string_view(rhs);
233 }
234
operator <(string_view lhs,string_view rhs)235 inline bool operator<(string_view lhs, string_view rhs)
236 {
237 return std::string_view(lhs) < std::string_view(rhs);
238 }
239
operator >(string_view lhs,string_view rhs)240 inline bool operator>(string_view lhs, string_view rhs)
241 {
242 return std::string_view(lhs) > std::string_view(rhs);
243 }
244
operator <=(string_view lhs,string_view rhs)245 inline bool operator<=(string_view lhs, string_view rhs)
246 {
247 return std::string_view(lhs) <= std::string_view(rhs);
248 }
249
operator >=(string_view lhs,string_view rhs)250 inline bool operator>=(string_view lhs, string_view rhs)
251 {
252 return std::string_view(lhs) >= std::string_view(rhs);
253 }
254
operator <<(std::ostream & os,string_view sv)255 inline std::ostream &operator<<(std::ostream &os, string_view sv)
256 {
257 return os << std::string_view(sv);
258 }
259
260 template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
to_string(T value)261 inline string to_string(T value)
262 {
263 char buffer[32];
264 std::to_chars_result result = std::to_chars(std::begin(buffer), std::end(buffer), value);
265 if (result.ec != std::errc {}) {
266 TH_THROW(std::runtime_error, "Conversion to char failed");
267 }
268 // buffer automatcally
269 return string {buffer, static_cast<std::size_t>(result.ptr - buffer)};
270 }
271
272 template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
to_string(T value)273 inline string to_string(T value)
274 {
275 char buffer[32];
276 std::to_chars_result result =
277 std::to_chars(std::begin(buffer), std::end(buffer), value, std::chars_format::general);
278 if (result.ec != std::errc {}) {
279 TH_THROW(std::runtime_error, "Conversion to char failed");
280 }
281 // buffer automatcally
282 return string {buffer, static_cast<std::size_t>(result.ptr - buffer)};
283 }
284
285 template <typename T, std::enable_if_t<std::is_same_v<T, bool>, int> = 0>
to_string(T value)286 string to_string(T value)
287 {
288 if (value) {
289 return string {"true", 4};
290 } else {
291 return string {"false", 5};
292 }
293 }
294
295 template <>
296 struct as_abi<string_view> {
297 using type = TString;
298 };
299
300 template <>
301 struct as_abi<string> {
302 using type = TString;
303 };
304
305 template <>
306 struct as_param<string> {
307 using type = string_view;
308 };
309 } // namespace taihe
310
311 template <>
312 struct std::hash<taihe::string> {
operator ()std::hash313 std::size_t operator()(taihe::string_view sv) const noexcept
314 {
315 return std::hash<std::string_view>()(std::string_view(sv));
316 }
317 };
318 // NOLINTEND
319 #endif // RUNTIME_INCLUDE_TAIHE_STRING_HPP_