NexusForce 1.0.0
A rigorously engineered full-stack C++ backend library.
载入中...
搜索中...
未找到
char_traits.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_STRING_CHAR_TRAITS_HPP__
2#define NEFORCE_CORE_STRING_CHAR_TRAITS_HPP__
3
12
16NEFORCE_BEGIN_NAMESPACE__
17
23
33template <typename CharT, typename IntT>
35 using char_type = CharT;
36 using int_type = IntT;
37
38 static_assert(sizeof(int_type) >= sizeof(char_type),
39 "int_type must be able to represent all char_type values plus EOF");
40
48 static constexpr char_type* copy(char_type* dest, const char_type* srcs, const size_t count) noexcept {
49 _NEFORCE memory_copy(dest, srcs, count * sizeof(char_type));
50 return dest;
51 }
52
60 static constexpr char_type* move(char_type* dest, const char_type* srcs, const size_t count) noexcept {
61 _NEFORCE memory_move(dest, srcs, count * sizeof(char_type));
62 return dest;
63 }
64
72 NEFORCE_NODISCARD static constexpr int compare(const char_type* lhs, const char_type* rhs, size_t count) noexcept {
73 return _NEFORCE string_compare(lhs, rhs, count);
74 }
75
81 NEFORCE_NODISCARD static constexpr size_t length(const char_type* str) noexcept {
82 return _NEFORCE string_length(str);
83 }
84
92 NEFORCE_NODISCARD static constexpr const char_type* find(const char_type* str, const size_t count,
93 const char_type target) noexcept {
94 return _NEFORCE string_find<char_type>(str, target, count);
95 }
96
104 static constexpr char_type* assign(char_type* const str, const size_t count, const char_type chr) noexcept {
105 return _NEFORCE string_set<char_type>(str, chr, count);
106 }
107
113 static constexpr void assign(char_type& lhs, const char_type rhs) noexcept { lhs = rhs; }
114
121 NEFORCE_NODISCARD static constexpr bool eq(const char_type lhs, const char_type rhs) noexcept { return lhs == rhs; }
122
129 NEFORCE_NODISCARD static constexpr bool lt(const char_type lhs, const char_type rhs) noexcept { return lhs < rhs; }
130
136 NEFORCE_NODISCARD static constexpr int_type not_eof(const int_type rsc) noexcept {
137 return rsc == eof() ? static_cast<int_type>(0) : rsc;
138 }
139
144 NEFORCE_NODISCARD static constexpr int_type eof() noexcept { return static_cast<int_type>(-1); }
145};
146
155template <typename CharT, typename IntT>
156struct narrow_char_traits : private base_char_traits<CharT, IntT> {
157 static_assert(sizeof(CharT) == sizeof(byte_t), "size of CharT must be the same as byte type");
158
159private:
160 using base_type = base_char_traits<CharT, IntT>;
161
162public:
163 using char_type = CharT;
164 using int_type = IntT;
165
166 using base_type::copy;
167 using base_type::eof;
168 using base_type::eq;
169 using base_type::length;
170 using base_type::lt;
171 using base_type::move;
172 using base_type::not_eof;
173
174public:
182 NEFORCE_NODISCARD static constexpr int compare(const char_type* lhs, const char_type* rhs,
183 const size_t n) noexcept {
184 return _NEFORCE memory_compare(lhs, rhs, n);
185 }
186
194 NEFORCE_NODISCARD static constexpr const char_type* find(const char_type* str, const size_t n,
195 const char_type chr) noexcept {
196 return static_cast<const char_type*>(_NEFORCE memory_find(str, chr, n));
197 }
198
206 static constexpr char_type* assign(char_type* str, size_t n, const char_type chr) noexcept {
207 return static_cast<char_type*>(_NEFORCE memory_set(str, chr, n));
208 }
209
215 static constexpr void assign(char_type& lhs, const char_type& rhs) noexcept { lhs = rhs; }
216};
217
218
226template <typename CharT>
227struct char_traits : base_char_traits<CharT, int64_t> {};
228
230template <>
231struct char_traits<char> : narrow_char_traits<char, int32_t> {};
232
234template <>
235struct char_traits<wchar_t> : base_char_traits<wchar_t, uint32_t> {};
236
237#ifdef NEFORCE_STANDARD_20
239template <>
240struct char_traits<char8_t> : narrow_char_traits<char8_t, uint32_t> {};
241#endif
242
244template <>
245struct char_traits<char16_t> : base_char_traits<char16_t, uint32_t> {};
246
248template <>
249struct char_traits<char32_t> : base_char_traits<char32_t, uint32_t> {};
250
251
256template <typename Traits>
257using char_traits_char_t = typename Traits::char_type;
258
263template <typename Traits>
264using char_traits_ptr_t = const typename Traits::char_type*;
265
266
268
269template <typename Traits>
270constexpr size_t char_traits_find_char(char_traits_ptr_t<Traits> dest, size_t dest_size, size_t start,
271 char_traits_char_t<Traits> chr) noexcept;
272
273template <typename Traits>
274constexpr size_t char_traits_rfind_char(char_traits_ptr_t<Traits> dest, size_t dest_size, size_t start,
275 char_traits_char_t<Traits> chr) noexcept;
276
277NEFORCE_BEGIN_INNER__
278
286template <typename CharT, typename = void>
287class __string_bitmap {
288public:
289 constexpr bool mark(const CharT* /*unused*/, const CharT* /*unused*/) const noexcept { return false; }
290 constexpr bool match(const CharT /*unused*/) const noexcept { return false; }
291};
292
297template <typename CharT>
298class __string_bitmap<CharT, enable_if_t<is_character_v<CharT> && sizeof(CharT) == 1>> {
299private:
300 bool matches_[numeric_traits<byte_t>::max() + 1] = {};
301
302public:
306 constexpr __string_bitmap() = default;
307
314 constexpr bool mark(const CharT* first, const CharT* const last) noexcept {
315 for (; first != last; ++first) {
316 matches_[static_cast<byte_t>(*first)] = true;
317 }
318 return true;
319 }
320
326 constexpr bool match(const CharT chr) const noexcept { return matches_[static_cast<byte_t>(chr)]; }
327};
328
339template <typename Traits>
340constexpr size_t char_traits_find_bmh(const char_traits_ptr_t<Traits> dest, const size_t dest_size, const size_t start,
341 const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
342 if (rsc_size == 1) {
343 return _NEFORCE char_traits_find_char<Traits>(dest, dest_size, start, rsc[0]);
344 }
345
346 size_t skip[256] = {};
347 for (auto& s: skip) {
348 s = rsc_size;
349 }
350 for (size_t i = 0; i + 1 < rsc_size; ++i) {
351 skip[static_cast<byte_t>(rsc[i])] = rsc_size - 1 - i;
352 }
353
354 const auto last = rsc[rsc_size - 1];
355 size_t i = start;
356 const size_t limit = dest_size - rsc_size;
357
358 while (i <= limit) {
359 if (Traits::eq(dest[i + rsc_size - 1], last)) {
360 if (Traits::compare(dest + i, rsc, rsc_size) == 0) {
361 return i;
362 }
363 }
364 i += skip[static_cast<byte_t>(dest[i + rsc_size - 1])];
365 }
366 return static_cast<size_t>(-1);
367}
368
381template <typename Traits>
382constexpr size_t char_traits_rfind_bmh(const char_traits_ptr_t<Traits> dest, const size_t dest_size, const size_t start,
383 const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
384 if (rsc_size == 1) {
385 return _NEFORCE char_traits_rfind_char<Traits>(dest, dest_size, start, rsc[0]);
386 }
387
388 size_t skip[256] = {};
389 for (auto& s: skip) {
390 s = rsc_size;
391 }
392 for (size_t i = 0; i + 1 < rsc_size; ++i) {
393 skip[static_cast<byte_t>(rsc[i])] = rsc_size - 1 - i;
394 }
395
396 const auto last = rsc[rsc_size - 1];
397 auto last_found = static_cast<size_t>(-1);
398 const size_t limit = _NEFORCE min(start, dest_size - rsc_size);
399 size_t i = 0;
400
401 while (i <= limit) {
402 if (Traits::eq(dest[i + rsc_size - 1], last)) {
403 if (Traits::compare(dest + i, rsc, rsc_size) == 0) {
404 last_found = i;
405 ++i;
406 continue;
407 }
408 }
409 i += skip[static_cast<byte_t>(dest[i + rsc_size - 1])];
410 }
411
412 return last_found;
413}
414
415template <typename Traits>
416constexpr size_t char_traits_find_naive(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
417 const size_t start, const char_traits_ptr_t<Traits> rsc,
418 const size_t rsc_size) noexcept {
419 const auto may_match_end = dest + (dest_size - rsc_size) + 1;
420 for (auto if_match = dest + start;; ++if_match) {
421 if_match = Traits::find(if_match, static_cast<size_t>(may_match_end - if_match), *rsc);
422 if (!if_match) {
423 return static_cast<size_t>(-1);
424 }
425
426 if (Traits::compare(if_match, rsc, rsc_size) == 0) {
427 return static_cast<size_t>(if_match - dest);
428 }
429 }
430}
431
432template <typename Traits>
433constexpr enable_if_t<sizeof(typename Traits::char_type) == 1, size_t>
434char_traits_find_dispatch(const char_traits_ptr_t<Traits> dest, const size_t dest_size, const size_t start,
435 const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
436 return inner::char_traits_find_bmh<Traits>(dest, dest_size, start, rsc, rsc_size);
437}
438
439template <typename Traits>
440constexpr enable_if_t<(sizeof(typename Traits::char_type) != 1), size_t>
441char_traits_find_dispatch(const char_traits_ptr_t<Traits> dest, const size_t dest_size, const size_t start,
442 const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
443 return inner::char_traits_find_naive<Traits>(dest, dest_size, start, rsc, rsc_size);
444}
445
446template <typename Traits>
447constexpr size_t char_traits_rfind_naive(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
448 const size_t start, const char_traits_ptr_t<Traits> rsc,
449 const size_t rsc_size) noexcept {
450 if (rsc_size <= dest_size) {
451 for (auto if_match = dest + _NEFORCE min(start, dest_size - rsc_size);; --if_match) {
452 if (Traits::eq(*if_match, *rsc) && Traits::compare(if_match, rsc, rsc_size) == 0) {
453 return static_cast<size_t>(if_match - dest);
454 }
455
456 if (if_match == dest) {
457 break;
458 }
459 }
460 }
461 return static_cast<size_t>(-1);
462}
463
464template <typename Traits>
465constexpr enable_if_t<sizeof(typename Traits::char_type) == 1, size_t>
466char_traits_rfind_dispatch(const char_traits_ptr_t<Traits> dest, const size_t dest_size, const size_t start,
467 const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
468 return inner::char_traits_rfind_bmh<Traits>(dest, dest_size, start, rsc, rsc_size);
469}
470
471template <typename Traits>
472constexpr enable_if_t<(sizeof(typename Traits::char_type) != 1), size_t>
473char_traits_rfind_dispatch(const char_traits_ptr_t<Traits> dest, const size_t dest_size, const size_t start,
474 const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
475 return inner::char_traits_rfind_naive<Traits>(dest, dest_size, start, rsc, rsc_size);
476}
477
478NEFORCE_END_INNER__
480
490template <typename Traits>
491constexpr bool char_traits_equal(const char_traits_ptr_t<Traits> lhs, const size_t lh_size,
492 const char_traits_ptr_t<Traits> rhs, const size_t rh_size) noexcept {
493 if (lh_size != rh_size) {
494 return false;
495 }
496 if (lh_size == 0U) {
497 return true;
498 }
499
500 return Traits::compare(lhs, rhs, lh_size) == 0;
501}
502
512template <typename Traits>
513constexpr int char_traits_compare(const char_traits_ptr_t<Traits> lhs, const size_t lh_size,
514 const char_traits_ptr_t<Traits> rhs, const size_t rh_size) noexcept {
515 const int state = Traits::compare(lhs, rhs, _NEFORCE min(lh_size, rh_size));
516 if (state != 0) {
517 return state;
518 }
519
520 if (lh_size < rh_size) {
521 return -1;
522 }
523 if (lh_size > rh_size) {
524 return 1;
525 }
526 return 0;
527}
528
539template <typename Traits>
540constexpr size_t char_traits_find(const char_traits_ptr_t<Traits> dest, const size_t dest_size, const size_t start,
541 const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
542 if (rsc_size > dest_size || start > dest_size - rsc_size) {
543 return static_cast<size_t>(-1);
544 }
545 if (rsc_size == 0) {
546 return start;
547 }
548
549 return inner::char_traits_find_dispatch<Traits>(dest, dest_size, start, rsc, rsc_size);
550}
551
561template <typename Traits>
562constexpr size_t char_traits_find_char(const char_traits_ptr_t<Traits> dest, const size_t dest_size, const size_t start,
563 const char_traits_char_t<Traits> chr) noexcept {
564 if (start < dest_size) {
565 const auto found = Traits::find(dest + start, dest_size - start, chr);
566 if (found) {
567 return static_cast<size_t>(found - dest);
568 }
569 }
570 return static_cast<size_t>(-1);
571}
572
583template <typename Traits>
584constexpr size_t char_traits_rfind(const char_traits_ptr_t<Traits> dest, const size_t dest_size, const size_t start,
585 const char_traits_ptr_t<Traits> rsc, const size_t rsc_size) noexcept {
586 if (rsc_size == 0) {
587 return _NEFORCE min(start, dest_size);
588 }
589 if (rsc_size > dest_size) {
590 return static_cast<size_t>(-1);
591 }
592
593 return inner::char_traits_rfind_dispatch<Traits>(dest, dest_size, start, rsc, rsc_size);
594}
595
605template <typename Traits>
606constexpr size_t char_traits_rfind_char(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
607 const size_t start, const char_traits_char_t<Traits> chr) noexcept {
608 if (dest_size != 0) {
609 for (auto if_match = dest + _NEFORCE min(start, dest_size - 1);; --if_match) {
610 if (Traits::eq(*if_match, chr)) {
611 return static_cast<size_t>(if_match - dest);
612 }
613
614 if (if_match == dest) {
615 break;
616 }
617 }
618 }
619 return static_cast<size_t>(-1);
620}
621
632template <typename Traits, enable_if_t<
633#ifdef NEFORCE_STANDARD_17
634 is_specialization_v<Traits, char_traits>
635#else
636 is_specialization_v<Traits, char_traits>()
637#endif
638 ,
639 int> = 0>
640constexpr size_t char_traits_find_first_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
641 const size_t start, const char_traits_ptr_t<Traits> rsc,
642 const size_t rsc_size) noexcept {
643 if (rsc_size != 0 && start < dest_size) {
644 inner::__string_bitmap<char_traits_char_t<Traits>> match;
645 if (!match.mark(rsc, rsc + rsc_size)) {
646 return (char_traits_find_first_of<Traits, false>) (dest, dest_size, start, rsc, rsc_size);
647 }
648 const auto end = dest + dest_size;
649 for (auto if_match = dest + start; if_match < end; ++if_match) {
650 if (match.match(*if_match)) {
651 return static_cast<size_t>(if_match - dest);
652 }
653 }
654 }
655 return static_cast<size_t>(-1);
656}
657
668template <typename Traits, enable_if_t<
669#ifdef NEFORCE_STANDARD_17
670 !is_specialization_v<Traits, char_traits>
671#else
672 !is_specialization_v<Traits, char_traits>()
673#endif
674 ,
675 int> = 0>
676constexpr size_t char_traits_find_first_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
677 const size_t start, const char_traits_ptr_t<Traits> rsc,
678 const size_t rsc_size) noexcept {
679 if (rsc_size != 0 && start < dest_size) {
680 const auto end = dest + dest_size;
681 for (auto if_match = dest + start; if_match < end; ++if_match) {
682 if (Traits::find(rsc, rsc_size, *if_match)) {
683 return static_cast<size_t>(if_match - dest);
684 }
685 }
686 }
687 return static_cast<size_t>(-1);
688}
689
700template <typename Traits, enable_if_t<
701#ifdef NEFORCE_STANDARD_17
702 is_specialization_v<Traits, char_traits>
703#else
704 is_specialization_v<Traits, char_traits>()
705#endif
706 ,
707 int> = 0>
708constexpr size_t char_traits_find_last_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
709 const size_t start, const char_traits_ptr_t<Traits> rsc,
710 const size_t rsc_size) noexcept {
711 if (rsc_size != 0 && dest_size != 0) {
712 inner::__string_bitmap<char_traits_char_t<Traits>> match;
713 if (!match.mark(rsc, rsc + rsc_size)) {
714 return (char_traits_find_last_of<Traits, false>) (dest, dest_size, start, rsc, rsc_size);
715 }
716
717 for (auto if_match = dest + _NEFORCE min(start, dest_size - 1);; --if_match) {
718 if (match.match(*if_match)) {
719 return static_cast<size_t>(if_match - dest);
720 }
721
722 if (if_match == dest) {
723 break;
724 }
725 }
726 }
727 return static_cast<size_t>(-1);
728}
729
740template <typename Traits, enable_if_t<
741#ifdef NEFORCE_STANDARD_17
742 !is_specialization_v<Traits, char_traits>
743#else
744 !is_specialization_v<Traits, char_traits>()
745#endif
746 ,
747 int> = 0>
748constexpr size_t char_traits_find_last_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
749 const size_t start, const char_traits_ptr_t<Traits> rsc,
750 const size_t rsc_size) noexcept {
751 if (rsc_size != 0 && dest_size != 0) {
752 for (auto if_match = dest + _NEFORCE min(start, dest_size - 1);; --if_match) {
753 if (Traits::find(rsc, rsc_size, *if_match)) {
754 return static_cast<size_t>(if_match - dest);
755 }
756
757 if (if_match == dest) {
758 break;
759 }
760 }
761 }
762 return static_cast<size_t>(-1);
763}
764
775template <typename Traits, enable_if_t<
776#ifdef NEFORCE_STANDARD_17
777 is_specialization_v<Traits, char_traits>
778#else
779 is_specialization_v<Traits, char_traits>()
780#endif
781 ,
782 int> = 0>
783constexpr size_t char_traits_find_first_not_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
784 const size_t start, const char_traits_ptr_t<Traits> rsc,
785 const size_t rsc_size) noexcept {
786 if (start < dest_size) {
787 inner::__string_bitmap<char_traits_char_t<Traits>> match;
788 if (!match.mark(rsc, rsc + rsc_size)) {
789 return (char_traits_find_first_not_of<Traits, false>) (dest, dest_size, start, rsc, rsc_size);
790 }
791
792 const auto end = dest + dest_size;
793 for (auto if_match = dest + start; if_match < end; ++if_match) {
794 if (!match.match(*if_match)) {
795 return static_cast<size_t>(if_match - dest);
796 }
797 }
798 }
799 return static_cast<size_t>(-1);
800}
801
812template <typename Traits, enable_if_t<
813#ifdef NEFORCE_STANDARD_17
814 !is_specialization_v<Traits, char_traits>
815#else
816 !is_specialization_v<Traits, char_traits>()
817#endif
818 ,
819 int> = 0>
820constexpr size_t char_traits_find_first_not_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
821 const size_t start, const char_traits_ptr_t<Traits> rsc,
822 const size_t rsc_size) noexcept {
823 if (start < dest_size) {
824 const auto end = dest + dest_size;
825 for (auto if_match = dest + start; if_match < end; ++if_match) {
826 if (!Traits::find(rsc, rsc_size, *if_match)) {
827 return static_cast<size_t>(if_match - dest);
828 }
829 }
830 }
831 return static_cast<size_t>(-1);
832}
833
843template <typename Traits>
844constexpr size_t char_traits_find_not_char(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
845 const size_t start, const char_traits_char_t<Traits> chr) noexcept {
846 if (start < dest_size) {
847 const auto end = dest + dest_size;
848 for (auto if_match = dest + start; if_match < end; ++if_match) {
849 if (!Traits::eq(*if_match, chr)) {
850 return static_cast<size_t>(if_match - dest);
851 }
852 }
853 }
854 return static_cast<size_t>(-1);
855}
856
867template <typename Traits, enable_if_t<
868#ifdef NEFORCE_STANDARD_17
869 is_specialization_v<Traits, char_traits>
870#else
871 is_specialization_v<Traits, char_traits>()
872#endif
873 ,
874 int> = 0>
875constexpr size_t char_traits_find_last_not_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
876 const size_t start, const char_traits_ptr_t<Traits> rsc,
877 const size_t rsc_size) noexcept {
878 if (dest_size != 0) {
879 inner::__string_bitmap<char_traits_char_t<Traits>> match;
880 if (!match.mark(rsc, rsc + rsc_size)) {
881 return (char_traits_find_last_not_of<Traits, false>) (dest, dest_size, start, rsc, rsc_size);
882 }
883
884 for (auto if_match = dest + _NEFORCE min(start, dest_size - 1);; --if_match) {
885 if (!match.match(*if_match)) {
886 return static_cast<size_t>(if_match - dest);
887 }
888
889 if (if_match == dest) {
890 break;
891 }
892 }
893 }
894 return static_cast<size_t>(-1);
895}
896
907template <typename Traits, enable_if_t<
908#ifdef NEFORCE_STANDARD_17
909 !is_specialization_v<Traits, char_traits>
910#else
911 !is_specialization_v<Traits, char_traits>()
912#endif
913 ,
914 int> = 0>
915constexpr size_t char_traits_find_last_not_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
916 const size_t start, const char_traits_ptr_t<Traits> rsc,
917 const size_t rsc_size) noexcept {
918 if (dest_size != 0) {
919 for (auto if_match = dest + _NEFORCE min(start, dest_size - 1);; --if_match) {
920 if (!Traits::find(rsc, rsc_size, *if_match)) {
921 return static_cast<size_t>(if_match - dest);
922 }
923
924 if (if_match == dest) {
925 break;
926 }
927 }
928 }
929 return static_cast<size_t>(-1);
930}
931
941template <typename Traits>
942constexpr size_t char_traits_rfind_not_char(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
943 const size_t start, const char_traits_char_t<Traits> chr) noexcept {
944 if (dest_size != 0) {
945 for (auto if_match = dest + _NEFORCE min(start, dest_size - 1);; --if_match) {
946 if (!Traits::eq(*if_match, chr)) {
947 return static_cast<size_t>(if_match - dest);
948 }
949
950 if (if_match == dest) {
951 break;
952 }
953 }
954 }
955 return static_cast<size_t>(-1);
956}
957
967template <typename Traits>
968constexpr size_t char_traits_find_first_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
969 const size_t start, const charset& cs) noexcept {
970 if (start < dest_size) {
971 const auto end = dest + dest_size;
972 for (auto if_match = dest + start; if_match < end; ++if_match) {
973 if (cs.contains(*if_match)) {
974 return static_cast<size_t>(if_match - dest);
975 }
976 }
977 }
978 return static_cast<size_t>(-1);
979}
980
990template <typename Traits>
991constexpr size_t char_traits_find_last_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
992 const size_t start, const charset& cs) noexcept {
993 if (dest_size != 0) {
994 for (auto if_match = dest + _NEFORCE min(start, dest_size - 1);; --if_match) {
995 if (cs.contains(*if_match)) {
996 return static_cast<size_t>(if_match - dest);
997 }
998 if (if_match == dest) {
999 break;
1000 }
1001 }
1002 }
1003 return static_cast<size_t>(-1);
1004}
1005
1015template <typename Traits>
1016constexpr size_t char_traits_find_first_not_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
1017 const size_t start, const charset& cs) noexcept {
1018 if (start < dest_size) {
1019 const auto end = dest + dest_size;
1020 for (auto if_match = dest + start; if_match < end; ++if_match) {
1021 if (!cs.contains(*if_match)) {
1022 return static_cast<size_t>(if_match - dest);
1023 }
1024 }
1025 }
1026 return static_cast<size_t>(-1);
1027}
1028
1038template <typename Traits>
1039constexpr size_t char_traits_find_last_not_of(const char_traits_ptr_t<Traits> dest, const size_t dest_size,
1040 const size_t start, const charset& cs) noexcept {
1041 if (dest_size != 0) {
1042 for (auto if_match = dest + _NEFORCE min(start, dest_size - 1);; --if_match) {
1043 if (!cs.contains(*if_match)) {
1044 return static_cast<size_t>(if_match - dest);
1045 }
1046 if (if_match == dest) {
1047 break;
1048 }
1049 }
1050 }
1051 return static_cast<size_t>(-1);
1052}
1053 // CharTraits
1055
1056#define __NEFORCE_BUILD_CHAR_PTR_HASH(OPT) \
1057 template <> \
1058 struct hash<OPT*> { \
1059 NEFORCE_NODISCARD constexpr size_t operator()(const OPT* str) const noexcept { \
1060 return XXH64(str, char_traits<OPT>::length(str) * sizeof(OPT)); \
1061 } \
1062 }; \
1063 template <> \
1064 struct hash<const OPT*> { \
1065 NEFORCE_NODISCARD constexpr size_t operator()(const OPT* str) const noexcept { \
1066 return XXH64(str, char_traits<OPT>::length(str) * sizeof(OPT)); \
1067 } \
1068 }; \
1069 template <size_t N> \
1070 struct hash<OPT[N]> { \
1071 NEFORCE_NODISCARD constexpr size_t operator()(const OPT (&str)[N]) const noexcept { \
1072 return XXH64(str, (N - 1) * sizeof(OPT)); \
1073 } \
1074 }; \
1075 template <size_t N> \
1076 struct hash<const OPT[N]> { \
1077 NEFORCE_NODISCARD constexpr size_t operator()(const OPT (&str)[N]) const noexcept { \
1078 return XXH64(str, (N - 1) * sizeof(OPT)); \
1079 } \
1080 };
1081
1082NEFORCE_MACRO_RANGE_CHARS(__NEFORCE_BUILD_CHAR_PTR_HASH)
1083#undef __NEFORCE_BUILD_CHAR_PTR_HASH
1084
1085NEFORCE_END_NAMESPACE__
1086#endif // NEFORCE_CORE_STRING_CHAR_TRAITS_HPP__
比较算法
字符集工具类
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_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_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(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_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 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 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_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特化版本)
typename Traits::char_type char_traits_char_t
获取字符特征中的字符类型
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 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
从后向前查找单个字符
const typename Traits::char_type * char_traits_ptr_t
获取字符特征中的字符指针类型
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)
统计范围内等于指定值的元素数量
constexpr const void * memory_find(const void *dest, const byte_t value, size_t count) noexcept
在内存中搜索特定字节
constexpr void * memory_copy(void *__restrict dest, const void *__restrict src, size_t count) noexcept
从源内存复制到目标内存
constexpr int memory_compare(const void *lhs, const void *rhs, size_t count) noexcept
比较两个内存区域的内容
constexpr void * memory_set(void *dest, const byte_t value, size_t count) noexcept
使用指定字节填充内存区域
constexpr void * memory_move(void *dest, const void *src, size_t count) noexcept
从源内存移动数据到目标内存
constexpr const CharT * string_find(const CharT *str, const CharT chr) noexcept
查找字符在字符串中首次出现的位置
constexpr int string_compare(const CharT *dest, const CharT *src) noexcept
比较两个字符串
constexpr CharT * string_set(CharT *str, const CharT value) noexcept
将字符串中的所有字符设置为指定值
constexpr size_t string_length(const CharT *str) noexcept
计算字符串长度
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 constexpr char_type * assign(char_type *const str, const size_t count, const char_type chr) noexcept
将字符序列中的每个字符设置为指定值
static constexpr const char_type * find(const char_type *str, const size_t count, const char_type target) noexcept
在字符序列中查找指定字符
static constexpr bool lt(const char_type lhs, const char_type rhs) noexcept
小于比较
static constexpr int_type not_eof(const int_type rsc) noexcept
如果不是EOF则返回原值,否则返回0
static 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 size_t length(const char_type *str) noexcept
计算字符串长度
static constexpr char_type * copy(char_type *dest, const char_type *srcs, const size_t count) noexcept
复制字符序列
static constexpr int_type eof() noexcept
返回EOF值
static constexpr bool eq(const char_type lhs, const char_type rhs) noexcept
相等比较
static constexpr void assign(char_type &lhs, const char_type rhs) noexcept
赋值单个字符
static constexpr char_type * assign(char_type *str, size_t n, const char_type chr) noexcept
将字符序列中的每个字符设置为指定值(内存优化版本)
static constexpr int compare(const char_type *lhs, const char_type *rhs, const size_t n) noexcept
比较两个字符序列(内存优化版本)
static constexpr const char_type * find(const char_type *str, const size_t n, const char_type chr) noexcept
在字符序列中查找指定字符(内存优化版本)
static constexpr void assign(char_type &lhs, const char_type &rhs) noexcept
赋值单个字符