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