P99
p99_enum.h
Go to the documentation of this file.
1 /* This may look like nonsense, but it really is -*- mode: C; coding: utf-8 -*- */
2 /* */
3 /* Except for parts copied from previous work and as explicitly stated below, */
4 /* the authors and copyright holders for this work are as follows: */
5 /* (C) copyright 2010-2013 Jens Gustedt, INRIA, France */
6 /* (C) copyright 2012 William Morris */
7 /* */
8 /* This file is free software; it is part of the P99 project. */
9 /* */
10 /* Licensed under the Apache License, Version 2.0 (the "License"); */
11 /* you may not use this file except in compliance with the License. */
12 /* You may obtain a copy of the License at */
13 /* */
14 /* http://www.apache.org/licenses/LICENSE-2.0 */
15 /* */
16 /* Unless required by applicable law or agreed to in writing, software */
17 /* distributed under the License is distributed on an "AS IS" BASIS, */
18 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
19 /* See the License for the specific language governing permissions and */
20 /* limitations under the License. */
21 /* */
22 #ifndef P99_ENUM_H_
23 # define P99_ENUM_H_
24 
25 #include "p99_for.h"
26 
33 #define P00_ENUM_CASE(X) case X: return P99_STRINGIFY(X)
34 
35 #define P00_ENUM_PARSE(C) \
36 if (!memcmp(P99_STRINGIFY(C), p00_s, p00_len)) { \
37  ++p00_c; \
38  p00_ret = C; \
39  }
40 
41 
42 
43 #ifdef P00_DOXYGEN
44 
48 #define P99_DECLARE_ENUM_GETNAME(T, ...) \
49  \
50 inline char const* P99_PASTE2(T, _getname)(T p00_x)
51 
55 #define P99_DECLARE_ENUM_PARSE(T, ...) \
56  \
57 inline T P99_PASTE2(T, _parse)(char const* p00_s)
58 #else
59 P00_DOCUMENT_TYPE_ARGUMENT(P99_DECLARE_ENUM_GETNAME, 0)
60 P00_DOCUMENT_DECLARATION_ARGUMENT(P99_DECLARE_ENUM_GETNAME, 1)
61 P00_DOCUMENT_DECLARATION_ARGUMENT(P99_DECLARE_ENUM_GETNAME, 2)
62 P00_DOCUMENT_DECLARATION_ARGUMENT(P99_DECLARE_ENUM_GETNAME, 3)
63 #define P99_DECLARE_ENUM_GETNAME(T, ...) \
64 P99_CONST_FUNCTION \
65 p99_inline \
66 char const* P99_PASTE2(T, _getname)(T p00_x) { \
67  switch ((uintmax_t)p00_x) { \
68  P99_SEP(P00_ENUM_CASE, __VA_ARGS__); \
69  default: return "((" #T ")unknown value)"; \
70  } \
71 } \
72 P99_MACRO_END(declare_enum_getname, T)
73 
74 P00_DOCUMENT_TYPE_ARGUMENT(P99_DECLARE_ENUM_PARSE, 0)
75 P00_DOCUMENT_DECLARATION_ARGUMENT(P99_DECLARE_ENUM_PARSE, 1)
76 P00_DOCUMENT_DECLARATION_ARGUMENT(P99_DECLARE_ENUM_PARSE, 2)
77 P00_DOCUMENT_DECLARATION_ARGUMENT(P99_DECLARE_ENUM_PARSE, 3)
78 #define P99_DECLARE_ENUM_PARSE(T, ...) \
79 P99_PURE_FUNCTION \
80 p99_inline \
81 T P99_PASTE2(T, _parse)(char const p00_s[]) { \
82  T p00_ret = P99_PASTE2(T, _amount); \
83  if (p00_s) { \
84  size_t p00_c = 0; \
85  size_t const p00_len = strlen(p00_s); \
86  P99_SEP(P00_ENUM_PARSE, __VA_ARGS__); \
87  if (p00_c > 1) p00_ret = P99_PASTE2(T, _amount); \
88  } \
89  return p00_ret; \
90 } \
91 P99_MACRO_END(declare_enum_parse, T)
92 #endif
93 
94 #ifdef DOXYGEN
95 
135 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_ENUM, 0)
136 P00_DOCUMENT_DECLARATION_ARGUMENT(P99_DECLARE_ENUM, 1)
137 P00_DOCUMENT_DECLARATION_ARGUMENT(P99_DECLARE_ENUM, 2)
138 P00_DOCUMENT_DECLARATION_ARGUMENT(P99_DECLARE_ENUM, 3)
139 #define P99_DECLARE_ENUM(T, ...) \
140  \
141 enum T { __VA_ARGS__ , \
142  \
143  P99_PASTE2(T, _amount), \
144  \
145  P99_PASTE2(T, _max) = ((size_t)(P99_PASTE2(T, _amount)) - 1u), \
146  \
147  P99_PASTE2(T, _min) = 0 \
148 }; \
149  \
150  \
151 typedef enum T T; \
152  P99_DECLARE_ENUM_GETNAME(T, __VA_ARGS__); \
153 P99_DECLARE_ENUM_PARSE(T, __VA_ARGS__)
154 #else
155 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_ENUM, 0)
156 P00_DOCUMENT_DECLARATION_ARGUMENT(P99_DECLARE_ENUM, 1)
157 P00_DOCUMENT_DECLARATION_ARGUMENT(P99_DECLARE_ENUM, 2)
158 P00_DOCUMENT_DECLARATION_ARGUMENT(P99_DECLARE_ENUM, 3)
159 #define P99_DECLARE_ENUM(T, ...) \
160 typedef enum T { __VA_ARGS__ , \
161  \
162  P99_PASTE2(T, _amount), \
163  \
164  P99_PASTE2(T, _max) = ((size_t)(P99_PASTE2(T, _amount)) - 1u), \
165  \
166  P99_PASTE2(T, _min) = 0 \
167 } T; \
168 P99_DECLARE_ENUM_GETNAME(T, __VA_ARGS__); \
169 P99_DECLARE_ENUM_PARSE(T, __VA_ARGS__)
170 #endif
171 
177 P00_DOCUMENT_TYPE_ARGUMENT(P99_DEFINE_ENUM, 0)
178 #define P99_DEFINE_ENUM(T) \
179 P99_INSTANTIATE(char const*, P99_PASTE2(T, _getname), T); \
180 P99_INSTANTIATE(T, P99_PASTE2(T, _parse), char const*)
181 
184 char const* bool_getname(bool p00_x) {
185  switch ((uintmax_t)p00_x) {
186  case 0: return "false";
187  case 1: return "true";
188  default: return "((bool)unknown value)";
189  }
190 }
191 
192 
215 #define P99_UNUSED(...) P99_SEP(P00_UNUSED, __VA_ARGS__)
216 
217 #define P00_CONSTANT_STATIC_3(T, NAME, ...) static T const NAME = __VA_ARGS__; P99_UNUSED(NAME)
218 #define P00_CONSTANT_ENUM_1(NAME) enum { NAME }
219 #define P00_CONSTANT_ENUM_2(NAME, ...) enum { NAME = (__VA_ARGS__) }
220 
221 #define P00_CONSTANT_2(T, NAME) \
222 P99_IF_INT(T) \
223 (P00_CONSTANT_ENUM_1(NAME)) \
224 (P00_CONSTANT_STATIC_3(T, NAME, P99_INIT))
225 
226 #define P00_CONSTANT_3(T, NAME, ...) \
227 P99_IF_INT(T) \
228  (P00_CONSTANT_ENUM_2(NAME, __VA_ARGS__)) \
229  (P00_CONSTANT_STATIC_3(T, NAME, __VA_ARGS__))
230 
231 #ifdef P00_DOXYGEN
232 
257 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_CONSTANT, 1)
258 #define P99_CONSTANT(T, NAME, INIT) register T const NAME = INIT
259 #else
260 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_CONSTANT, 1)
261 #define P99_CONSTANT(...) \
262 P99_IF_LT(P99_NARG(__VA_ARGS__), 3) \
263 (P00_CONSTANT_2(__VA_ARGS__)) \
264 (P00_CONSTANT_3(__VA_ARGS__))
265 #endif
266 
280 typedef enum p99_endianness {
281  p99_big_endian = 0x01020304u,
282  p99_little_endian = 0x04030201u,
283  p99_pdp_endian = 0x02010403u
285 
291 );
292 
297 #define P99_ENDIANNESS ((p99_endianness)P99_HTON(4, UINT32_C(0x01020304)))
298 
303 #endif /* !P99_ENUM_H_ */
p99_pdp_endian
@ p99_pdp_endian
Definition: p99_enum.h:283
p99_for.h
A preprocessor for loop implementation and some derived list handling macros.
bool_getname
char const * bool_getname(bool p00_x)
Definition: p99_enum.h:184
uintmax_t
uintmax_t
Definition: p99_str.h:117
P99_CONSTANT
#define P99_CONSTANT(T, NAME, INIT)
define a compile time constant NAME of type T with value INIT
Definition: p99_enum.h:258
P99_DEFINE_ENUM
#define P99_DEFINE_ENUM(T)
Define the necessary symbols for a simple enumeration type.
Definition: p99_enum.h:178
P99_DECLARE_ENUM_GETNAME
#define P99_DECLARE_ENUM_GETNAME(T,...)
Declare a simple inline function to return strings containing the names of enumeration constants.
Definition: p99_enum.h:48
p99_inline
#define p99_inline
Try to force a function always to be inlined.
Definition: p99_compiler.h:496
P99_DECLARE_ENUM
#define P99_DECLARE_ENUM(T,...)
Declare a simple enumeration type.
Definition: p99_enum.h:139
p99_endianness
p99_endianness
Classify platforms according to their endianness.
Definition: p99_enum.h:280
P99_CONST_FUNCTION
#define P99_CONST_FUNCTION
On architectures that support this, assert that a function is "const", i.e only depends on parameters...
Definition: p99_compiler.h:622
p99_big_endian
@ p99_big_endian
Definition: p99_enum.h:281
P99_DECLARE_ENUM_PARSE
#define P99_DECLARE_ENUM_PARSE(T,...)
Declare a simple inline function to return the longest enumeration constants of type T found in a str...
Definition: p99_enum.h:55
p99_little_endian
@ p99_little_endian
Definition: p99_enum.h:282