File Coverage

include/horus_parse.h
Criterion Covered Total %
statement 23 34 67.6
branch 20 40 50.0
condition n/a
subroutine n/a
pod n/a
total 43 74 58.1


line stmt bran cond sub pod time code
1             #ifndef HORUS_PARSE_H
2             #define HORUS_PARSE_H
3              
4             /*
5             * horus_parse.h - Universal UUID parser: any format string -> 16-byte binary
6             *
7             * Auto-detects format from input length and content.
8             */
9              
10             #include
11              
12             /* Return values */
13             #define HORUS_PARSE_OK 1
14             #define HORUS_PARSE_ERROR 0
15              
16             /*
17             * Parse a UUID string of any supported format into a 16-byte binary buffer.
18             * Returns HORUS_PARSE_OK on success, HORUS_PARSE_ERROR on failure.
19             */
20 193           static inline int horus_parse_uuid(unsigned char *out,
21             const char *input, size_t len) {
22             /* Raw binary: 16 bytes */
23 193 100         if (len == 16) {
24 62           memcpy(out, input, 16);
25 62           return HORUS_PARSE_OK;
26             }
27              
28             /* Base64: 22 chars */
29 131 100         if (len == 22) {
30 6           int n = horus_base64_decode(out, input, 22);
31 6           return (n >= 16) ? HORUS_PARSE_OK : HORUS_PARSE_ERROR;
32             }
33              
34             /* Base32: 26 chars */
35 125 50         if (len == 26) {
36             /* Detect Crockford vs RFC 4648 by checking for Crockford-only chars
37             * Crockford uses 0-9A-Z minus I,L,O,U
38             * RFC 4648 uses A-Z2-7
39             * If we see any of 0,1,8,9 it's Crockford; if we see any of a-z
40             * we try both with standard first */
41 0           int has_digit_019 = 0;
42             int i;
43 0 0         for (i = 0; i < 26; i++) {
44 0           char c = input[i];
45 0 0         if (c == '8' || c == '9' || c == '0' || c == '1') {
    0          
    0          
    0          
46 0           has_digit_019 = 1;
47 0           break;
48             }
49             }
50 0 0         if (has_digit_019) {
51 0           int n = horus_crockford_decode(out, input, 26);
52 0           return (n >= 16) ? HORUS_PARSE_OK : HORUS_PARSE_ERROR;
53             } else {
54 0           int n = horus_base32_decode(out, input, 26);
55 0           return (n >= 16) ? HORUS_PARSE_OK : HORUS_PARSE_ERROR;
56             }
57             }
58              
59             /* No hyphens hex: 32 chars */
60 125 100         if (len == 32) {
61 13           return horus_hex_decode(out, input, 32) ? HORUS_PARSE_OK : HORUS_PARSE_ERROR;
62             }
63              
64             /* Standard hyphenated: 36 chars (8-4-4-4-12) */
65 112 100         if (len == 36 && input[8] == '-' && input[13] == '-'
    50          
    50          
66 95 50         && input[18] == '-' && input[23] == '-') {
    50          
67             char hex[32];
68 95           memcpy(hex, input, 8); /* time_low */
69 95           memcpy(hex + 8, input + 9, 4); /* time_mid */
70 95           memcpy(hex + 12, input + 14, 4); /* time_hi */
71 95           memcpy(hex + 16, input + 19, 4); /* clock_seq */
72 95           memcpy(hex + 20, input + 24, 12); /* node */
73 95           return horus_hex_decode(out, hex, 32) ? HORUS_PARSE_OK : HORUS_PARSE_ERROR;
74             }
75              
76             /* Braces: 38 chars {8-4-4-4-12} */
77 17 100         if (len == 38 && input[0] == '{' && input[37] == '}') {
    50          
    50          
78 6           return horus_parse_uuid(out, input + 1, 36);
79             }
80              
81             /* URN: 45 chars urn:uuid:8-4-4-4-12 */
82 11 100         if (len >= 45 && memcmp(input, "urn:uuid:", 9) == 0) {
    50          
83 6           return horus_parse_uuid(out, input + 9, len - 9);
84             }
85              
86 5           return HORUS_PARSE_ERROR;
87             }
88              
89             #endif /* HORUS_PARSE_H */