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