1#ifndef MSTL_CORE_STRING_CHAR_TRAITS_HPP__
2#define MSTL_CORE_STRING_CHAR_TRAITS_HPP__
7template <
typename CharT,
typename IntT>
8struct base_char_traits {
9 using char_type = CharT;
10 using int_type = IntT;
13 sizeof(int_type) >=
sizeof(char_type),
14 "int_type must be able to represent all char_type values plus EOF"
17 static constexpr char_type* copy(
18 char_type*
const dest,
const char_type*
const srcs,
const size_t count)
noexcept {
23 static constexpr char_type* move(
24 char_type*
const dest,
const char_type*
const srcs,
const size_t count)
noexcept {
29 MSTL_NODISCARD
static constexpr int compare(
30 const char_type* lhs,
const char_type* rhs,
size_t count)
noexcept {
34 MSTL_NODISCARD
static constexpr size_t length(
const char_type* str)
noexcept {
38 MSTL_NODISCARD
static constexpr const char_type* find(
39 const char_type* str,
const size_t count,
const char_type target)
noexcept {
43 static constexpr char_type* assign(
44 char_type*
const str,
const size_t count,
const char_type chr)
noexcept {
48 static constexpr void assign(char_type& lhs,
const char_type rhs)
noexcept {
52 MSTL_NODISCARD
static constexpr bool eq(
const char_type lhs,
const char_type rhs)
noexcept {
55 MSTL_NODISCARD
static constexpr bool lt(
const char_type lhs,
const char_type rhs)
noexcept {
59 MSTL_NODISCARD
static constexpr int_type not_eof(
const int_type rsc)
noexcept {
60 return rsc == eof() ?
static_cast<int_type
>(0) : rsc;
62 MSTL_NODISCARD
static constexpr int_type eof() noexcept {
63 return static_cast<int_type
>(-1);
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");
73 using base_type = base_char_traits<CharT, IntT>;
76 using char_type = CharT;
77 using int_type = IntT;
79 using base_type::copy;
80 using base_type::move;
81 using base_type::length;
84 using base_type::not_eof;
88 MSTL_NODISCARD
static constexpr int compare(
89 const char_type*
const lhs,
const char_type*
const rhs,
const size_t n)
noexcept {
93 MSTL_NODISCARD
static constexpr const char_type* find(
94 const char_type*
const str,
const size_t n,
const char_type chr)
noexcept {
98 static constexpr char_type* assign(
99 char_type*
const str,
size_t n,
const char_type chr)
noexcept {
103 static constexpr void assign(char_type& lhs,
const char_type& rhs)
noexcept {
109template <
typename CharT>
110struct char_traits : base_char_traits<CharT, int64_t> {};
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> {};
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> {};
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*;
130template <
typename CharT,
bool = is_
character_v<CharT>>
131class __string_bitmap {
136 constexpr __string_bitmap() =
default;
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;
143 constexpr bool match(
const CharT chr)
const noexcept {
144 return matches_[
static_cast<byte_t>(chr)];
148template <
typename CharT>
149class __string_bitmap<CharT, false> {};
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;
160 return Traits::compare(lhs, rhs, lh_size) == 0;
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;
169 if (lh_size < rh_size)
return -1;
170 if (lh_size > rh_size)
return 1;
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;
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);
185 if (Traits::compare(if_match, rsc, rsc_size) == 0)
186 return static_cast<size_t>(if_match - dest);
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);
196 return static_cast<size_t>(found - dest);
198 return static_cast<size_t>(-1);
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);
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);
211 if (if_match == dest)
break;
214 return static_cast<size_t>(-1);
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);
225 if (if_match == dest)
break;
228 return static_cast<size_t>(-1);
232#ifdef MSTL_STANDARD_17__
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);
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);
252 return static_cast<size_t>(-1);
256#ifdef MSTL_STANDARD_17__
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);
271 return static_cast<size_t>(-1);
275#ifdef MSTL_STANDARD_17__
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);
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);
293 if (if_match == dest)
break;
296 return static_cast<size_t>(-1);
300#ifdef MSTL_STANDARD_17__
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);
313 if (if_match == dest)
break;
316 return static_cast<size_t>(-1);
320#ifdef MSTL_STANDARD_17__
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);
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);
340 return static_cast<size_t>(-1);
344#ifdef MSTL_STANDARD_17__
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);
359 return static_cast<size_t>(-1);
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);
372 return static_cast<size_t>(-1);
376#ifdef MSTL_STANDARD_17__
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);
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);
394 if (if_match == dest)
break;
397 return static_cast<size_t>(-1);
401#ifdef MSTL_STANDARD_17__
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);
414 if (if_match == dest)
break;
417 return static_cast<size_t>(-1);
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);
428 if (if_match == dest)
break;
431 return static_cast<size_t>(-1);
435#define __MSTL_BUILD_CHAR_PTR_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)); \
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)); \
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); \
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); \
461MSTL_MACRO_RANGE_CHARS(__MSTL_BUILD_CHAR_PTR_HASH)
462#undef __MSTL_BUILD_CHAR_PTR_HASH
static MSTL_NODISCARD constexpr T max() noexcept
获取类型的最大值
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的便捷别名