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: a8f8fd4113d6f4afb6ad2fa0fa0e414603f10024 $")
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 /*
74 * Alternative names
75 */
76 { L("cidr"), FR_TYPE_IPV4_PREFIX },
77 { L("byte"), FR_TYPE_UINT8 },
78 { L("short"), FR_TYPE_UINT16 },
79 { L("integer"), FR_TYPE_UINT32 },
80 { L("integer64"), FR_TYPE_UINT64 },
81 { L("decimal"), FR_TYPE_FLOAT64 },
82 { L("signed"), FR_TYPE_INT32 }
83};
85
86/** Table of all the direct mappings between types and C types
87 *
88 * Useful for setting talloc types correctly.
89 */
90static char const *fr_type_to_c_type[] = {
91 [FR_TYPE_STRING] = "char *",
92 [FR_TYPE_OCTETS] = "uint8_t *",
93
94 [FR_TYPE_IPV4_ADDR] = "fr_ipaddr_t",
95 [FR_TYPE_IPV4_PREFIX] = "fr_ipaddr_t",
96 [FR_TYPE_IPV6_ADDR] = "fr_ipaddr_t",
97 [FR_TYPE_IPV6_PREFIX] = "fr_ipaddr_t",
98 [FR_TYPE_COMBO_IP_ADDR] = "fr_ipaddr_t",
99 [FR_TYPE_COMBO_IP_PREFIX] = "fr_ipaddr_t",
100 [FR_TYPE_IFID] = "fr_ifid_t",
101 [FR_TYPE_ETHERNET] = "fr_ethernet_t",
102
103 [FR_TYPE_BOOL] = "bool",
104 [FR_TYPE_UINT8] = "uint8_t",
105 [FR_TYPE_UINT16] = "uint16_t",
106 [FR_TYPE_UINT32] = "uint32_t",
107 [FR_TYPE_UINT64] = "uint64_t",
108
109 [FR_TYPE_INT8] = "int8_t",
110 [FR_TYPE_INT16] = "int16_t",
111 [FR_TYPE_INT32] = "int32_t",
112 [FR_TYPE_INT64] = "int64_t",
113
114 [FR_TYPE_FLOAT32] = "float",
115 [FR_TYPE_FLOAT64] = "double",
116
117 [FR_TYPE_DATE] = "fr_unix_time_t",
118
119 [FR_TYPE_TIME_DELTA] = "fr_time_delta_t",
120 [FR_TYPE_SIZE] = "size_t",
121 [FR_TYPE_VALUE_BOX] = "fr_value_box_t",
122 [FR_TYPE_VOID] = "void *",
123
124 [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
125};
126
127/** Table of all the direct mappings between types and C type sizes
128 *
129 */
130static size_t const fr_type_to_c_size[] = {
131 [FR_TYPE_STRING] = sizeof(char *),
132 [FR_TYPE_OCTETS] = sizeof(uint8_t *),
133
134 [FR_TYPE_IPV4_ADDR] = sizeof(fr_ipaddr_t),
136 [FR_TYPE_IPV6_ADDR] = sizeof(fr_ipaddr_t),
140 [FR_TYPE_IFID] = sizeof(fr_ifid_t),
142
143 [FR_TYPE_BOOL] = sizeof(bool),
144 [FR_TYPE_UINT8] = sizeof(uint8_t),
145 [FR_TYPE_UINT16] = sizeof(uint16_t),
146 [FR_TYPE_UINT32] = sizeof(uint32_t),
147 [FR_TYPE_UINT64] = sizeof(uint64_t),
148
149 [FR_TYPE_INT8] = sizeof(int8_t),
150 [FR_TYPE_INT16] = sizeof(int16_t),
151 [FR_TYPE_INT32] = sizeof(int32_t),
152 [FR_TYPE_INT64] = sizeof(int64_t),
153
154 [FR_TYPE_FLOAT32] = sizeof(float),
155 [FR_TYPE_FLOAT64] = sizeof(double),
156
157 [FR_TYPE_DATE] = sizeof(fr_unix_time_t),
158
160 [FR_TYPE_SIZE] = sizeof(size_t),
162 [FR_TYPE_VOID] = sizeof(void *),
163
164 [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
165};
166
167#define ARRAY_BEG(_type) { [_type] = true,
168#define ARRAY_MID(_type) [_type] = true,
169#define ARRAY_END(_type) [_type] = true }
170
175
177
181
186
187#define O(_x) [FR_TYPE_ ## _x] = true
188
189/*
190 * Can we promote [src][dst] -> dst
191 * dst is not octets / string
192 * src and dst are both FR_TYPE_VALUE
193 */
196 O(IPV4_PREFIX),
197 O(IPV6_ADDR),
198 O(IPV6_PREFIX),
199 O(COMBO_IP_ADDR),
200 O(COMBO_IP_PREFIX),
201 O(UINT32), /* ipv4 addresses are uint32 */
202 },
204 O(IPV4_ADDR), /* if the prefix is /32 */
205 O(IPV6_ADDR),
206 O(IPV6_PREFIX),
207 O(COMBO_IP_ADDR),
208 O(COMBO_IP_PREFIX)
209 },
211 O(IPV6_PREFIX),
212 O(COMBO_IP_ADDR),
213 O(COMBO_IP_PREFIX)
214 },
216 O(IPV6_ADDR), /* if the prefix is /128 */
217 O(COMBO_IP_ADDR),
218 O(COMBO_IP_PREFIX)
219 },
221 O(IPV4_ADDR),
222 O(IPV4_PREFIX),
223 O(IPV6_ADDR),
224 O(IPV6_PREFIX),
225 O(COMBO_IP_PREFIX)
226 },
228 O(IPV4_ADDR),
229 O(IPV4_PREFIX),
230 O(IPV6_ADDR),
231 O(IPV6_PREFIX),
232 O(COMBO_IP_ADDR) /* if the prefix is /128 or /32 */
233 },
234
235 [FR_TYPE_ETHERNET] = {
236 O(UINT64),
237 },
238
239 [FR_TYPE_UINT64] = {
240 O(ETHERNET),
241 },
242
243 [FR_TYPE_DATE] = { /* in 2021, dates always have values 2^31 or more */
244 O(UINT32),
245 O(UINT64),
246 O(INT32),
247 O(INT64),
248 O(SIZE),
249 O(FLOAT32),
250 O(FLOAT64),
251 O(TIME_DELTA),
252 },
253
255 O(DATE),
256 },
257
258 [FR_TYPE_UINT32] = {
259 O(IPV4_ADDR),
260 },
261
262};
263
264/*
265 * This is different from FR_TYPE_NUMERIC, largely in that it
266 * doesn't include FR_TYPE_DATE. Because we know that dates
267 * always have values 2^31 or greater, so casts exclude some of
268 * the smaller integer types.
269 */
270static const bool type_is_number[FR_TYPE_MAX] = {
271 O(BOOL), O(SIZE), O(FLOAT32), O(FLOAT64),
272 O(UINT8), O(UINT16), O(UINT32), O(UINT64),
273 O(INT8), O(INT16), O(INT32), O(INT64),
274 O(TIME_DELTA),
275};
276
277/** Return if we're allowed to cast the types.
278 *
279 * @param dst the destination type we wish to cast to
280 * @param src the source type we wish to cast to
281 *
282 */
284{
285 /*
286 * Invalid casts.
287 */
288 switch (dst) {
289 case FR_TYPE_NON_LEAF:
290 return false;
291
292 default:
293 break;
294 }
295
296 switch (src) {
297 case FR_TYPE_NON_LEAF:
298 return false;
299
300 default:
301 break;
302 }
303
304 if (src == dst) return true;
305
306 /*
307 * Anything can be converted to octets or strings.
308 */
309 if (dst == FR_TYPE_OCTETS) return true;
310 if (dst == FR_TYPE_STRING) return true;
311
312 /*
313 * Strings and octets can be converted to anything. We
314 * do run-time checks on the values to see if they fit.
315 */
316 if (src == FR_TYPE_OCTETS) return true;
317 if (src == FR_TYPE_STRING) return true;
318
319 /*
320 * Any integer-style thing can be cast to any other
321 * integer-style thing. Mostly. We do run-time checks
322 * on values to see if they fit.
323 */
324 if (type_is_number[src] && type_is_number[dst]) {
325 return true;
326 }
327
328 /*
329 * That takes care of the simple cases. :( Now to the
330 * complex ones. Instead of masses of if / then / else,
331 * we just use a lookup table.
332 */
333 return type_cast_table[src][dst];
334}
335
336#undef O
337#define O(_x) [FR_TYPE_ ## _x] = FR_TYPE_ ## _x
338
339/** promote (a,b) -> a or b
340 * a/b are not octets / string
341 * a and b are both FR_TYPE_VALUE
342 *
343 * Note that this table can return a type which is _not_ a or b.
344 *
345 * Many lookups of table[a][b] will return b. Some will return a.
346 * Others will return a type which is compatible with both a and b.
347 */
350 O(IPV4_PREFIX),
351 O(IPV6_ADDR),
352 O(IPV6_PREFIX),
354 },
355
358 O(IPV4_PREFIX),
360 O(IPV6_PREFIX),
361 },
362
364 O(IPV6_PREFIX),
365 },
366
369 },
370
371 /* unsigned integers */
372
373 [FR_TYPE_BOOL] = {
374 O(UINT8),
375 O(UINT16),
376 O(UINT32),
377 O(UINT64),
378 O(INT8),
379 O(INT16),
380 O(INT32),
381 O(INT64),
382 O(SIZE),
383 O(FLOAT32),
384 O(FLOAT64),
385 O(TIME_DELTA),
386 },
387
388 [FR_TYPE_UINT8] = {
390 O(UINT16),
391 O(UINT32),
392 O(UINT64),
394 O(INT16),
395 O(INT32),
396 O(INT64),
397 O(SIZE),
398 O(FLOAT32),
399 O(FLOAT64),
400 O(TIME_DELTA),
401 },
402
403 [FR_TYPE_UINT16] = {
406 O(UINT32),
407 O(UINT64),
409 O(INT32),
410 O(INT64),
411 O(SIZE),
412 O(FLOAT32),
413 O(FLOAT64),
414 O(TIME_DELTA),
415 },
416
417 [FR_TYPE_UINT32] = {
419 O(IPV4_ADDR),
422 O(UINT64),
424 O(INT64),
425 O(SIZE),
426 O(FLOAT32),
427 O(FLOAT64),
428 O(TIME_DELTA),
429 O(DATE),
430 },
431
432 [FR_TYPE_UINT64] = {
437
442 O(SIZE),
444 O(FLOAT64),
445 O(TIME_DELTA),
446 O(DATE),
447 },
448
449 /* signed integers */
450 [FR_TYPE_INT8] = {
452 O(UINT8),
453 O(UINT16),
454 O(UINT32),
455 O(UINT64),
456 O(INT16),
457 O(INT32),
458 O(INT64),
459 O(SIZE),
460 O(FLOAT32),
461 O(FLOAT64),
462 O(TIME_DELTA),
463 },
464
465 [FR_TYPE_INT16] = {
468 O(UINT16),
469 O(UINT32),
470 O(UINT64),
472 O(INT32),
473 O(INT64),
474 O(SIZE),
475 O(FLOAT32),
476 O(FLOAT64),
477 O(TIME_DELTA),
478 },
479
480 [FR_TYPE_INT32] = {
484 O(UINT32),
485 O(UINT64),
488 O(INT64),
489 O(SIZE),
490 O(FLOAT32),
491 O(FLOAT64),
492 O(TIME_DELTA),
493 O(DATE),
494 },
495
496 [FR_TYPE_INT64] = {
500 O(UINT64),
501 O(SIZE),
506 O(FLOAT64),
507 O(TIME_DELTA),
508 O(DATE),
509 },
510
518
523
527 },
528
529 [FR_TYPE_DATE] = {
533
536
539 O(TIME_DELTA),
540 },
541
542 [FR_TYPE_SIZE] = {
553 O(FLOAT64),
555 O(DATE),
556 }
557};
558
559/** Return the promoted type
560 *
561 * We presume that the two types are compatible, as checked by
562 * calling fr_type_cast(). The main difference here is that the two
563 * types don't have any src / dst relationship. Instead, we just
564 * pick one which best suits any value-box comparisons
565 *
566 * Note that this function can return a type which is _not_ a or b.
567 *
568 * @param a type one
569 * @param b type two
570 * @return the promoted type
571 */
573{
574 if (!fr_type_is_leaf(a) || !fr_type_is_leaf(b)) return FR_TYPE_NULL;
575
576 if (a == b) return a;
577
578 /*
579 * string / octets and "type", the un-typed data gets cast to
580 * "type".
581 *
582 * We prefer to cast raw data to real types. We also
583 * prefer to _parse_ strings, and do the type checking on
584 * the real types. That way we have things like: "000" == 0
585 */
586 if (a == FR_TYPE_OCTETS) return b;
587 if (b == FR_TYPE_OCTETS) return a;
588
589 /*
590 * Check for string after octets, because we want to cast
591 * octets to string, and not vice versa.
592 */
593 if (a == FR_TYPE_STRING) return b;
594 if (b == FR_TYPE_STRING) return a;
595
596 /*
597 * Otherwise bad things happen. :(
598 */
599 if (unlikely(type_promote_table[a][b] != type_promote_table[b][a])) {
600 fr_strerror_printf("Inverse type mapping inconsistent for a = %s, b = %s",
602 fr_type_to_str(b));
603
604 return FR_TYPE_NULL;
605 }
606
608 fr_strerror_printf("No type promotions for a = %s, b = %s",
610 fr_type_to_str(b));
611 return FR_TYPE_NULL;
612 }
613
614 /*
615 * That takes care of the simple cases. :( Now to the
616 * complex ones. Instead of masses of if / then / else,
617 * we just use a lookup table.
618 */
619 return type_promote_table[a][b];
620}
621
622/** Allocate an array of a given type
623 *
624 * @param[in] ctx to allocate array in.
625 * @param[in] type array to allocate.
626 * @param[in] count The number of elements to allocate.
627 * @return
628 * - NULL on error.
629 * - A new talloc array.
630 */
631void **fr_type_array_alloc(TALLOC_CTX *ctx, fr_type_t type, size_t count)
632{
633 char const *c_type;
634
635 c_type = fr_type_to_c_type[type];
636 if (c_type == NULL) {
637 fr_strerror_printf("Type %s does not have a C type equivalent", fr_type_to_str(type));
638 return NULL;
639 }
640
641 return _talloc_zero_array(ctx, fr_type_to_c_size[type], count, c_type);
642 }
#define RCSID(id)
Definition build.h:483
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define unlikely(_x)
Definition build.h:381
#define NUM_ELEMENTS(_t)
Definition build.h:337
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:163
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:187
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:90
bool const fr_type_structural_except_vsa[FR_TYPE_MAX+1]
Definition types.c:182
#define ARRAY_MID(_type)
Definition types.c:168
bool const fr_type_non_leaf[FR_TYPE_MAX+1]
Definition types.c:185
bool fr_type_cast(fr_type_t dst, fr_type_t src)
Return if we're allowed to cast the types.
Definition types.c:283
bool const fr_type_signed[FR_TYPE_MAX+1]
Definition types.c:174
bool const fr_type_integer[FR_TYPE_MAX+1]
Definition types.c:172
bool const fr_type_variable_size[FR_TYPE_MAX+1]
Definition types.c:179
bool const fr_type_numeric[FR_TYPE_MAX+1]
Definition types.c:173
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:348
bool const fr_type_ip[FR_TYPE_MAX+1]
Definition types.c:176
static const bool type_is_number[FR_TYPE_MAX]
Definition types.c:270
bool const fr_type_fixed_size[FR_TYPE_MAX+1]
Definition types.c:178
#define ARRAY_END(_type)
Definition types.c:169
bool const fr_type_integer_except_bool[FR_TYPE_MAX+1]
Definition types.c:171
bool const fr_type_quoted[FR_TYPE_MAX+1]
Definition types.c:180
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:631
bool const fr_type_leaf[FR_TYPE_MAX+1]
Definition types.c:184
size_t fr_type_table_len
Definition types.c:84
static size_t const fr_type_to_c_size[]
Table of all the direct mappings between types and C type sizes.
Definition types.c:130
fr_type_t fr_type_promote(fr_type_t a, fr_type_t b)
Return the promoted type.
Definition types.c:572
static const bool type_cast_table[FR_TYPE_MAX][FR_TYPE_MAX]
Definition types.c:194
#define ARRAY_BEG(_type)
Definition types.c:167
bool const fr_type_structural[FR_TYPE_MAX+1]
Definition types.c:183
#define FR_TYPE_NON_LEAF_DEF(_beg, _mid, _end)
Types which do not represent leaf values.
Definition types.h:267
#define FR_TYPE_IP_DEF(_beg, _mid, _end)
Types which can fit in an fr_ipaddr_t.
Definition types.h:162
#define FR_TYPE_FIXED_SIZE_DEF(_beg, _mid, _end)
Match all fixed length types.
Definition types.h:176
#define FR_TYPE_STRUCTURAL_EXCEPT_VSA_DEF(_beg, _mid, _end)
Stupid hack for things which produce special error messages for VSAs.
Definition types.h:214
#define FR_TYPE_NON_LEAF
Definition types.h:298
#define FR_TYPE_SIGNED_DEF(_beg, _mid, _end)
Signed values.
Definition types.h:131
#define FR_TYPE_VARIABLE_SIZE_DEF(_beg, _mid, _end)
Match all variable length types.
Definition types.h:194
#define FR_TYPE_NUMERIC_DEF(_beg, _mid, _end)
Naturally numeric types.
Definition types.h:148
#define FR_TYPE_INTEGER_EXCEPT_BOOL_DEF(_beg, _mid, _end)
All integer types except bool.
Definition types.h:101
#define FR_TYPE_LEAF_DEF(_beg, _mid, _end)
Types which represent concrete values.
Definition types.h:252
#define fr_type_is_leaf(_x)
Definition types.h:372
#define FR_TYPE_STRUCTURAL_DEF(_beg, _mid, _end)
Match all non value types in case statements.
Definition types.h:241
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:433
#define FR_TYPE_QUOTED_DEF(_beg, _mid, _end)
Types which should be wrapped in double quotes when printed.
Definition types.h:203
#define FR_TYPE_INTEGER_DEF(_beg, _mid, _end)
Signed or unsigned integers.
Definition types.h:121