@@ -115,11 +115,73 @@ template <typename CharT, typename Iterator, typename EndIterator> constexpr CTR
115
115
return false ;
116
116
}
117
117
118
- template <auto ... String, size_t ... Idx, typename Iterator, typename EndIterator> constexpr CTRE_FORCE_INLINE string_match_result<Iterator> evaluate_match_string (Iterator current, [[maybe_unused]] const EndIterator end, std::index_sequence<Idx...>) noexcept {
119
-
120
- bool same = (compare_character (String, current, end) && ... && true );
118
+ #if __cpp_char8_t >= 201811
119
+ template <size_t N, size_t ... Idx, typename Iterator, typename EndIterator> constexpr CTRE_FORCE_INLINE string_match_result<Iterator> evaluate_match_utf8_string (Iterator current, [[maybe_unused]] const EndIterator end, char8_t (&buffer)[N], std::index_sequence<Idx...>) noexcept {
120
+ // abuse inside knowledge of how utf8_iterator works
121
+ if constexpr (!std::is_same_v<::std::remove_const_t <EndIterator>, utf8_iterator::sentinel>) {
122
+ size_t count = end.ptr - current.ptr ; // size_t count = std::distance(current.ptr, end.ptr);
123
+ size_t bump = ((count < N) ? count : N);
124
+ // using ^ operator vs != because gcc complains about parens
125
+ #if defined(__GNUC__) && !defined(__clang__)
126
+ return { Iterator{current.ptr + bump, current.end }, (count >= N) && !(bool )(((current.ptr [Idx] != buffer[Idx])) + ... + size_t {0 }) };
127
+ #else
128
+ return { Iterator{current.ptr + bump, current.end }, (count >= N) && !(bool )(((current.ptr [Idx] ^ buffer[Idx])) | ... | char8_t {0 }) };
129
+ #endif
130
+ } else {
131
+ size_t count = current.end - current.ptr ; // size_t count = std::distance(current.ptr, current.end);
132
+ size_t bump = ((count < N) ? count : N);
133
+ #if defined(__GNUC__) && !defined(__clang__)
134
+ return { Iterator{current.ptr + bump, current.end }, (count >= N) && !(bool )(((current.ptr [Idx] != buffer[Idx])) + ... + size_t {0 }) };
135
+ #else
136
+ return { Iterator{current.ptr + bump, current.end }, (count >= N) && !(bool )(((current.ptr [Idx] ^ buffer[Idx])) | ... | char8_t {0 }) };
137
+ #endif
138
+ }
139
+ }
140
+ #endif
121
141
122
- return {current, same};
142
+ template <auto ... String, size_t ... Idx, typename Iterator, typename EndIterator> constexpr CTRE_FORCE_INLINE string_match_result<Iterator> evaluate_match_string (Iterator current, [[maybe_unused]] const EndIterator end, std::index_sequence<Idx...>) noexcept {
143
+ #if __cpp_char8_t >= 201811
144
+ if constexpr (sizeof ...(String) && std::is_same_v<::std::remove_const_t <Iterator>, utf8_iterator> && (std::is_same_v<std::remove_const_t <Iterator>, std::remove_const_t <EndIterator>> || std::is_same_v<::std::remove_const_t <EndIterator>, utf8_iterator::sentinel>)) {
145
+ constexpr size_t str_length = (utf8_codepoint_length (String) + ... + 0ULL );
146
+ // encode our String... into it's utf8 representation
147
+ char8_t utf8_sequence[str_length];
148
+ char8_t * ptr = utf8_sequence;
149
+ ((ptr = utf32_codepoint_to_utf8_codepoint (String, ptr)), ...);
150
+ // run the comparison
151
+ return evaluate_match_utf8_string (current, end, utf8_sequence, std::make_index_sequence<str_length>());
152
+ } else if constexpr (sizeof ...(String) && is_random_accessible (typename std::iterator_traits<Iterator>::iterator_category{}) && std::is_same_v<std::remove_const_t <Iterator>, std::remove_const_t <EndIterator>>) {
153
+ using char_type = ::std::remove_reference_t <::std::remove_cv_t <decltype (*current)>>;
154
+ // check the remaining bytes*
155
+ size_t count = end - current;
156
+ // make sure we only "bump" the iterator a safe distance
157
+ size_t bump = ((count < sizeof ...(String)) ? count : sizeof ...(String));
158
+ // do math against how many characters we match, avoid as many branches as possible
159
+ #if defined(__GNUC__) && !defined(__clang__)
160
+ // because gcc's pedantic about binary operators and parens
161
+ return { current + bump, (count >= sizeof ...(String)) && !(bool )(((current[Idx] != static_cast <char_type>(String))) + ... + size_t {0 }) };
162
+ #else
163
+ return { current + bump, (count >= sizeof ...(String)) && !(bool )(((current[Idx] ^ static_cast <char_type>(String))) | ... | char_type{0 }) };
164
+ #endif
165
+ } else {
166
+ bool same = (compare_character (String, current, end) && ... && true );
167
+ return { current, same };
168
+ }
169
+ #else
170
+ if constexpr (sizeof ...(String) && is_random_accessible (typename std::iterator_traits<Iterator>::iterator_category{}) && std::is_same_v<std::remove_const_t <Iterator>, std::remove_const_t <EndIterator>>) {
171
+ using char_type = ::std::remove_reference_t <::std::remove_cv_t <decltype (*current)>>;
172
+ size_t count = end - current;
173
+ size_t bump = ((count < sizeof ...(String)) ? count : sizeof ...(String));
174
+ #if defined(__GNUC__) && !defined(__clang__)
175
+ // because gcc's pedantic about binary operators and parens
176
+ return { current + bump, (count >= sizeof ...(String)) && !(bool )(((current[Idx] != static_cast <char_type>(String))) + ... + size_t {0 }) };
177
+ #else
178
+ return { current + bump, (count >= sizeof ...(String)) && !(bool )(((current[Idx] ^ static_cast <char_type>(String))) | ... | char_type{0 }) };
179
+ #endif
180
+ } else {
181
+ bool same = (compare_character (String, current, end) && ... && true );
182
+ return { current, same };
183
+ }
184
+ #endif
123
185
}
124
186
125
187
template <typename R, typename Iterator, typename EndIterator, auto ... String, typename ... Tail>
0 commit comments