1#define _GNU_SOURCE // for memrchr
2#include <string.h>
3
4#include "include/pw.h"
5#include "src/types/string/string_internal.h"
6
7
8static uint8_t* strrchr2_1(uint8_t* start_ptr, uint8_t* end_ptr, char32_t codepoint, uint8_t* char_size)
9{
10 *char_size = 1;
11 return memrchr(start_ptr, (uint8_t) codepoint, end_ptr - start_ptr);
12}
13
14static uint8_t* strrchr2_2(uint8_t* start_ptr, uint8_t* end_ptr, char32_t codepoint, uint8_t* char_size)
15{
16 char32_t width = 0;
17 while (start_ptr < end_ptr) {
18 end_ptr -= 2;
19 char32_t c = *(uint16_t*) end_ptr;
20 width |= c;
21 if (c == codepoint) {
22 *char_size = calc_char_size(width);
23 return end_ptr;
24 }
25 }
26 *char_size = calc_char_size(width);
27 return nullptr;
28}
29
30static uint8_t* strrchr2_3(uint8_t* start_ptr, uint8_t* end_ptr, char32_t codepoint, uint8_t* char_size)
31{
32 char32_t width = 0;
33 while (start_ptr < end_ptr) {
34 end_ptr -= 3;
35 char32_t c = *end_ptr++;
36 c |= (*end_ptr++) << 8;
37 c |= (*end_ptr++) << 16;
38 end_ptr -= 3;
39 width |= c;
40 if (c == codepoint) {
41 *char_size = calc_char_size(width);
42 return end_ptr;
43 }
44 }
45 *char_size = calc_char_size(width);
46 return nullptr;
47}
48
49static uint8_t* strrchr2_4(uint8_t* start_ptr, uint8_t* end_ptr, char32_t codepoint, uint8_t* char_size)
50{
51 char32_t width = 0;
52 while (start_ptr < end_ptr) {
53 end_ptr -= 4;
54 char32_t c = *(char32_t*) end_ptr;
55 width |= c;
56 if (c == codepoint) {
57 *char_size = calc_char_size(width);
58 return end_ptr;
59 }
60 }
61 *char_size = calc_char_size(width);
62 return nullptr;
63}
64
65StrRChr2 _pw_strrchr2_variants[5] = {
66 nullptr,
67 strrchr2_1,
68 strrchr2_2,
69 strrchr2_3,
70 strrchr2_4
71};