| 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_PUNCT = 0x40, | ||
| 19 | ASCII_UNDERSCORE = 0x80, | ||
| 20 | ASCII_ALPHA = ASCII_LOWER | ASCII_UPPER, | ||
| 21 | ASCII_ALNUM = ASCII_ALPHA | ASCII_DIGIT, | ||
| 22 | ASCII_NONWORD = ASCII_SPACE | ASCII_CNTRL | ASCII_PUNCT, | ||
| 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_ispunct(x) ascii_test(x, ASCII_PUNCT | ASCII_UNDERSCORE) | ||
| 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_NONWORD) // See comment in ascii.c | ||
| 37 | |||
| 38 | 108592 | static inline bool ascii_test(unsigned char c, AsciiCharType mask) | |
| 39 | { | ||
| 40 | 108592 | return (ascii_table[c] & mask) != 0; | |
| 41 | } | ||
| 42 | |||
| 43 | 277 | static inline bool ascii_isprint(unsigned char c) | |
| 44 | { | ||
| 45 | 277 | return c >= ' ' && c <= '~'; | |
| 46 | } | ||
| 47 | |||
| 48 | 9842 | static inline bool ascii_isblank(unsigned char c) | |
| 49 | { | ||
| 50 | 9842 | return c == ' ' || c == '\t'; | |
| 51 | } | ||
| 52 | |||
| 53 | 1930 | static inline bool ascii_isdigit(unsigned char c) | |
| 54 | { | ||
| 55 | 1930 | return c >= '0' && c <= '9'; | |
| 56 | } | ||
| 57 | |||
| 58 | 84 | static inline bool ascii_is_digit_or_dot(unsigned char c) | |
| 59 | { | ||
| 60 |
4/4✓ Branch 0 (2→3) taken 73 times.
✓ Branch 1 (2→5) taken 11 times.
✓ Branch 2 (3→4) taken 68 times.
✓ Branch 3 (3→5) taken 5 times.
|
84 | return ascii_isdigit(c) || c == '.'; |
| 61 | } | ||
| 62 | |||
| 63 | 16 | static inline bool ascii_is_nonspace_cntrl(unsigned char c) | |
| 64 | { | ||
| 65 | 16 | return ascii_table[c] == ASCII_CNTRL; | |
| 66 | } | ||
| 67 | |||
| 68 | 67023 | static inline unsigned char ascii_tolower(unsigned char c) | |
| 69 | { | ||
| 70 | 67023 | static_assert(ASCII_UPPER == 0x20); | |
| 71 | 67023 | return c + (ascii_table[c] & ASCII_UPPER); | |
| 72 | } | ||
| 73 | |||
| 74 | 334 | static inline unsigned char ascii_toupper(unsigned char c) | |
| 75 | { | ||
| 76 | 334 | static_assert(ASCII_LOWER << 1 == 0x20); | |
| 77 | 334 | return c - ((ascii_table[c] & ASCII_LOWER) << 1); | |
| 78 | } | ||
| 79 | |||
| 80 | NONNULL_ARGS | ||
| 81 | 11730 | static inline int ascii_strcmp_icase(const char *s1, const char *s2) | |
| 82 | { | ||
| 83 | 11730 | unsigned char c1, c2; | |
| 84 | 19360 | do { | |
| 85 | 19360 | c1 = ascii_tolower(*s1++); | |
| 86 | 19360 | c2 = ascii_tolower(*s2++); | |
| 87 |
2/2✓ Branch 0 (3→3) taken 7630 times.
✓ Branch 1 (3→4) taken 11730 times.
|
19360 | } while (c1 && c1 == c2); |
| 88 | |||
| 89 | 11730 | return c1 - c2; | |
| 90 | } | ||
| 91 | |||
| 92 | NONNULL_ARGS | ||
| 93 | 11264 | static inline bool ascii_streq_icase(const char *s1, const char *s2) | |
| 94 | { | ||
| 95 | 11264 | return ascii_strcmp_icase(s1, s2) == 0; | |
| 96 | } | ||
| 97 | |||
| 98 | 26 | static inline size_t ascii_type_prefix_length ( | |
| 99 | const char *str, | ||
| 100 | size_t len, | ||
| 101 | AsciiCharType mask | ||
| 102 | ) { | ||
| 103 | 26 | size_t i = 0; | |
| 104 |
4/4✓ Branch 0 (4→5) taken 185 times.
✓ Branch 1 (4→6) taken 12 times.
✓ Branch 2 (5→3) taken 171 times.
✓ Branch 3 (5→6) taken 14 times.
|
197 | while (i < len && ascii_test(str[i], mask)) { |
| 105 | 171 | i++; | |
| 106 | } | ||
| 107 | 26 | return i; | |
| 108 | } | ||
| 109 | |||
| 110 | 10300 | static inline size_t ascii_blank_prefix_length(const char *str, size_t len) | |
| 111 | { | ||
| 112 | 10300 | size_t i = 0; | |
| 113 |
4/4✓ Branch 0 (4→5) taken 9239 times.
✓ Branch 1 (4→6) taken 1536 times.
✓ Branch 2 (5→3) taken 475 times.
✓ Branch 3 (5→6) taken 8764 times.
|
10775 | while (i < len && ascii_isblank(str[i])) { |
| 114 | 475 | i++; | |
| 115 | } | ||
| 116 | 10300 | return i; | |
| 117 | } | ||
| 118 | |||
| 119 | #endif | ||
| 120 |