/src/systemd/src/basic/string-table.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | | |
3 | | #pragma once |
4 | | |
5 | | #include <errno.h> |
6 | | #include <stddef.h> |
7 | | #include <stdio.h> |
8 | | #include <sys/types.h> |
9 | | |
10 | | #include "macro.h" |
11 | | #include "parse-util.h" |
12 | | #include "string-util.h" |
13 | | |
14 | | ssize_t string_table_lookup(const char * const *table, size_t len, const char *key); |
15 | | |
16 | | /* For basic lookup tables with strictly enumerated entries */ |
17 | | #define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ |
18 | 0 | scope const char *name##_to_string(type i) { \ |
19 | 0 | if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \ |
20 | 0 | return NULL; \ |
21 | 0 | return name##_table[i]; \ |
22 | 0 | } |
23 | | |
24 | | #define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ |
25 | 199 | scope type name##_from_string(const char *s) { \ |
26 | 199 | return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ |
27 | 199 | } |
28 | | |
29 | | #define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \ |
30 | | scope type name##_from_string(const char *s) { \ |
31 | | if (!s) \ |
32 | | return -EINVAL; \ |
33 | | int b = parse_boolean(s); \ |
34 | | if (b == 0) \ |
35 | | return (type) 0; \ |
36 | | if (b > 0) \ |
37 | | return yes; \ |
38 | | return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ |
39 | | } |
40 | | |
41 | | #define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,scope) \ |
42 | | scope int name##_to_string_alloc(type i, char **str) { \ |
43 | | char *s; \ |
44 | | if (i < 0 || i > max) \ |
45 | | return -ERANGE; \ |
46 | | if (i < (type) ELEMENTSOF(name##_table) && name##_table[i]) { \ |
47 | | s = strdup(name##_table[i]); \ |
48 | | if (!s) \ |
49 | | return -ENOMEM; \ |
50 | | } else { \ |
51 | | if (asprintf(&s, "%i", i) < 0) \ |
52 | | return -ENOMEM; \ |
53 | | } \ |
54 | | *str = s; \ |
55 | | return 0; \ |
56 | | } |
57 | | |
58 | | #define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,scope) \ |
59 | | scope type name##_from_string(const char *s) { \ |
60 | | unsigned u = 0; \ |
61 | | type i; \ |
62 | | if (!s) \ |
63 | | return -EINVAL; \ |
64 | | i = (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ |
65 | | if (i >= 0) \ |
66 | | return i; \ |
67 | | if (safe_atou(s, &u) < 0) \ |
68 | | return -EINVAL; \ |
69 | | if (u > max) \ |
70 | | return -EINVAL; \ |
71 | | return (type) u; \ |
72 | | } |
73 | | |
74 | | #define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ |
75 | | _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ |
76 | | _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) |
77 | | |
78 | | #define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \ |
79 | | _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ |
80 | | _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) |
81 | | |
82 | | #define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,) |
83 | | #define DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,) |
84 | | #define DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,) |
85 | | #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static) |
86 | | #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static) |
87 | | #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static) |
88 | | |
89 | | #define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,) |
90 | | #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,static) |
91 | | #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes) \ |
92 | | _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,static) |
93 | | |
94 | | /* For string conversions where numbers are also acceptable */ |
95 | | #define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \ |
96 | | _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,) \ |
97 | | _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,) |
98 | | |
99 | | #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max) \ |
100 | | _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static) |
101 | | #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \ |
102 | | _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static) |
103 | | |
104 | | #define DUMP_STRING_TABLE(name,type,max) \ |
105 | | do { \ |
106 | | flockfile(stdout); \ |
107 | | for (type _k = 0; _k < (max); _k++) { \ |
108 | | const char *_t; \ |
109 | | _t = name##_to_string(_k); \ |
110 | | if (!_t) \ |
111 | | continue; \ |
112 | | fputs_unlocked(_t, stdout); \ |
113 | | fputc_unlocked('\n', stdout); \ |
114 | | } \ |
115 | | funlockfile(stdout); \ |
116 | | } while (false) |