File Coverage

tstr_packed_alpha.h
Criterion Covered Total %
statement 10 12 83.3
branch 5 8 62.5
condition n/a
subroutine n/a
pod n/a
total 15 20 75.0


line stmt bran cond sub pod time code
1             #ifndef TSTR_PACKED_ALPHA_H
2             #define TSTR_PACKED_ALPHA_H
3              
4             #include
5             #include
6              
7             /*
8             * Pack up to 12 ASCII letters into a uint64_t using 5 bits per character.
9             *
10             * Case-insensitive: a-z => 1-26, packed MSB-first.
11             * Returns the number of characters consumed, or 0 if none or >12.
12             */
13 181           static inline size_t tstr_packed_alpha_encode(const char* str,
14             size_t len,
15             uint64_t* packed) {
16 181           const unsigned char* src = (const unsigned char*)str;
17             uint64_t enc;
18             size_t i;
19              
20 790 100         for (enc = 0, i = 0; i < len; i++) {
21 609           unsigned char lower = src[i] | 0x20;
22             unsigned char c;
23              
24 609 50         if (lower - 'a' <= (unsigned)('z' - 'a'))
25 609           c = lower - 'a' + 1;
26             else
27 0           break;
28              
29 609           enc = (enc << 5) | c;
30             }
31              
32 181 50         if (i == 0 || i > 12)
    50          
33 0           return 0;
34 181           *packed = enc;
35 181           return i;
36             }
37              
38             /* clang-format off */
39             #define TSTR_PACKED_ALPHA_MAP_CHAR(c) \
40             ( ((c) == 'A' || (c) == 'a') ? 1 : \
41             ((c) == 'B' || (c) == 'b') ? 2 : \
42             ((c) == 'C' || (c) == 'c') ? 3 : \
43             ((c) == 'D' || (c) == 'd') ? 4 : \
44             ((c) == 'E' || (c) == 'e') ? 5 : \
45             ((c) == 'F' || (c) == 'f') ? 6 : \
46             ((c) == 'G' || (c) == 'g') ? 7 : \
47             ((c) == 'H' || (c) == 'h') ? 8 : \
48             ((c) == 'I' || (c) == 'i') ? 9 : \
49             ((c) == 'J' || (c) == 'j') ? 10 : \
50             ((c) == 'K' || (c) == 'k') ? 11 : \
51             ((c) == 'L' || (c) == 'l') ? 12 : \
52             ((c) == 'M' || (c) == 'm') ? 13 : \
53             ((c) == 'N' || (c) == 'n') ? 14 : \
54             ((c) == 'O' || (c) == 'o') ? 15 : \
55             ((c) == 'P' || (c) == 'p') ? 16 : \
56             ((c) == 'Q' || (c) == 'q') ? 17 : \
57             ((c) == 'R' || (c) == 'r') ? 18 : \
58             ((c) == 'S' || (c) == 's') ? 19 : \
59             ((c) == 'T' || (c) == 't') ? 20 : \
60             ((c) == 'U' || (c) == 'u') ? 21 : \
61             ((c) == 'V' || (c) == 'v') ? 22 : \
62             ((c) == 'W' || (c) == 'w') ? 23 : \
63             ((c) == 'X' || (c) == 'x') ? 24 : \
64             ((c) == 'Y' || (c) == 'y') ? 25 : \
65             ((c) == 'Z' || (c) == 'z') ? 26 : \
66             0 )
67              
68             #define TSTR_PACKED_ALPHA1(c1) \
69             ((uint64_t)(TSTR_PACKED_ALPHA_MAP_CHAR(c1) & 0x1F))
70             #define TSTR_PACKED_ALPHA2(c1, c2) \
71             ((TSTR_PACKED_ALPHA1(c1) << (5*1)) | TSTR_PACKED_ALPHA1(c2))
72             #define TSTR_PACKED_ALPHA3(c1, c2, c3) \
73             ((TSTR_PACKED_ALPHA1(c1) << (5*2)) | TSTR_PACKED_ALPHA2(c2, c3))
74             #define TSTR_PACKED_ALPHA4(c1, c2, c3, c4) \
75             ((TSTR_PACKED_ALPHA1(c1) << (5*3)) | TSTR_PACKED_ALPHA3(c2, c3, c4))
76             #define TSTR_PACKED_ALPHA5(c1, c2, c3, c4, c5) \
77             ((TSTR_PACKED_ALPHA1(c1) << (5*4)) | TSTR_PACKED_ALPHA4(c2, c3, c4, c5))
78             #define TSTR_PACKED_ALPHA6(c1, c2, c3, c4, c5, c6) \
79             ((TSTR_PACKED_ALPHA1(c1) << (5*5)) | TSTR_PACKED_ALPHA5(c2, c3, c4, c5, c6))
80             #define TSTR_PACKED_ALPHA7(c1, c2, c3, c4, c5, c6, c7) \
81             ((TSTR_PACKED_ALPHA1(c1) << (5*6)) | TSTR_PACKED_ALPHA6(c2, c3, c4, c5, c6, c7))
82             #define TSTR_PACKED_ALPHA8(c1, c2, c3, c4, c5, c6, c7, c8) \
83             ((TSTR_PACKED_ALPHA1(c1) << (5*7)) | TSTR_PACKED_ALPHA7(c2, c3, c4, c5, c6, c7, c8))
84             #define TSTR_PACKED_ALPHA9(c1, c2, c3, c4, c5, c6, c7, c8, c9) \
85             ((TSTR_PACKED_ALPHA1(c1) << (5*8)) | TSTR_PACKED_ALPHA8(c2, c3, c4, c5, c6, c7, c8, c9))
86             #define TSTR_PACKED_ALPHA10(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10) \
87             ((TSTR_PACKED_ALPHA1(c1) << (5*9)) | TSTR_PACKED_ALPHA9(c2, c3, c4, c5, c6, c7, c8, c9, c10))
88             #define TSTR_PACKED_ALPHA11(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11) \
89             ((TSTR_PACKED_ALPHA1(c1) << (5*10)) | TSTR_PACKED_ALPHA10(c2, c3, c4, c5, c6, c7, c8, c9, c10, c11))
90             #define TSTR_PACKED_ALPHA12(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12) \
91             ((TSTR_PACKED_ALPHA1(c1) << (5*11)) | TSTR_PACKED_ALPHA11(c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12))
92             /* clang-format on */
93              
94             #endif /* TSTR_PACKED_ALPHA_H */