Line | Branch | Exec | Source |
---|---|---|---|
1 | #ifndef UTIL_ASCII_H | ||
2 | #define UTIL_ASCII_H | ||
3 | |||
4 | #include <stdbool.h> | ||
5 | #include <stddef.h> | ||
6 | #include <stdint.h> | ||
7 | #include "macros.h" | ||
8 | |||
9 | extern const uint8_t ascii_table[256]; | ||
10 | |||
11 | typedef enum { | ||
12 | ASCII_SPACE = 0x01, | ||
13 | ASCII_DIGIT = 0x02, | ||
14 | ASCII_CNTRL = 0x04, | ||
15 | ASCII_REGEX = 0x08, // [$()*+.?[^{|\] | ||
16 | ASCII_LOWER = 0x10, | ||
17 | ASCII_UPPER = 0x20, | ||
18 | ASCII_UNDERSCORE = 0x40, | ||
19 | ASCII_NONASCII = 0x80, | ||
20 | ASCII_ALPHA = ASCII_LOWER | ASCII_UPPER, | ||
21 | ASCII_ALNUM = ASCII_ALPHA | ASCII_DIGIT, | ||
22 | ASCII_WORDBYTE = ASCII_ALNUM | ASCII_UNDERSCORE | ASCII_NONASCII, | ||
23 | } AsciiCharType; | ||
24 | |||
25 | #define ascii_isspace(x) ascii_test(x, ASCII_SPACE) | ||
26 | #define ascii_iscntrl(x) ascii_test(x, ASCII_CNTRL) | ||
27 | #define ascii_islower(x) ascii_test(x, ASCII_LOWER) | ||
28 | #define ascii_isupper(x) ascii_test(x, ASCII_UPPER) | ||
29 | #define ascii_isalpha(x) ascii_test(x, ASCII_ALPHA) | ||
30 | #define ascii_isalnum(x) ascii_test(x, ASCII_ALNUM) | ||
31 | #define ascii_isprint(x) (!ascii_test(x, ASCII_CNTRL | ASCII_NONASCII)) | ||
32 | |||
33 | #define is_alpha_or_underscore(x) ascii_test(x, ASCII_ALPHA | ASCII_UNDERSCORE) | ||
34 | #define is_alnum_or_underscore(x) ascii_test(x, ASCII_ALNUM | ASCII_UNDERSCORE) | ||
35 | #define is_regex_special_char(x) ascii_test(x, ASCII_REGEX) | ||
36 | #define is_word_byte(x) ascii_test(x, ASCII_WORDBYTE) | ||
37 | |||
38 | 74229 | static inline bool ascii_test(unsigned char c, AsciiCharType mask) | |
39 | { | ||
40 | 74229 | return (ascii_table[c] & mask) != 0; | |
41 | } | ||
42 | |||
43 | 8054 | static inline bool ascii_isblank(unsigned char c) | |
44 | { | ||
45 | 8054 | return c == ' ' || c == '\t'; | |
46 | } | ||
47 | |||
48 | 1770 | static inline bool ascii_isdigit(unsigned char c) | |
49 | { | ||
50 | 1770 | return (unsigned int)c - '0' <= 9; | |
51 | } | ||
52 | |||
53 | 81 | static inline bool ascii_is_digit_or_dot(unsigned char c) | |
54 | { | ||
55 |
4/4✓ Branch 0 taken 70 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 5 times.
|
81 | return ascii_isdigit(c) || c == '.'; |
56 | } | ||
57 | |||
58 | 269 | static inline bool ascii_is_nonspace_cntrl(unsigned char c) | |
59 | { | ||
60 | 269 | return ascii_table[c] == ASCII_CNTRL; | |
61 | } | ||
62 | |||
63 | 51843 | static inline unsigned char ascii_tolower(unsigned char c) | |
64 | { | ||
65 | 51843 | static_assert(ASCII_UPPER == 0x20); | |
66 | 51843 | return c + (ascii_table[c] & ASCII_UPPER); | |
67 | } | ||
68 | |||
69 | 272 | static inline unsigned char ascii_toupper(unsigned char c) | |
70 | { | ||
71 | 272 | static_assert(ASCII_LOWER << 1 == 0x20); | |
72 | 272 | return c - ((ascii_table[c] & ASCII_LOWER) << 1); | |
73 | } | ||
74 | |||
75 | NONNULL_ARGS | ||
76 | 7360 | static inline int ascii_strcmp_icase(const char *s1, const char *s2) | |
77 | { | ||
78 | 12242 | unsigned char c1, c2; | |
79 | 12242 | do { | |
80 | 12242 | c1 = ascii_tolower(*s1++); | |
81 | 12242 | c2 = ascii_tolower(*s2++); | |
82 |
2/2✓ Branch 0 taken 4882 times.
✓ Branch 1 taken 7360 times.
|
12242 | } while (c1 && c1 == c2); |
83 | |||
84 | 7360 | return c1 - c2; | |
85 | } | ||
86 | |||
87 | NONNULL_ARGS | ||
88 | 6990 | static inline bool ascii_streq_icase(const char *s1, const char *s2) | |
89 | { | ||
90 | 6990 | return ascii_strcmp_icase(s1, s2) == 0; | |
91 | } | ||
92 | |||
93 | 8471 | static inline size_t ascii_blank_prefix_length(const char *str, size_t len) | |
94 | { | ||
95 | 8471 | size_t i = 0; | |
96 |
4/4✓ Branch 0 taken 7491 times.
✓ Branch 1 taken 1356 times.
✓ Branch 2 taken 376 times.
✓ Branch 3 taken 7115 times.
|
8847 | while (i < len && ascii_isblank(str[i])) { |
97 | 376 | i++; | |
98 | } | ||
99 | 8471 | return i; | |
100 | } | ||
101 | |||
102 | 3 | static inline bool strn_contains_char_type(const char *str, size_t len, AsciiCharType mask) | |
103 | { | ||
104 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 3 times.
|
23 | for (size_t i = 0; i < len; i++) { |
105 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | if (ascii_test(str[i], mask)) { |
106 | return true; | ||
107 | } | ||
108 | } | ||
109 | return false; | ||
110 | } | ||
111 | |||
112 | #endif | ||
113 |