1 /* $NetBSD: enum.h,v 1.12 2020/09/25 15:54:50 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 {
42 const char *Enum_FlagsToString(char *, size_t, int, const EnumToStringSpec *);
43 const char *Enum_ValueToString(int, const EnumToStringSpec *);
45 /* For Enum_FlagsToString, the separator between flags. */
48 /* Generate the string that joins all possible flags, to see how large the
50 #define ENUM__JOIN_STR_1(v1) \
52 #define ENUM__JOIN_STR_2(v1, v2) \
53 ENUM__JOIN_STR_1(v1) ENUM__SEP \
55 #define ENUM__JOIN_STR_4(v1, v2, v3, v4) \
56 ENUM__JOIN_STR_2(v1, v2) ENUM__SEP \
57 ENUM__JOIN_STR_2(v3, v4)
58 #define ENUM__JOIN_STR_8(v1, v2, v3, v4, v5, v6, v7, v8) \
59 ENUM__JOIN_STR_4(v1, v2, v3, v4) ENUM__SEP \
60 ENUM__JOIN_STR_4(v5, v6, v7, v8)
61 #define ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
62 v09, v10, v11, v12, v13, v14, v15, v16) \
63 ENUM__JOIN_STR_8(v01, v02, v03, v04, v05, v06, v07, v08) ENUM__SEP \
64 ENUM__JOIN_STR_8(v09, v10, v11, v12, v13, v14, v15, v16)
66 #define ENUM__JOIN_2(part1, part2) \
68 #define ENUM__JOIN_3(part1, part2, part3) \
69 part1 ENUM__SEP part2 ENUM__SEP part3
70 #define ENUM__JOIN_4(part1, part2, part3, part4) \
71 part1 ENUM__SEP part2 ENUM__SEP part3 ENUM__SEP part4
72 #define ENUM__JOIN_5(part1, part2, part3, part4, part5) \
73 part1 ENUM__SEP part2 ENUM__SEP part3 ENUM__SEP part4 ENUM__SEP part5
75 /* List the pairs of enum value and corresponding name. */
76 #define ENUM__SPEC_1(v1) \
78 #define ENUM__SPEC_2(v1, v2) \
81 #define ENUM__SPEC_4(v1, v2, v3, v4) \
82 ENUM__SPEC_2(v1, v2), \
84 #define ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8) \
85 ENUM__SPEC_4(v1, v2, v3, v4), \
86 ENUM__SPEC_4(v5, v6, v7, v8)
87 #define ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
88 v09, v10, v11, v12, v13, v14, v15, v16) \
89 ENUM__SPEC_8(v01, v02, v03, v04, v05, v06, v07, v08), \
90 ENUM__SPEC_8(v09, v10, v11, v12, v13, v14, v15, v16)
92 #define ENUM__SPECS_2(part1, part2) \
93 { part1, part2, { 0, "" } }
94 #define ENUM__SPECS_3(part1, part2, part3) \
95 { part1, part2, part3, { 0, "" } }
96 #define ENUM__SPECS_4(part1, part2, part3, part4) \
97 { part1, part2, part3, part4, { 0, "" } }
98 #define ENUM__SPECS_5(part1, part2, part3, part4, part5) \
99 { part1, part2, part3, part4, part5, { 0, "" } }
101 /* Declare the necessary data structures for calling Enum_ValueToString. */
102 #define ENUM__VALUE_RTTI(typnam, specs) \
103 static const EnumToStringSpec typnam ## _ ## ToStringSpecs[] = specs
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 }
110 /* Declare the necessary data structures for calling Enum_FlagsToString
111 * for an enum with 2 flags. */
112 #define ENUM_FLAGS_RTTI_2(typnam, v1, v2) \
113 ENUM__FLAGS_RTTI(typnam, \
118 ENUM__JOIN_STR_1(v1), \
119 ENUM__JOIN_STR_1(v2)))
121 /* Declare the necessary data structures for calling Enum_FlagsToString
122 * for an enum with 3 flags. */
123 #define ENUM_FLAGS_RTTI_3(typnam, v1, v2, v3) \
124 ENUM__FLAGS_RTTI(typnam, \
126 ENUM__SPEC_2(v1, v2), \
129 ENUM__JOIN_STR_2(v1, v2), \
130 ENUM__JOIN_STR_1(v3)))
132 /* Declare the necessary data structures for calling Enum_FlagsToString
133 * for an enum with 6 flags. */
134 #define ENUM_FLAGS_RTTI_6(typnam, v1, v2, v3, v4, v5, v6) \
135 ENUM__FLAGS_RTTI(typnam, \
137 ENUM__SPEC_4(v1, v2, v3, v4), \
138 ENUM__SPEC_2(v5, v6)), \
140 ENUM__JOIN_STR_4(v1, v2, v3, v4), \
141 ENUM__JOIN_STR_2(v5, v6)))
143 /* Declare the necessary data structures for calling Enum_FlagsToString
144 * for an enum with 8 flags. */
145 #define ENUM_FLAGS_RTTI_8(typnam, v1, v2, v3, v4, v5, v6, v7, v8) \
146 ENUM__FLAGS_RTTI(typnam, \
148 ENUM__SPEC_4(v1, v2, v3, v4), \
149 ENUM__SPEC_4(v5, v6, v7, v8)), \
151 ENUM__JOIN_STR_4(v1, v2, v3, v4), \
152 ENUM__JOIN_STR_4(v5, v6, v7, v8)))
154 /* Declare the necessary data structures for calling Enum_ValueToString
155 * for an enum with 8 constants. */
156 #define ENUM_VALUE_RTTI_8(typnam, v1, v2, v3, v4, v5, v6, v7, v8) \
157 ENUM__VALUE_RTTI(typnam, \
159 ENUM__SPEC_4(v1, v2, v3, v4), \
160 ENUM__SPEC_4(v5, v6, v7, v8)))
162 /* Declare the necessary data structures for calling Enum_FlagsToString
163 * for an enum with 10 flags. */
164 #define ENUM_FLAGS_RTTI_10(typnam, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) \
165 ENUM__FLAGS_RTTI(typnam, \
167 ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8), \
168 ENUM__SPEC_2(v9, v10)), \
170 ENUM__JOIN_STR_8(v1, v2, v3, v4, v5, v6, v7, v8), \
171 ENUM__JOIN_STR_2(v9, v10)))
173 /* Declare the necessary data structures for calling Enum_FlagsToString
174 * for an enum with 31 flags. */
175 #define ENUM_FLAGS_RTTI_31(typnam, \
176 v01, v02, v03, v04, v05, v06, v07, v08, \
177 v09, v10, v11, v12, v13, v14, v15, v16, \
178 v17, v18, v19, v20, v21, v22, v23, v24, \
179 v25, v26, v27, v28, v29, v30, v31) \
180 ENUM__FLAGS_RTTI(typnam, \
182 ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
183 v09, v10, v11, v12, v13, v14, v15, v16), \
184 ENUM__SPEC_8(v17, v18, v19, v20, v21, v22, v23, v24), \
185 ENUM__SPEC_4(v25, v26, v27, v28), \
186 ENUM__SPEC_2(v29, v30), \
187 ENUM__SPEC_1(v31)), \
189 ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
190 v09, v10, v11, v12, v13, v14, v15, v16), \
191 ENUM__JOIN_STR_8(v17, v18, v19, v20, v21, v22, v23, v24), \
192 ENUM__JOIN_STR_4(v25, v26, v27, v28), \
193 ENUM__JOIN_STR_2(v29, v30), \
194 ENUM__JOIN_STR_1(v31)))
196 /* Declare the necessary data structures for calling Enum_FlagsToString
197 * for an enum with 32 flags. */
198 #define ENUM_FLAGS_RTTI_32(typnam, \
199 v01, v02, v03, v04, v05, v06, v07, v08, \
200 v09, v10, v11, v12, v13, v14, v15, v16, \
201 v17, v18, v19, v20, v21, v22, v23, v24, \
202 v25, v26, v27, v28, v29, v30, v31, v32) \
203 ENUM__FLAGS_RTTI(typnam, \
205 ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
206 v09, v10, v11, v12, v13, v14, v15, v16), \
207 ENUM__SPEC_16(v17, v18, v19, v20, v21, v22, v23, v24, \
208 v25, v26, v27, v28, v29, v30, v31, v32)), \
210 ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
211 v09, v10, v11, v12, v13, v14, v15, v16), \
212 ENUM__JOIN_STR_16(v17, v18, v19, v20, v21, v22, v23, v24, \
213 v25, v26, v27, v28, v29, v30, v31, v32)))