MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
char_traits.hpp
1#ifndef MSTL_CORE_STRING_CHAR_TRAITS_HPP__
2#define MSTL_CORE_STRING_CHAR_TRAITS_HPP__
6
7template <typename CharT, typename IntT>
8struct base_char_traits {
9 using char_type = CharT;
10 using int_type = IntT;
11
12 static_assert(
13 sizeof(int_type) >= sizeof(char_type),
14 "int_type must be able to represent all char_type values plus EOF"
15 );
16
17 static constexpr char_type* copy(
18 char_type* const dest, const char_type* const srcs, const size_t count) noexcept {
19 _MSTL memory_copy(dest, srcs, count * sizeof(char_type));
20 return dest;
21 }
22
23 static constexpr char_type* move(
24 char_type* const dest, const char_type* const srcs, const size_t count) noexcept {
25 _MSTL memory_move(dest, srcs, count * sizeof(char_type));
26 return dest;
27 }
28
29 MSTL_NODISCARD static constexpr int compare(
30 const char_type* lhs, const char_type* rhs, size_t count) noexcept {
31 return _MSTL string_compare(lhs, rhs, count);
32 }
33
34 MSTL_NODISCARD static constexpr size_t length(const char_type* str) noexcept {
35 return _MSTL string_length(str);
36 }
37
38 MSTL_NODISCARD static constexpr const char_type* find(
39 const char_type* str, const size_t count, const char_type target) noexcept {
40 return _MSTL string_find<char_type>(str, target, count);
41 }
42
43 static constexpr char_type* assign(
44 char_type* const str, const size_t count, const char_type chr) noexcept {
45 return _MSTL string_set<char_type>(str, chr, count);
46 }
47
48 static constexpr void assign(char_type& lhs, const char_type rhs) noexcept {
49 lhs = rhs;
50 }
51
52 MSTL_NODISCARD static constexpr bool eq(const char_type lhs, const char_type rhs) noexcept {
53 return lhs == rhs;
54 }
55 MSTL_NODISCARD static constexpr bool lt(const char_type lhs, const char_type rhs) noexcept {
56 return lhs < rhs;
57 }
58
59 MSTL_NODISCARD static constexpr int_type not_eof(const int_type rsc) noexcept {
60 return rsc == eof() ? static_cast<int_type>(0) : rsc;
61 }
62 MSTL_NODISCARD static constexpr int_type eof() noexcept {
63 return static_cast<int_type>(-1);
64 }
65};
66
67
68template <typename CharT, typename IntT>
69struct narrow_char_traits : private base_char_traits<CharT, IntT> {
70 static_assert(sizeof(CharT) == sizeof(byte_t), "size of CharT must be the same as byte type");
71
72private:
73 using base_type = base_char_traits<CharT, IntT>;
74
75public:
76 using char_type = CharT;
77 using int_type = IntT;
78
79 using base_type::copy;
80 using base_type::move;
81 using base_type::length;
82 using base_type::eq;
83 using base_type::lt;
84 using base_type::not_eof;
85 using base_type::eof;
86
87public:
88 MSTL_NODISCARD static constexpr int compare(
89 const char_type* const lhs, const char_type* const rhs, const size_t n) noexcept {
90 return _MSTL memory_compare(lhs, rhs, n);
91 }
92
93 MSTL_NODISCARD static constexpr const char_type* find(
94 const char_type* const str, const size_t n, const char_type chr) noexcept {
95 return static_cast<const char_type*>(_MSTL memory_find(str, chr, n));
96 }
97
98 static constexpr char_type* assign(
99 char_type* const str, size_t n, const char_type chr) noexcept {
100 return static_cast<char_type*>(_MSTL memory_set(str, chr, n));
101 }
102
103 static constexpr void assign(char_type& lhs, const char_type& rhs) noexcept {
104 lhs = rhs;
105 }
106};
107
108
109template <typename CharT>
110struct char_traits : base_char_traits<CharT, int64_t> {};
111
112template <> struct char_traits<char> : narrow_char_traits<char,
113 conditional_t<numeric_traits<char>::is_signed, int32_t, uint32_t>> {};
114template <> struct char_traits<wchar_t> : base_char_traits<wchar_t, uint32_t> {};
115#ifdef MSTL_STANDARD_20__
116template <> struct char_traits<char8_t> : narrow_char_traits<char8_t, uint32_t> {};
117#endif
118template <> struct char_traits<char16_t> : base_char_traits<char16_t, uint32_t> {};
119template <> struct char_traits<char32_t> : base_char_traits<char32_t, uint32_t> {};
120
121
122template <typename Traits>
123using char_traits_char_t = typename Traits::char_type;
124template <typename Traits>
125using char_traits_ptr_t = const typename Traits::char_type*;
126
127
129
130template <typename CharT, bool = is_character_v<CharT>>
131class __string_bitmap {
132private:
133 bool matches_[numeric_traits<byte_t>::max() + 1] = {};
134
135public:
136 constexpr __string_bitmap() = default;
137
138 constexpr bool mark(const CharT* first, const CharT* const last) noexcept {
139 for (; first != last; ++first)
140 matches_[static_cast<byte_t>(*first)] = true;
141 return true;
142 }
143 constexpr bool match(const CharT chr) const noexcept {
144 return matches_[static_cast<byte_t>(chr)];
145 }
146};
147
148template <typename CharT>
149class __string_bitmap<CharT, false> {};
150
152
153
154template <typename Traits>
155constexpr bool char_traits_equal(const char_traits_ptr_t<Traits> lhs, const size_t lh_size,
156 const char_traits_ptr_t<Traits> rhs, const size_t rh_size) noexcept {
157 if (lh_size != rh_size) return false;
158 if (lh_size == 0u) return true;
159
160 return Traits::compare(lhs, rhs, lh_size) == 0;
161}
162
163template <typename Traits>
164constexpr int char_traits_compare(const char_traits_ptr_t<Traits> lhs, const size_t lh_size,
165 const char_traits_ptr_t<Traits> rhs, const size_t rh_size) noexcept {
166 const int state = Traits::compare(lhs, rhs, _MSTL min(lh_size, rh_size));
167 if (state != 0) return state;
168
169 if (lh_size < rh_size) return -1;
170 if (lh_size > rh_size) return 1;
171 return 0;
172}
173
174template <typename Traits>
175constexpr size_t char_traits_find(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
176 const size_t start, const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
177 if (rsc_size > dest_size || start > dest_size - rsc_size) return static_cast<size_t>(-1);
178 if (rsc_size == 0) return start;
179
180 const auto may_match_end = dest + (dest_size - rsc_size) + 1;
181 for (auto if_match = dest + start; ; ++if_match) {
182 if_match = Traits::find(if_match, static_cast<size_t>(may_match_end - if_match), *rsc);
183 if (!if_match) return static_cast<size_t>(-1);
184
185 if (Traits::compare(if_match, rsc, rsc_size) == 0)
186 return static_cast<size_t>(if_match - dest);
187 }
188}
189
190template <typename Traits>
191constexpr size_t char_traits_find_char(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
192 const size_t start, const char_traits_char_t<Traits> chr) noexcept {
193 if (start < dest_size) {
194 const auto found = Traits::find(dest + start, dest_size - start, chr);
195 if (found)
196 return static_cast<size_t>(found - dest);
197 }
198 return static_cast<size_t>(-1);
199}
200
201template <typename Traits>
202constexpr size_t char_traits_rfind(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
203 const size_t start, const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
204 if (rsc_size == 0) return _MSTL min(start, dest_size);
205
206 if (rsc_size <= dest_size) {
207 for (auto if_match = dest + _MSTL min(start, dest_size - rsc_size);; --if_match) {
208 if (Traits::eq(*if_match, *rsc) && Traits::compare(if_match, rsc, rsc_size) == 0)
209 return static_cast<size_t>(if_match - dest);
210
211 if (if_match == dest) break;
212 }
213 }
214 return static_cast<size_t>(-1);
215}
216
217template <typename Traits>
218constexpr size_t char_traits_rfind_char(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
219 const size_t start, const char_traits_char_t<Traits> chr) noexcept {
220 if (dest_size != 0) {
221 for (auto if_match = dest + _MSTL min(start, dest_size - 1);; --if_match) {
222 if (Traits::eq(*if_match, chr))
223 return static_cast<size_t>(if_match - dest);
224
225 if (if_match == dest) break;
226 }
227 }
228 return static_cast<size_t>(-1);
229}
230
231template <typename Traits, enable_if_t<
232#ifdef MSTL_STANDARD_17__
234#else
236#endif
237 , int> = 0>
238constexpr size_t char_traits_find_first_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
239 const size_t start, const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
240 if (rsc_size != 0 && start < dest_size) {
241 _INNER __string_bitmap<char_traits_char_t<Traits>> match;
242 if (!match.mark(rsc, rsc + rsc_size)) {
243 return (char_traits_find_first_of<Traits, false>)
244 (dest, dest_size, start, rsc, rsc_size);
245 }
246 const auto end = dest + dest_size;
247 for (auto if_match = dest + start; if_match < end; ++if_match) {
248 if (match.match(*if_match))
249 return static_cast<size_t>(if_match - dest);
250 }
251 }
252 return static_cast<size_t>(-1);
253}
254
255template <typename Traits, enable_if_t<
256#ifdef MSTL_STANDARD_17__
258#else
260#endif
261 , int> = 0>
262constexpr size_t char_traits_find_first_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
263 const size_t start, const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
264 if (rsc_size != 0 && start < dest_size) {
265 const auto end = dest + dest_size;
266 for (auto if_match = dest + start; if_match < end; ++if_match) {
267 if (Traits::find(rsc, rsc_size, *if_match))
268 return static_cast<size_t>(if_match - dest);
269 }
270 }
271 return static_cast<size_t>(-1);
272}
273
274template <typename Traits, enable_if_t<
275#ifdef MSTL_STANDARD_17__
277#else
279#endif
280 , int> = 0>
281constexpr size_t char_traits_find_last_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
282 const size_t start, const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
283 if (rsc_size != 0 && dest_size != 0) {
284 _INNER __string_bitmap<char_traits_char_t<Traits>> match;
285 if (!match.mark(rsc, rsc + rsc_size))
286 return (char_traits_find_last_of<Traits, false>)
287 (dest, dest_size, start, rsc, rsc_size);
288
289 for (auto if_match = dest + _MSTL min(start, dest_size - 1);; --if_match) {
290 if (match.match(*if_match))
291 return static_cast<size_t>(if_match - dest);
292
293 if (if_match == dest) break;
294 }
295 }
296 return static_cast<size_t>(-1);
297}
298
299template <typename Traits, enable_if_t<
300#ifdef MSTL_STANDARD_17__
302#else
304#endif
305 , int> = 0>
306constexpr size_t char_traits_find_last_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
307 const size_t start, const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
308 if (rsc_size != 0 && dest_size != 0) {
309 for (auto if_match = dest + _MSTL min(start, dest_size - 1);; --if_match) {
310 if (Traits::find(rsc, rsc_size, *if_match))
311 return static_cast<size_t>(if_match - dest);
312
313 if (if_match == dest) break;
314 }
315 }
316 return static_cast<size_t>(-1);
317}
318
319template <typename Traits, enable_if_t<
320#ifdef MSTL_STANDARD_17__
322#else
324#endif
325 , int> = 0>
326constexpr size_t char_traits_find_first_not_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
327 const size_t start, const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
328 if (start < dest_size) {
329 _INNER __string_bitmap<char_traits_char_t<Traits>> match;
330 if (!match.mark(rsc, rsc + rsc_size))
331 return (char_traits_find_first_not_of<Traits, false>)
332 (dest, dest_size, start, rsc, rsc_size);
333
334 const auto end = dest + dest_size;
335 for (auto if_match = dest + start; if_match < end; ++if_match) {
336 if (!match.match(*if_match))
337 return static_cast<size_t>(if_match - dest);
338 }
339 }
340 return static_cast<size_t>(-1);
341}
342
343template <typename Traits, enable_if_t<
344#ifdef MSTL_STANDARD_17__
346#else
348#endif
349 , int> = 0>
350constexpr size_t char_traits_find_first_not_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
351 const size_t start, const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
352 if (start < dest_size) {
353 const auto end = dest + dest_size;
354 for (auto if_match = dest + start; if_match < end; ++if_match) {
355 if (!Traits::find(rsc, rsc_size, *if_match))
356 return static_cast<size_t>(if_match - dest);
357 }
358 }
359 return static_cast<size_t>(-1);
360}
361
362template <typename Traits>
363constexpr size_t char_traits_find_not_char(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
364 const size_t start, const char_traits_char_t<Traits> chr) noexcept {
365 if (start < dest_size) {
366 const auto end = dest + dest_size;
367 for (auto if_match = dest + start; if_match < end; ++if_match) {
368 if (!Traits::eq(*if_match, chr))
369 return static_cast<size_t>(if_match - dest);
370 }
371 }
372 return static_cast<size_t>(-1);
373}
374
375template <typename Traits, enable_if_t<
376#ifdef MSTL_STANDARD_17__
378#else
380#endif
381 , int> = 0>
382constexpr size_t char_traits_find_last_not_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
383 const size_t start, const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
384 if (dest_size != 0) {
385 _INNER __string_bitmap<char_traits_char_t<Traits>> match;
386 if (!match.mark(rsc, rsc + rsc_size))
387 return (char_traits_find_last_not_of<Traits, false>)
388 (dest, dest_size, start, rsc, rsc_size);
389
390 for (auto if_match = dest + _MSTL min(start, dest_size - 1);; --if_match) {
391 if (!match.match(*if_match))
392 return static_cast<size_t>(if_match - dest);
393
394 if (if_match == dest) break;
395 }
396 }
397 return static_cast<size_t>(-1);
398}
399
400template <typename Traits, enable_if_t<
401#ifdef MSTL_STANDARD_17__
403#else
405#endif
406 , int> = 0>
407constexpr size_t char_traits_find_last_not_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
408 const size_t start, const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
409 if (dest_size != 0) {
410 for (auto if_match = dest + _MSTL min(start, dest_size - 1);; --if_match) {
411 if (!Traits::find(rsc, rsc_size, *if_match))
412 return static_cast<size_t>(if_match - dest);
413
414 if (if_match == dest) break;
415 }
416 }
417 return static_cast<size_t>(-1);
418}
419
420template <typename Traits>
421constexpr size_t char_traits_rfind_not_char(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
422 const size_t start, const char_traits_char_t<Traits> chr) noexcept {
423 if (dest_size != 0) {
424 for (auto if_match = dest + _MSTL min(start, dest_size - 1);; --if_match) {
425 if (!Traits::eq(*if_match, chr))
426 return static_cast<size_t>(if_match - dest);
427
428 if (if_match == dest) break;
429 }
430 }
431 return static_cast<size_t>(-1);
432}
433
434
435#define __MSTL_BUILD_CHAR_PTR_HASH(OPT) \
436template <> \
437struct hash<OPT*> { \
438 MSTL_NODISCARD constexpr size_t operator ()(const OPT* str) const noexcept { \
439 return _INNER FNV_hash_string(str, char_traits<OPT>::length(str)); \
440 } \
441}; \
442template <> \
443struct hash<const OPT*> { \
444 MSTL_NODISCARD constexpr size_t operator ()(const OPT* str) const noexcept { \
445 return _INNER FNV_hash_string(str, char_traits<OPT>::length(str)); \
446 } \
447}; \
448template <size_t N> \
449struct hash<OPT[N]> { \
450 MSTL_NODISCARD constexpr size_t operator ()(const OPT (&str)[N]) const noexcept { \
451 return _INNER FNV_hash_string(str, N - 1); \
452 } \
453}; \
454template <size_t N> \
455struct hash<const OPT[N]> { \
456 MSTL_NODISCARD constexpr size_t operator ()(const OPT (&str)[N]) const noexcept { \
457 return _INNER FNV_hash_string(str, N - 1); \
458 } \
459};
460
461MSTL_MACRO_RANGE_CHARS(__MSTL_BUILD_CHAR_PTR_HASH)
462#undef __MSTL_BUILD_CHAR_PTR_HASH
463
465#endif // MSTL_CORE_STRING_CHAR_TRAITS_HPP__
static MSTL_NODISCARD constexpr T max() noexcept
获取类型的最大值
MSTL比较算法
constexpr const T & min(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(b, a)))
返回两个值中的较小者
unsigned char byte_t
字节类型,定义为无符号字符
constexpr iter_difference_t< Iterator > count(Iterator first, Iterator last, const T &value)
统计范围内等于指定值的元素数量
MSTL_CONSTEXPR14 void * memory_copy(void *MSTL_RESTRICT dest, const void *MSTL_RESTRICT src, size_t count) noexcept
从源内存复制到目标内存
MSTL_PURE_FUNCTION MSTL_CONSTEXPR14 int memory_compare(const void *lhs, const void *rhs, size_t count) noexcept
比较两个内存区域的内容
MSTL_PURE_FUNCTION MSTL_CONSTEXPR14 const void * memory_find(const void *dest, const byte_t value, size_t count) noexcept
在内存中搜索特定字节
MSTL_CONSTEXPR14 void * memory_move(void *dest, const void *src, size_t count) noexcept
从源内存移动数据到目标内存
MSTL_CONSTEXPR14 void * memory_set(void *dest, const byte_t value, size_t count) noexcept
使用指定字节填充内存区域
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
MSTL_PURE_FUNCTION constexpr int string_compare(const CharT *dest, const CharT *src) noexcept
比较两个字符串
MSTL_PURE_FUNCTION constexpr const CharT * string_find(const CharT *str, const CharT chr) noexcept
查找字符在字符串中首次出现的位置
MSTL_PURE_FUNCTION constexpr size_t string_length(const CharT *str) noexcept
计算字符串长度
constexpr CharT * string_set(CharT *str, const CharT value) noexcept
将字符串中的所有字符设置为指定值
constexpr bool is_specialization_v()
is_specialization的便捷函数模板
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) end(Container &cont) noexcept(noexcept(cont.end()))
获取容器的结束迭代器
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
MSTL哈希函数库