The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
types.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Boxed value structures and functions to manipulate them
18 *
19 * @file src/lib/util/types.c
20 *
21 * @copyright 2021 The FreeRADIUS server project
22 */
23RCSID("$Id: 55ed550bb7ce86826da5f15cf6353ac8d9f65067 $")
24
25#include <freeradius-devel/util/strerror.h>
26#include <freeradius-devel/util/types.h>
27#include <freeradius-devel/util/value.h>
28
29/** Map data types to names representing those types
30 */
32 { L("null"), FR_TYPE_NULL },
33 { L("string"), FR_TYPE_STRING },
34 { L("octets"), FR_TYPE_OCTETS },
35
36 { L("ipaddr"), FR_TYPE_IPV4_ADDR },
37 { L("ipv4addr"), FR_TYPE_IPV4_ADDR },
38 { L("ipv4prefix"), FR_TYPE_IPV4_PREFIX },
39 { L("ipv6addr"), FR_TYPE_IPV6_ADDR },
40 { L("ipv6prefix"), FR_TYPE_IPV6_PREFIX },
41 { L("ifid"), FR_TYPE_IFID },
42 { L("combo-ip"), FR_TYPE_COMBO_IP_ADDR },
43 { L("combo-prefix"), FR_TYPE_COMBO_IP_PREFIX },
44 { L("ether"), FR_TYPE_ETHERNET },
45
46 { L("bool"), FR_TYPE_BOOL },
47
48 { L("uint8"), FR_TYPE_UINT8 },
49 { L("uint16"), FR_TYPE_UINT16 },
50 { L("uint32"), FR_TYPE_UINT32 },
51 { L("uint64"), FR_TYPE_UINT64 },
52
53 { L("int8"), FR_TYPE_INT8 },
54 { L("int16"), FR_TYPE_INT16 },
55 { L("int32"), FR_TYPE_INT32 },
56 { L("int64"), FR_TYPE_INT64 },
57
58 { L("float32"), FR_TYPE_FLOAT32 },
59 { L("float64"), FR_TYPE_FLOAT64 },
60
61 { L("date"), FR_TYPE_DATE },
62 { L("time_delta"), FR_TYPE_TIME_DELTA },
63
64 { L("size"), FR_TYPE_SIZE },
65
66 { L("tlv"), FR_TYPE_TLV },
67 { L("struct"), FR_TYPE_STRUCT },
68
69 { L("vsa"), FR_TYPE_VSA },
70 { L("vendor"), FR_TYPE_VENDOR },
71 { L("group"), FR_TYPE_GROUP },
72
73 { L("attribute"), FR_TYPE_ATTR },
74
75 /*
76 * Alternative names
77 */
78 { L("cidr"), FR_TYPE_IPV4_PREFIX },
79 { L("byte"), FR_TYPE_UINT8 },
80 { L("short"), FR_TYPE_UINT16 },
81 { L("integer"), FR_TYPE_UINT32 },
82 { L("integer64"), FR_TYPE_UINT64 },
83 { L("decimal"), FR_TYPE_FLOAT64 },
84 { L("signed"), FR_TYPE_INT32 }
85};
87
88/** Table of all the direct mappings between types and C types
89 *
90 * Useful for setting talloc types correctly.
91 */
92static char const *fr_type_to_c_type[] = {
93 [FR_TYPE_STRING] = "char *",
94 [FR_TYPE_OCTETS] = "uint8_t *",
95
96 [FR_TYPE_IPV4_ADDR] = "fr_ipaddr_t",
97 [FR_TYPE_IPV4_PREFIX] = "fr_ipaddr_t",
98 [FR_TYPE_IPV6_ADDR] = "fr_ipaddr_t",
99 [FR_TYPE_IPV6_PREFIX] = "fr_ipaddr_t",
100 [FR_TYPE_COMBO_IP_ADDR] = "fr_ipaddr_t",
101 [FR_TYPE_COMBO_IP_PREFIX] = "fr_ipaddr_t",
102 [FR_TYPE_IFID] = "fr_ifid_t",
103 [FR_TYPE_ETHERNET] = "fr_ethernet_t",
104
105 [FR_TYPE_BOOL] = "bool",
106 [FR_TYPE_UINT8] = "uint8_t",
107 [FR_TYPE_UINT16] = "uint16_t",
108 [FR_TYPE_UINT32] = "uint32_t",
109 [FR_TYPE_UINT64] = "uint64_t",
110
111 [FR_TYPE_INT8] = "int8_t",
112 [FR_TYPE_INT16] = "int16_t",
113 [FR_TYPE_INT32] = "int32_t",
114 [FR_TYPE_INT64] = "int64_t",
115
116 [FR_TYPE_FLOAT32] = "float",
117 [FR_TYPE_FLOAT64] = "double",
118
119 [FR_TYPE_DATE] = "fr_unix_time_t",
120
121 [FR_TYPE_TIME_DELTA] = "fr_time_delta_t",
122 [FR_TYPE_SIZE] = "size_t",
123 [FR_TYPE_VALUE_BOX] = "fr_value_box_t",
124 [FR_TYPE_ATTR] = "fr_dict_attr_t *",
125 [FR_TYPE_VOID] = "void *",
126
127 [FR_TYPE_VALUE_BOX_CURSOR] = "fr_dcursor_t *",
128 [FR_TYPE_PAIR_CURSOR] = "fr_dcursor_t *",
129
130 [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
131};
132
133/** Table of all the direct mappings between types and C type sizes
134 *
135 */
136static size_t const fr_type_to_c_size[] = {
137 [FR_TYPE_STRING] = sizeof(char *),
138 [FR_TYPE_OCTETS] = sizeof(uint8_t *),
139
140 [FR_TYPE_IPV4_ADDR] = sizeof(fr_ipaddr_t),
142 [FR_TYPE_IPV6_ADDR] = sizeof(fr_ipaddr_t),
146 [FR_TYPE_IFID] = sizeof(fr_ifid_t),
148
149 [FR_TYPE_BOOL] = sizeof(bool),
150 [FR_TYPE_UINT8] = sizeof(uint8_t),
151 [FR_TYPE_UINT16] = sizeof(uint16_t),
152 [FR_TYPE_UINT32] = sizeof(uint32_t),
153 [FR_TYPE_UINT64] = sizeof(uint64_t),
154
155 [FR_TYPE_INT8] = sizeof(int8_t),
156 [FR_TYPE_INT16] = sizeof(int16_t),
157 [FR_TYPE_INT32] = sizeof(int32_t),
158 [FR_TYPE_INT64] = sizeof(int64_t),
159
160 [FR_TYPE_FLOAT32] = sizeof(float),
161 [FR_TYPE_FLOAT64] = sizeof(double),
162
163 [FR_TYPE_DATE] = sizeof(fr_unix_time_t),
164
166 [FR_TYPE_SIZE] = sizeof(size_t),
168 [FR_TYPE_ATTR] = sizeof(fr_dict_attr_t *),
169 [FR_TYPE_VOID] = sizeof(void *),
170
171 [FR_TYPE_VALUE_BOX_CURSOR] = sizeof(void *),
172 [FR_TYPE_PAIR_CURSOR] = sizeof(void *),
173
174 [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
175};
176
177#define ARRAY_BEG(_type) { [_type] = true,
178#define ARRAY_MID(_type) [_type] = true,
179#define ARRAY_END(_type) [_type] = true }
180
185
187
191
196
197#define O(_x) [FR_TYPE_ ## _x] = true
198
199/*
200 * Can we promote [src][dst] -> dst
201 * dst is not octets / string
202 * src and dst are both FR_TYPE_VALUE
203 */
206 O(IPV4_PREFIX),
207 O(IPV6_ADDR),
208 O(IPV6_PREFIX),
209 O(COMBO_IP_ADDR),
210 O(COMBO_IP_PREFIX),
211 O(UINT32), /* ipv4 addresses are uint32 */
212 },
214 O(IPV4_ADDR), /* if the prefix is /32 */
215 O(IPV6_ADDR),
216 O(IPV6_PREFIX),
217 O(COMBO_IP_ADDR),
218 O(COMBO_IP_PREFIX)
219 },
221 O(IPV6_PREFIX),
222 O(COMBO_IP_ADDR),
223 O(COMBO_IP_PREFIX)
224 },
226 O(IPV6_ADDR), /* if the prefix is /128 */
227 O(COMBO_IP_ADDR),
228 O(COMBO_IP_PREFIX)
229 },
231 O(IPV4_ADDR),
232 O(IPV4_PREFIX),
233 O(IPV6_ADDR),
234 O(IPV6_PREFIX),
235 O(COMBO_IP_PREFIX)
236 },
238 O(IPV4_ADDR),
239 O(IPV4_PREFIX),
240 O(IPV6_ADDR),
241 O(IPV6_PREFIX),
242 O(COMBO_IP_ADDR) /* if the prefix is /128 or /32 */
243 },
244
245 [FR_TYPE_ETHERNET] = {
246 O(UINT64),
247 },
248
249 [FR_TYPE_UINT64] = {
250 O(ETHERNET),
251 },
252
253 [FR_TYPE_DATE] = { /* in 2021, dates always have values 2^31 or more */
254 O(UINT32),
255 O(UINT64),
256 O(INT32),
257 O(INT64),
258 O(SIZE),
259 O(FLOAT32),
260 O(FLOAT64),
261 O(TIME_DELTA),
262 },
263
265 O(DATE),
266 },
267
268 [FR_TYPE_UINT32] = {
269 O(IPV4_ADDR),
270 },
271
272};
273
274/*
275 * This is different from FR_TYPE_NUMERIC, largely in that it
276 * doesn't include FR_TYPE_DATE. Because we know that dates
277 * always have values 2^31 or greater, so casts exclude some of
278 * the smaller integer types.
279 */
280static const bool type_is_number[FR_TYPE_MAX] = {
281 O(BOOL), O(SIZE), O(FLOAT32), O(FLOAT64),
282 O(UINT8), O(UINT16), O(UINT32), O(UINT64),
283 O(INT8), O(INT16), O(INT32), O(INT64),
284 O(TIME_DELTA),
285};
286
287/** Return if we're allowed to cast the types.
288 *
289 * @param dst the destination type we wish to cast to
290 * @param src the source type we wish to cast to
291 *
292 */
294{
295 /*
296 * Invalid casts.
297 */
298 switch (dst) {
299 case FR_TYPE_NON_LEAF:
300 return false;
301
302 default:
303 break;
304 }
305
306 switch (src) {
307 case FR_TYPE_NON_LEAF:
308 return false;
309
310 default:
311 break;
312 }
313
314 if (src == dst) return true;
315
316 /*
317 * Anything can be converted to octets or strings.
318 */
319 if (dst == FR_TYPE_OCTETS) return true;
320 if (dst == FR_TYPE_STRING) return true;
321
322 /*
323 * Strings and octets can be converted to anything. We
324 * do run-time checks on the values to see if they fit.
325 */
326 if (src == FR_TYPE_OCTETS) return true;
327 if (src == FR_TYPE_STRING) return true;
328
329 /*
330 * Any integer-style thing can be cast to any other
331 * integer-style thing. Mostly. We do run-time checks
332 * on values to see if they fit.
333 */
334 if (type_is_number[src] && type_is_number[dst]) {
335 return true;
336 }
337
338 /*
339 * That takes care of the simple cases. :( Now to the
340 * complex ones. Instead of masses of if / then / else,
341 * we just use a lookup table.
342 */
343 return type_cast_table[src][dst];
344}
345
346#undef O
347#define O(_x) [FR_TYPE_ ## _x] = FR_TYPE_ ## _x
348
349/** promote (a,b) -> a or b
350 * a/b are not octets / string
351 * a and b are both FR_TYPE_VALUE
352 *
353 * Note that this table can return a type which is _not_ a or b.
354 *
355 * Many lookups of table[a][b] will return b. Some will return a.
356 * Others will return a type which is compatible with both a and b.
357 */
360 O(IPV4_PREFIX),
361 O(IPV6_ADDR),
362 O(IPV6_PREFIX),
364 },
365
368 O(IPV4_PREFIX),
370 O(IPV6_PREFIX),
371 },
372
374 O(IPV6_PREFIX),
375 },
376
379 },
380
381 /* unsigned integers */
382
383 [FR_TYPE_BOOL] = {
384 O(UINT8),
385 O(UINT16),
386 O(UINT32),
387 O(UINT64),
388 O(INT8),
389 O(INT16),
390 O(INT32),
391 O(INT64),
392 O(SIZE),
393 O(FLOAT32),
394 O(FLOAT64),
395 O(TIME_DELTA),
396 },
397
398 [FR_TYPE_UINT8] = {
400 O(UINT16),
401 O(UINT32),
402 O(UINT64),
404 O(INT16),
405 O(INT32),
406 O(INT64),
407 O(SIZE),
408 O(FLOAT32),
409 O(FLOAT64),
410 O(TIME_DELTA),
411 },
412
413 [FR_TYPE_UINT16] = {
416 O(UINT32),
417 O(UINT64),
419 O(INT32),
420 O(INT64),
421 O(SIZE),
422 O(FLOAT32),
423 O(FLOAT64),
424 O(TIME_DELTA),
425 },
426
427 [FR_TYPE_UINT32] = {
429 O(IPV4_ADDR),
432 O(UINT64),
434 O(INT64),
435 O(SIZE),
436 O(FLOAT32),
437 O(FLOAT64),
438 O(TIME_DELTA),
439 O(DATE),
440 },
441
442 [FR_TYPE_UINT64] = {
447
452 O(SIZE),
454 O(FLOAT64),
455 O(TIME_DELTA),
456 O(DATE),
457 },
458
459 /* signed integers */
460 [FR_TYPE_INT8] = {
462 O(UINT8),
463 O(UINT16),
464 O(UINT32),
465 O(UINT64),
466 O(INT16),
467 O(INT32),
468 O(INT64),
469 O(SIZE),
470 O(FLOAT32),
471 O(FLOAT64),
472 O(TIME_DELTA),
473 },
474
475 [FR_TYPE_INT16] = {
478 O(UINT16),
479 O(UINT32),
480 O(UINT64),
482 O(INT32),
483 O(INT64),
484 O(SIZE),
485 O(FLOAT32),
486 O(FLOAT64),
487 O(TIME_DELTA),
488 },
489
490 [FR_TYPE_INT32] = {
494 O(UINT32),
495 O(UINT64),
498 O(INT64),
499 O(SIZE),
500 O(FLOAT32),
501 O(FLOAT64),
502 O(TIME_DELTA),
503 O(DATE),
504 },
505
506 [FR_TYPE_INT64] = {
510 O(UINT64),
511 O(SIZE),
516 O(FLOAT64),
517 O(TIME_DELTA),
518 O(DATE),
519 },
520
528
533
537 },
538
539 [FR_TYPE_DATE] = {
543
546
549 O(TIME_DELTA),
550 },
551
552 [FR_TYPE_SIZE] = {
563 O(FLOAT64),
565 O(DATE),
566 }
567};
568
569/** Return the promoted type
570 *
571 * We presume that the two types are compatible, as checked by
572 * calling fr_type_cast(). The main difference here is that the two
573 * types don't have any src / dst relationship. Instead, we just
574 * pick one which best suits any value-box comparisons
575 *
576 * Note that this function can return a type which is _not_ a or b.
577 *
578 * @param a type one
579 * @param b type two
580 * @return the promoted type
581 */
583{
584 if (!fr_type_is_leaf(a) || !fr_type_is_leaf(b)) return FR_TYPE_NULL;
585
586 if (a == b) return a;
587
588 /*
589 * string / octets and "type", the un-typed data gets cast to
590 * "type".
591 *
592 * We prefer to cast raw data to real types. We also
593 * prefer to _parse_ strings, and do the type checking on
594 * the real types. That way we have things like: "000" == 0
595 */
596 if (a == FR_TYPE_OCTETS) return b;
597 if (b == FR_TYPE_OCTETS) return a;
598
599 /*
600 * Check for string after octets, because we want to cast
601 * octets to string, and not vice versa.
602 */
603 if (a == FR_TYPE_STRING) return b;
604 if (b == FR_TYPE_STRING) return a;
605
606 /*
607 * Otherwise bad things happen. :(
608 */
609 if (unlikely(type_promote_table[a][b] != type_promote_table[b][a])) {
610 fr_strerror_printf("Inverse type mapping inconsistent for a = %s, b = %s",
612 fr_type_to_str(b));
613
614 return FR_TYPE_NULL;
615 }
616
618 fr_strerror_printf("No type promotions for a = %s, b = %s",
620 fr_type_to_str(b));
621 return FR_TYPE_NULL;
622 }
623
624 /*
625 * That takes care of the simple cases. :( Now to the
626 * complex ones. Instead of masses of if / then / else,
627 * we just use a lookup table.
628 */
629 return type_promote_table[a][b];
630}
631
632/** Allocate an array of a given type
633 *
634 * @param[in] ctx to allocate array in.
635 * @param[in] type array to allocate.
636 * @param[in] count The number of elements to allocate.
637 * @return
638 * - NULL on error.
639 * - A new talloc array.
640 */
641void **fr_type_array_alloc(TALLOC_CTX *ctx, fr_type_t type, size_t count)
642{
643 char const *c_type;
644
645 c_type = fr_type_to_c_type[type];
646 if (c_type == NULL) {
647 fr_strerror_printf("Type %s does not have a C type equivalent", fr_type_to_str(type));
648 return NULL;
649 }
650
651 return _talloc_zero_array(ctx, fr_type_to_c_size[type], count, c_type);
652 }
#define RCSID(id)
Definition build.h:485
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define unlikely(_x)
Definition build.h:383
#define NUM_ELEMENTS(_t)
Definition build.h:339
Struct to represent an ethernet address.
Definition inet.h:45
Struct to represent an interface id.
Definition inet.h:54
IPv4/6 prefix.
unsigned short uint16_t
fr_type_t
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_FLOAT32
Single precision floating point.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_INT8
8 Bit signed integer.
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_MAX
Number of defined data types.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_INT16
16 Bit signed integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_VALUE_BOX
A boxed value.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_VENDOR
Attribute that represents a vendor in the attribute tree.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_VOID
User data.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_IFID
Interface ID.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
@ FR_TYPE_FLOAT64
Double precision floating point.
unsigned int uint32_t
unsigned char bool
unsigned char uint8_t
return count
Definition module.c:155
fr_aka_sim_id_type_t type
An element in an arbitrarily ordered array of name to num mappings.
Definition table.h:57
struct fr_time_delta_s fr_time_delta_t
A time delta, a difference in time measured in nanoseconds.
"Unix" time.
Definition time.h:95
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define O(_x)
Definition types.c:197
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
Definition types.c:31
static char const * fr_type_to_c_type[]
Table of all the direct mappings between types and C types.
Definition types.c:92
bool const fr_type_structural_except_vsa[FR_TYPE_MAX+1]
Definition types.c:192
#define ARRAY_MID(_type)
Definition types.c:178
bool const fr_type_non_leaf[FR_TYPE_MAX+1]
Definition types.c:195
bool fr_type_cast(fr_type_t dst, fr_type_t src)
Return if we're allowed to cast the types.
Definition types.c:293
bool const fr_type_signed[FR_TYPE_MAX+1]
Definition types.c:184
bool const fr_type_integer[FR_TYPE_MAX+1]
Definition types.c:182
bool const fr_type_variable_size[FR_TYPE_MAX+1]
Definition types.c:189
bool const fr_type_numeric[FR_TYPE_MAX+1]
Definition types.c:183
static fr_type_t type_promote_table[FR_TYPE_MAX][FR_TYPE_MAX]
promote (a,b) -> a or b a/b are not octets / string a and b are both FR_TYPE_VALUE
Definition types.c:358
bool const fr_type_ip[FR_TYPE_MAX+1]
Definition types.c:186
static const bool type_is_number[FR_TYPE_MAX]
Definition types.c:280
bool const fr_type_fixed_size[FR_TYPE_MAX+1]
Definition types.c:188
#define ARRAY_END(_type)
Definition types.c:179
bool const fr_type_integer_except_bool[FR_TYPE_MAX+1]
Definition types.c:181
bool const fr_type_quoted[FR_TYPE_MAX+1]
Definition types.c:190
void ** fr_type_array_alloc(TALLOC_CTX *ctx, fr_type_t type, size_t count)
Allocate an array of a given type.
Definition types.c:641
bool const fr_type_leaf[FR_TYPE_MAX+1]
Definition types.c:194
size_t fr_type_table_len
Definition types.c:86
static size_t const fr_type_to_c_size[]
Table of all the direct mappings between types and C type sizes.
Definition types.c:136
fr_type_t fr_type_promote(fr_type_t a, fr_type_t b)
Return the promoted type.
Definition types.c:582
static const bool type_cast_table[FR_TYPE_MAX][FR_TYPE_MAX]
Definition types.c:204
#define ARRAY_BEG(_type)
Definition types.c:177
bool const fr_type_structural[FR_TYPE_MAX+1]
Definition types.c:193
#define FR_TYPE_NON_LEAF_DEF(_beg, _mid, _end)
Types which do not represent leaf values.
Definition types.h:286
#define FR_TYPE_IP_DEF(_beg, _mid, _end)
Types which can fit in an fr_ipaddr_t.
Definition types.h:167
#define FR_TYPE_FIXED_SIZE_DEF(_beg, _mid, _end)
Match all fixed length types.
Definition types.h:181
@ FR_TYPE_VALUE_BOX_CURSOR
cursor over a fr_value_box_t
Definition types.h:88
@ FR_TYPE_ATTR
A contains an attribute reference.
Definition types.h:83
@ FR_TYPE_PAIR_CURSOR
cursor over a fr_pair_t
Definition types.h:90
#define FR_TYPE_STRUCTURAL_EXCEPT_VSA_DEF(_beg, _mid, _end)
Stupid hack for things which produce special error messages for VSAs.
Definition types.h:219
#define FR_TYPE_NON_LEAF
Definition types.h:316
#define FR_TYPE_SIGNED_DEF(_beg, _mid, _end)
Signed values.
Definition types.h:136
#define FR_TYPE_VARIABLE_SIZE_DEF(_beg, _mid, _end)
Match all variable length types.
Definition types.h:199
#define FR_TYPE_NUMERIC_DEF(_beg, _mid, _end)
Naturally numeric types.
Definition types.h:153
#define FR_TYPE_INTEGER_EXCEPT_BOOL_DEF(_beg, _mid, _end)
All integer types except bool.
Definition types.h:106
#define FR_TYPE_LEAF_DEF(_beg, _mid, _end)
Types which represent concrete values.
Definition types.h:257
#define fr_type_is_leaf(_x)
Definition types.h:391
#define FR_TYPE_STRUCTURAL_DEF(_beg, _mid, _end)
Match all non value types in case statements.
Definition types.h:246
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:452
#define FR_TYPE_QUOTED_DEF(_beg, _mid, _end)
Types which should be wrapped in double quotes when printed.
Definition types.h:208
#define FR_TYPE_INTEGER_DEF(_beg, _mid, _end)
Signed or unsigned integers.
Definition types.h:126