/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  | 19  |         scope type name##_from_string(const char *s) {                  \ | 
26  | 19  |                 return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \  | 
27  | 19  |         }  | 
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)  |