1#ifndef NEFORCE_CORE_STRING_CHAR_TRAITS_HPP__
2#define NEFORCE_CORE_STRING_CHAR_TRAITS_HPP__
14NEFORCE_BEGIN_NAMESPACE__
31template <
typename CharT,
typename IntT>
37 "int_type must be able to represent all char_type values plus EOF");
119 NEFORCE_NODISCARD
static constexpr bool eq(
const char_type lhs,
const char_type rhs)
noexcept {
return lhs == rhs; }
127 NEFORCE_NODISCARD
static constexpr bool lt(
const char_type lhs,
const char_type rhs)
noexcept {
return lhs < rhs; }
135 return rsc ==
eof() ?
static_cast<int_type>(0) : rsc;
153template <
typename CharT,
typename IntT>
155 static_assert(
sizeof(CharT) ==
sizeof(
byte_t),
"size of CharT must be the same as byte type");
181 const size_t n)
noexcept {
224template <
typename CharT>
235#if defined(NEFORCE_STANDARD_20) || defined(NEXUSFORCE_ENABLE_DOXYGEN)
254template <
typename Traits>
261template <
typename Traits>
276template <
typename CharT,
bool IsChar = is_
character_v<CharT>>
277class __string_bitmap {
285 constexpr __string_bitmap() =
default;
293 constexpr bool mark(
const CharT* first,
const CharT*
const last)
noexcept {
294 for (; first != last; ++first) {
295 matches_[
static_cast<byte_t>(*first)] =
true;
305 constexpr bool match(
const CharT chr)
const noexcept {
return matches_[
static_cast<byte_t>(chr)]; }
308template <
typename CharT>
309class __string_bitmap<CharT, false> {};
323template <
typename Traits>
326 if (lh_size != rh_size) {
333 return Traits::compare(lhs, rhs, lh_size) == 0;
345template <
typename Traits>
348 const int state = Traits::compare(lhs, rhs, _NEFORCE
min(lh_size, rh_size));
353 if (lh_size < rh_size) {
356 if (lh_size > rh_size) {
372template <
typename Traits>
375 if (rsc_size > dest_size || start > dest_size - rsc_size) {
376 return static_cast<size_t>(-1);
382 const auto may_match_end = dest + (dest_size - rsc_size) + 1;
383 for (
auto if_match = dest + start;; ++if_match) {
384 if_match = Traits::find(if_match,
static_cast<size_t>(may_match_end - if_match), *rsc);
386 return static_cast<size_t>(-1);
389 if (Traits::compare(if_match, rsc, rsc_size) == 0) {
390 return static_cast<size_t>(if_match - dest);
404template <
typename Traits>
407 if (start < dest_size) {
408 const auto found = Traits::find(dest + start, dest_size - start, chr);
410 return static_cast<size_t>(found - dest);
413 return static_cast<size_t>(-1);
426template <
typename Traits>
430 return _NEFORCE
min(start, dest_size);
433 if (rsc_size <= dest_size) {
434 for (
auto if_match = dest + _NEFORCE
min(start, dest_size - rsc_size);; --if_match) {
435 if (Traits::eq(*if_match, *rsc) && Traits::compare(if_match, rsc, rsc_size) == 0) {
436 return static_cast<size_t>(if_match - dest);
439 if (if_match == dest) {
444 return static_cast<size_t>(-1);
456template <
typename Traits>
459 if (dest_size != 0) {
460 for (
auto if_match = dest + _NEFORCE
min(start, dest_size - 1);; --if_match) {
461 if (Traits::eq(*if_match, chr)) {
462 return static_cast<size_t>(if_match - dest);
465 if (if_match == dest) {
470 return static_cast<size_t>(-1);
484#ifdef NEFORCE_STANDARD_17
493 const size_t rsc_size)
noexcept {
494 if (rsc_size != 0 && start < dest_size) {
495 inner::__string_bitmap<char_traits_char_t<Traits>> match;
496 if (!match.mark(rsc, rsc + rsc_size)) {
499 const auto end = dest + dest_size;
500 for (
auto if_match = dest + start; if_match <
end; ++if_match) {
501 if (match.match(*if_match)) {
502 return static_cast<size_t>(if_match - dest);
506 return static_cast<size_t>(-1);
520#ifdef NEFORCE_STANDARD_17
529 const size_t rsc_size)
noexcept {
530 if (rsc_size != 0 && start < dest_size) {
531 const auto end = dest + dest_size;
532 for (
auto if_match = dest + start; if_match <
end; ++if_match) {
533 if (Traits::find(rsc, rsc_size, *if_match)) {
534 return static_cast<size_t>(if_match - dest);
538 return static_cast<size_t>(-1);
552#ifdef NEFORCE_STANDARD_17
561 const size_t rsc_size)
noexcept {
562 if (rsc_size != 0 && dest_size != 0) {
563 inner::__string_bitmap<char_traits_char_t<Traits>> match;
564 if (!match.mark(rsc, rsc + rsc_size)) {
568 for (
auto if_match = dest + _NEFORCE
min(start, dest_size - 1);; --if_match) {
569 if (match.match(*if_match)) {
570 return static_cast<size_t>(if_match - dest);
573 if (if_match == dest) {
578 return static_cast<size_t>(-1);
592#ifdef NEFORCE_STANDARD_17
601 const size_t rsc_size)
noexcept {
602 if (rsc_size != 0 && dest_size != 0) {
603 for (
auto if_match = dest + _NEFORCE
min(start, dest_size - 1);; --if_match) {
604 if (Traits::find(rsc, rsc_size, *if_match)) {
605 return static_cast<size_t>(if_match - dest);
608 if (if_match == dest) {
613 return static_cast<size_t>(-1);
627#ifdef NEFORCE_STANDARD_17
636 const size_t rsc_size)
noexcept {
637 if (start < dest_size) {
638 inner::__string_bitmap<char_traits_char_t<Traits>> match;
639 if (!match.mark(rsc, rsc + rsc_size)) {
643 const auto end = dest + dest_size;
644 for (
auto if_match = dest + start; if_match <
end; ++if_match) {
645 if (!match.match(*if_match)) {
646 return static_cast<size_t>(if_match - dest);
650 return static_cast<size_t>(-1);
664#ifdef NEFORCE_STANDARD_17
673 const size_t rsc_size)
noexcept {
674 if (start < dest_size) {
675 const auto end = dest + dest_size;
676 for (
auto if_match = dest + start; if_match <
end; ++if_match) {
677 if (!Traits::find(rsc, rsc_size, *if_match)) {
678 return static_cast<size_t>(if_match - dest);
682 return static_cast<size_t>(-1);
694template <
typename Traits>
697 if (start < dest_size) {
698 const auto end = dest + dest_size;
699 for (
auto if_match = dest + start; if_match <
end; ++if_match) {
700 if (!Traits::eq(*if_match, chr)) {
701 return static_cast<size_t>(if_match - dest);
705 return static_cast<size_t>(-1);
719#ifdef NEFORCE_STANDARD_17
728 const size_t rsc_size)
noexcept {
729 if (dest_size != 0) {
730 inner::__string_bitmap<char_traits_char_t<Traits>> match;
731 if (!match.mark(rsc, rsc + rsc_size)) {
735 for (
auto if_match = dest + _NEFORCE
min(start, dest_size - 1);; --if_match) {
736 if (!match.match(*if_match)) {
737 return static_cast<size_t>(if_match - dest);
740 if (if_match == dest) {
745 return static_cast<size_t>(-1);
759#ifdef NEFORCE_STANDARD_17
768 const size_t rsc_size)
noexcept {
769 if (dest_size != 0) {
770 for (
auto if_match = dest + _NEFORCE
min(start, dest_size - 1);; --if_match) {
771 if (!Traits::find(rsc, rsc_size, *if_match)) {
772 return static_cast<size_t>(if_match - dest);
775 if (if_match == dest) {
780 return static_cast<size_t>(-1);
792template <
typename Traits>
795 if (dest_size != 0) {
796 for (
auto if_match = dest + _NEFORCE
min(start, dest_size - 1);; --if_match) {
797 if (!Traits::eq(*if_match, chr)) {
798 return static_cast<size_t>(if_match - dest);
801 if (if_match == dest) {
806 return static_cast<size_t>(-1);
811#define __NEFORCE_BUILD_CHAR_PTR_HASH(OPT) \
813 struct hash<OPT*> { \
814 NEFORCE_NODISCARD constexpr size_t operator()(const OPT* str) const noexcept { \
815 return FNV_hash_string(str, char_traits<OPT>::length(str)); \
819 struct hash<const OPT*> { \
820 NEFORCE_NODISCARD constexpr size_t operator()(const OPT* str) const noexcept { \
821 return FNV_hash_string(str, char_traits<OPT>::length(str)); \
824 template <size_t N> \
825 struct hash<OPT[N]> { \
826 NEFORCE_NODISCARD constexpr size_t operator()(const OPT (&str)[N]) const noexcept { \
827 return FNV_hash_string(str, N - 1); \
830 template <size_t N> \
831 struct hash<const OPT[N]> { \
832 NEFORCE_NODISCARD constexpr size_t operator()(const OPT (&str)[N]) const noexcept { \
833 return FNV_hash_string(str, N - 1); \
838#undef __NEFORCE_BUILD_CHAR_PTR_HASH
840NEFORCE_END_NAMESPACE__
static NEFORCE_NODISCARD constexpr T max() noexcept
获取类型的最大值
const typename Traits::char_type * char_traits_ptr_t
获取字符特征中的字符指针类型
typename Traits::char_type char_traits_char_t
获取字符特征中的字符类型
constexpr size_t char_traits_find_first_of(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_ptr_t< Traits > rsc, const size_t rsc_size) noexcept
查找第一个出现在给定集合中的字符(char_traits特化版本)
constexpr size_t char_traits_rfind(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_ptr_t< Traits > rsc, const size_t rsc_size) noexcept
从后向前查找子序列
constexpr size_t char_traits_find_last_of(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_ptr_t< Traits > rsc, const size_t rsc_size) noexcept
查找最后一个出现在给定集合中的字符(char_traits特化版本)
constexpr size_t char_traits_find_last_not_of(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_ptr_t< Traits > rsc, const size_t rsc_size) noexcept
查找最后一个不在给定集合中的字符(char_traits特化版本)
constexpr size_t char_traits_rfind_char(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_char_t< Traits > chr) noexcept
从后向前查找单个字符
constexpr size_t char_traits_rfind_not_char(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_char_t< Traits > chr) noexcept
查找最后一个不等于指定字符的位置
constexpr int char_traits_compare(const char_traits_ptr_t< Traits > lhs, const size_t lh_size, const char_traits_ptr_t< Traits > rhs, const size_t rh_size) noexcept
比较两个字符序列(三路比较)
constexpr size_t char_traits_find(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_ptr_t< Traits > rsc, const size_t rsc_size) noexcept
在字符序列中查找子序列
constexpr size_t char_traits_find_not_char(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_char_t< Traits > chr) noexcept
查找第一个不等于指定字符的位置
constexpr size_t char_traits_find_first_not_of(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_ptr_t< Traits > rsc, const size_t rsc_size) noexcept
查找第一个不在给定集合中的字符(char_traits特化版本)
constexpr size_t char_traits_find_char(const char_traits_ptr_t< Traits > dest, const size_t dest_size, const size_t start, const char_traits_char_t< Traits > chr) noexcept
在字符序列中查找单个字符
constexpr bool char_traits_equal(const char_traits_ptr_t< Traits > lhs, const size_t lh_size, const char_traits_ptr_t< Traits > rhs, const size_t rh_size) 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)
统计范围内等于指定值的元素数量
NEFORCE_CONSTEXPR14 void * memory_copy(void *NEFORCE_RESTRICT dest, const void *NEFORCE_RESTRICT src, size_t count) noexcept
从源内存复制到目标内存
NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 int memory_compare(const void *lhs, const void *rhs, size_t count) noexcept
比较两个内存区域的内容
NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 const void * memory_find(const void *dest, const byte_t value, size_t count) noexcept
在内存中搜索特定字节
NEFORCE_CONSTEXPR14 void * memory_move(void *dest, const void *src, size_t count) noexcept
从源内存移动数据到目标内存
NEFORCE_CONSTEXPR14 void * memory_set(void *dest, const byte_t value, size_t count) noexcept
使用指定字节填充内存区域
NEFORCE_PURE_FUNCTION constexpr size_t string_length(const CharT *str) noexcept
计算字符串长度
NEFORCE_PURE_FUNCTION constexpr const CharT * string_find(const CharT *str, const CharT chr) noexcept
查找字符在字符串中首次出现的位置
NEFORCE_PURE_FUNCTION constexpr int string_compare(const CharT *dest, const CharT *src) noexcept
比较两个字符串
constexpr CharT * string_set(CharT *str, const CharT value) noexcept
将字符串中的所有字符设置为指定值
NEFORCE_INLINE17 constexpr bool is_specialization_v
is_specialization的便捷变量模板
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr decltype(auto) end(Container &cont) noexcept(noexcept(cont.end()))
获取容器的结束迭代器
#define NEFORCE_MACRO_RANGE_CHARS(MAC)
所有字符类型列表宏
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
static NEFORCE_NODISCARD constexpr bool eq(const char_type lhs, const char_type rhs) noexcept
相等比较
static constexpr char_type * assign(char_type *const str, const size_t count, const char_type chr) noexcept
将字符序列中的每个字符设置为指定值
static NEFORCE_NODISCARD constexpr int_type eof() noexcept
返回EOF值
static NEFORCE_NODISCARD constexpr bool lt(const char_type lhs, const char_type rhs) noexcept
小于比较
static NEFORCE_NODISCARD constexpr int compare(const char_type *lhs, const char_type *rhs, size_t count) noexcept
比较两个字符序列
static constexpr char_type * move(char_type *dest, const char_type *srcs, const size_t count) noexcept
移动字符序列
static constexpr char_type * copy(char_type *dest, const char_type *srcs, const size_t count) noexcept
复制字符序列
static NEFORCE_NODISCARD constexpr int_type not_eof(const int_type rsc) noexcept
如果不是EOF则返回原值,否则返回0
static NEFORCE_NODISCARD constexpr size_t length(const char_type *str) noexcept
计算字符串长度
static NEFORCE_NODISCARD constexpr const char_type * find(const char_type *str, const size_t count, const char_type target) noexcept
在字符序列中查找指定字符
static constexpr void assign(char_type &lhs, const char_type rhs) noexcept
赋值单个字符
static constexpr void assign(char_type &lhs, const char_type &rhs) noexcept
赋值单个字符
static NEFORCE_NODISCARD constexpr int compare(const char_type *lhs, const char_type *rhs, const size_t n) noexcept
比较两个字符序列(内存优化版本)
static constexpr char_type * assign(char_type *str, size_t n, const char_type chr) noexcept
将字符序列中的每个字符设置为指定值(内存优化版本)
static NEFORCE_NODISCARD constexpr const char_type * find(const char_type *str, const size_t n, const char_type chr) noexcept
在字符序列中查找指定字符(内存优化版本)