1#include "include/pw.h"
2#include "src/types/string/string_internal.h"
3
4bool _pw_strstr(PwValuePtr str, PwValuePtr substr, unsigned start_pos, unsigned* pos)
5{
6 pw_assert_string(str);
7 pw_assert_string(substr);
8
9 uint8_t substr_char_size = substr->char_size;
10 uint8_t* substr_end_ptr;
11 uint8_t* substr_start_ptr = _pw_string_start_end(substr, &substr_end_ptr);
12 if (_pw_unlikely(substr_start_ptr >= substr_end_ptr)) {
13 // empty substring
14 return false;
15 }
16
17 uint8_t str_char_size = str->char_size;
18 uint8_t* str_end_ptr;
19 uint8_t* str_start_ptr = _pw_string_start_end(str, &str_end_ptr);
20 str_start_ptr += start_pos * str_char_size;
21
22 char32_t start_codepoint = _pw_get_char(substr_start_ptr, substr_char_size);
23 if (_pw_unlikely(start_codepoint >= (1ULL << (8 * str_char_size)))) {
24 return false;
25 }
26
27 StrChr fn_strchr = _pw_strchr_variants[str_char_size];
28 SubstrEq fn_substreq = _pw_substreq_variants[str_char_size][substr_char_size];
29
30 str_end_ptr -= substr_end_ptr - substr_start_ptr - 1; // reduce by strlen(substr) - 1
31 for (uint8_t* str_ptr = str_start_ptr; str_start_ptr < str_end_ptr; ) {
32
33 uint8_t* maybe_substr = fn_strchr(str_ptr, str_end_ptr, start_codepoint);
34 if (!maybe_substr) {
35 break;
36 }
37 if (fn_substreq(maybe_substr, substr_start_ptr, substr_end_ptr)) {
38 if (pos) {
39 *pos = start_pos + (maybe_substr - str_start_ptr) / str_char_size;
40 }
41 return true;
42 }
43 str_ptr = maybe_substr + str_char_size;
44 }
45 return false;
46}