1#include <string.h>
2
3#include "include/pw.h"
4#include "src/types/string/string_internal.h"
5
6
7static uint8_t* strchr2_1(uint8_t* start_ptr, uint8_t* end_ptr, char32_t codepoint, uint8_t* char_size)
8{
9 *char_size = 1;
10 return memchr(start_ptr, (uint8_t) codepoint, end_ptr - start_ptr);
11}
12
13static uint8_t* strchr2_2(uint8_t* start_ptr, uint8_t* end_ptr, char32_t codepoint, uint8_t* char_size)
14{
15 char32_t width = 0;
16 while (start_ptr < end_ptr) {
17 char32_t c = *(uint16_t*) start_ptr;
18 width |= c;
19 if (c == codepoint) {
20 *char_size = calc_char_size(width);
21 return start_ptr;
22 }
23 start_ptr += 2;
24 }
25 *char_size = calc_char_size(width);
26 return nullptr;
27}
28
29static uint8_t* strchr2_3(uint8_t* start_ptr, uint8_t* end_ptr, char32_t codepoint, uint8_t* char_size)
30{
31 char32_t width = 0;
32 while (start_ptr < end_ptr) {
33 char32_t c = *start_ptr++;
34 c |= (*start_ptr++) << 8;
35 c |= (*start_ptr++) << 16;
36 width |= c;
37 if (c == codepoint) {
38 *char_size = calc_char_size(width);
39 return start_ptr - 3;
40 }
41 }
42 *char_size = calc_char_size(width);
43 return nullptr;
44}
45
46static uint8_t* strchr2_4(uint8_t* start_ptr, uint8_t* end_ptr, char32_t codepoint, uint8_t* char_size)
47{
48 char32_t width = 0;
49 while (start_ptr < end_ptr) {
50 char32_t c = *(char32_t*) start_ptr;
51 width |= c;
52 if (c == codepoint) {
53 *char_size = calc_char_size(width);
54 return start_ptr;
55 }
56 start_ptr += 4;
57 }
58 *char_size = calc_char_size(width);
59 return nullptr;
60}
61
62StrChr2 _pw_strchr2_variants[5] = {
63 nullptr,
64 strchr2_1,
65 strchr2_2,
66 strchr2_3,
67 strchr2_4
68};
69
70[[nodiscard]] bool pw_strchr2(PwValuePtr str, char32_t chr, unsigned start_pos, unsigned* result, uint8_t* max_char_size)
71{
72 pw_assert_string(str);
73 uint8_t char_size = str->char_size;
74 uint8_t* end_ptr;
75 uint8_t* start_ptr = _pw_string_start_end(str, &end_ptr) + start_pos * char_size;
76 if (_pw_unlikely(start_ptr >= end_ptr)) {
77 *max_char_size = 1;
78 return false;
79 }
80 StrChr2 fn_strchr2 = _pw_strchr2_variants[char_size];
81 return fn_strchr2(start_ptr, end_ptr, chr, max_char_size);
82}