1#include "include/pw.h"
2#include "src/types/string/string_internal.h"
3
4#define is_ascii_digit(c) ('0' <= (c) && (c) <= '9')
5
6static bool is_digit_1(uint8_t* start_ptr, uint8_t* end_ptr)
7{
8 while (start_ptr < end_ptr) {
9 uint8_t c = *start_ptr++;
10 if (!is_ascii_digit(c)) {
11 return false;
12 }
13 }
14 return true;
15}
16
17#define IS_DIGIT(CHAR_TYPE, CHAR_SIZE) \
18 static bool is_digit_##CHAR_SIZE(uint8_t* start_ptr, uint8_t* end_ptr) \
19 { \
20 while (start_ptr < end_ptr) { \
21 char32_t c = *(CHAR_TYPE*) start_ptr; \
22 if (!pw_isdigit(c)) { \
23 return false; \
24 } \
25 start_ptr += CHAR_SIZE; \
26 } \
27 return true; \
28 }
29IS_DIGIT(uint16_t, 2)
30IS_DIGIT(char32_t, 4)
31
32static bool is_digit_3(uint8_t* start_ptr, uint8_t* end_ptr)
33{
34 while (start_ptr < end_ptr) {
35 char32_t c = *start_ptr++;
36 c |= (*start_ptr++) << 8;
37 c |= (*start_ptr++) << 16;
38 if (!pw_isdigit(c)) {
39 return false;
40 }
41 }
42 return true;
43}
44
45typedef bool (*StrIsDigit)(uint8_t* start_ptr, uint8_t* end_ptr);
46
47static StrIsDigit is_digit_variants[5] = {
48 nullptr,
49 is_digit_1,
50 is_digit_2,
51 is_digit_3,
52 is_digit_4
53};
54
55bool pw_string_isdigit(PwValuePtr str)
56{
57 pw_assert_string(str);
58 uint8_t* end_ptr;
59 uint8_t* start_ptr = _pw_string_start_end(str, &end_ptr);
60 if (_pw_unlikely(start_ptr == end_ptr)) {
61 return false;
62 }
63 StrIsDigit fn_is_digit = is_digit_variants[str->char_size];
64 return fn_is_digit(start_ptr, end_ptr);
65}