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