1 /* $NetBSD: enum.h,v 1.19 2021/03/15 16:00:05 rillig Exp $ */
4 Copyright (c) 2020 Roland Illig <rillig@NetBSD.org>
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE.
33 /* Generate string representations for bitmasks and simple enums. */
37 typedef struct EnumToStringSpec {
43 const char *Enum_FlagsToString(char *, size_t, int, const EnumToStringSpec *);
46 /* For Enum_FlagsToString, the separator between flags. */
50 * Generate the string that joins all possible flags, to see how large the
53 #define ENUM__JOIN_STR_1(v1) \
55 #define ENUM__JOIN_STR_2(v1, v2) \
56 ENUM__JOIN_STR_1(v1) ENUM__SEP \
58 #define ENUM__JOIN_STR_4(v1, v2, v3, v4) \
59 ENUM__JOIN_STR_2(v1, v2) ENUM__SEP \
60 ENUM__JOIN_STR_2(v3, v4)
61 #define ENUM__JOIN_STR_8(v1, v2, v3, v4, v5, v6, v7, v8) \
62 ENUM__JOIN_STR_4(v1, v2, v3, v4) ENUM__SEP \
63 ENUM__JOIN_STR_4(v5, v6, v7, v8)
64 #define ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
65 v09, v10, v11, v12, v13, v14, v15, v16) \
66 ENUM__JOIN_STR_8(v01, v02, v03, v04, v05, v06, v07, v08) ENUM__SEP \
67 ENUM__JOIN_STR_8(v09, v10, v11, v12, v13, v14, v15, v16)
69 #define ENUM__JOIN_2(part1, part2) \
71 #define ENUM__JOIN_3(part1, part2, part3) \
72 part1 ENUM__SEP part2 ENUM__SEP part3
73 #define ENUM__JOIN_4(part1, part2, part3, part4) \
74 part1 ENUM__SEP part2 ENUM__SEP part3 ENUM__SEP part4
75 #define ENUM__JOIN_5(part1, part2, part3, part4, part5) \
76 part1 ENUM__SEP part2 ENUM__SEP part3 ENUM__SEP part4 ENUM__SEP part5
78 /* List the pairs of enum value and corresponding name. */
79 #define ENUM__SPEC_1(v1) \
81 #define ENUM__SPEC_2(v1, v2) \
84 #define ENUM__SPEC_4(v1, v2, v3, v4) \
85 ENUM__SPEC_2(v1, v2), \
87 #define ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8) \
88 ENUM__SPEC_4(v1, v2, v3, v4), \
89 ENUM__SPEC_4(v5, v6, v7, v8)
90 #define ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
91 v09, v10, v11, v12, v13, v14, v15, v16) \
92 ENUM__SPEC_8(v01, v02, v03, v04, v05, v06, v07, v08), \
93 ENUM__SPEC_8(v09, v10, v11, v12, v13, v14, v15, v16)
95 #define ENUM__SPECS_2(part1, part2) \
96 { part1, part2, { 0, "" } }
97 #define ENUM__SPECS_3(part1, part2, part3) \
98 { part1, part2, part3, { 0, "" } }
99 #define ENUM__SPECS_4(part1, part2, part3, part4) \
100 { part1, part2, part3, part4, { 0, "" } }
101 #define ENUM__SPECS_5(part1, part2, part3, part4, part5) \
102 { part1, part2, part3, part4, part5, { 0, "" } }
105 /* Declare the necessary data structures for calling Enum_FlagsToString. */
106 #define ENUM__FLAGS_RTTI(typnam, specs, joined) \
107 static const EnumToStringSpec typnam ## _ ## ToStringSpecs[] = specs; \
108 enum { typnam ## _ ## ToStringSize = sizeof (joined) }; \
109 MAKE_INLINE const char *typnam ## _ToString(char *buf, typnam value) \
110 { return Enum_FlagsToString(buf, typnam ## _ ## ToStringSize, \
111 value, typnam ## _ ## ToStringSpecs); \
113 extern void enum_flags_rtti_dummy(void)
116 * Declare the necessary data structures for calling Enum_FlagsToString
117 * for an enum with 3 flags.
119 #define ENUM_FLAGS_RTTI_3(typnam, v1, v2, v3) \
120 ENUM__FLAGS_RTTI(typnam, \
122 ENUM__SPEC_2(v1, v2), \
125 ENUM__JOIN_STR_2(v1, v2), \
126 ENUM__JOIN_STR_1(v3)))
129 * Declare the necessary data structures for calling Enum_FlagsToString
130 * for an enum with 6 flags.
132 #define ENUM_FLAGS_RTTI_6(typnam, v1, v2, v3, v4, v5, v6) \
133 ENUM__FLAGS_RTTI(typnam, \
135 ENUM__SPEC_4(v1, v2, v3, v4), \
136 ENUM__SPEC_2(v5, v6)), \
138 ENUM__JOIN_STR_4(v1, v2, v3, v4), \
139 ENUM__JOIN_STR_2(v5, v6)))
142 * Declare the necessary data structures for calling Enum_FlagsToString
143 * for an enum with 9 flags.
145 #define ENUM_FLAGS_RTTI_9(typnam, v1, v2, v3, v4, v5, v6, v7, v8, v9) \
146 ENUM__FLAGS_RTTI(typnam, \
148 ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8), \
151 ENUM__JOIN_STR_8(v1, v2, v3, v4, v5, v6, v7, v8), \
152 ENUM__JOIN_STR_1(v9)))
155 * Declare the necessary data structures for calling Enum_FlagsToString
156 * for an enum with 31 flags.
158 #define ENUM_FLAGS_RTTI_31(typnam, \
159 v01, v02, v03, v04, v05, v06, v07, v08, \
160 v09, v10, v11, v12, v13, v14, v15, v16, \
161 v17, v18, v19, v20, v21, v22, v23, v24, \
162 v25, v26, v27, v28, v29, v30, v31) \
163 ENUM__FLAGS_RTTI(typnam, \
165 ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
166 v09, v10, v11, v12, v13, v14, v15, v16), \
167 ENUM__SPEC_8(v17, v18, v19, v20, v21, v22, v23, v24), \
168 ENUM__SPEC_4(v25, v26, v27, v28), \
169 ENUM__SPEC_2(v29, v30), \
170 ENUM__SPEC_1(v31)), \
172 ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
173 v09, v10, v11, v12, v13, v14, v15, v16), \
174 ENUM__JOIN_STR_8(v17, v18, v19, v20, v21, v22, v23, v24), \
175 ENUM__JOIN_STR_4(v25, v26, v27, v28), \
176 ENUM__JOIN_STR_2(v29, v30), \
177 ENUM__JOIN_STR_1(v31)))