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: 105000b6b5e24670fa401eef416f716bb606b1d0 $")
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_VALUE_BOX_CURSOR] = "fr_dcursor_t *",
125 [FR_TYPE_PAIR_CURSOR] = "fr_dcursor_t *",
126
127 [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
128};
129
130/** Table of all the direct mappings between types and C type sizes
131 *
132 */
133static size_t const fr_type_to_c_size[] = {
134 [FR_TYPE_STRING] = sizeof(char *),
135 [FR_TYPE_OCTETS] = sizeof(uint8_t *),
136
137 [FR_TYPE_IPV4_ADDR] = sizeof(fr_ipaddr_t),
139 [FR_TYPE_IPV6_ADDR] = sizeof(fr_ipaddr_t),
143 [FR_TYPE_IFID] = sizeof(fr_ifid_t),
145
146 [FR_TYPE_BOOL] = sizeof(bool),
147 [FR_TYPE_UINT8] = sizeof(uint8_t),
148 [FR_TYPE_UINT16] = sizeof(uint16_t),
149 [FR_TYPE_UINT32] = sizeof(uint32_t),
150 [FR_TYPE_UINT64] = sizeof(uint64_t),
151
152 [FR_TYPE_INT8] = sizeof(int8_t),
153 [FR_TYPE_INT16] = sizeof(int16_t),
154 [FR_TYPE_INT32] = sizeof(int32_t),
155 [FR_TYPE_INT64] = sizeof(int64_t),
156
157 [FR_TYPE_FLOAT32] = sizeof(float),
158 [FR_TYPE_FLOAT64] = sizeof(double),
159
160 [FR_TYPE_DATE] = sizeof(fr_unix_time_t),
161
163 [FR_TYPE_SIZE] = sizeof(size_t),
165 [FR_TYPE_VOID] = sizeof(void *),
166
167 [FR_TYPE_VALUE_BOX_CURSOR] = sizeof(void *),
168 [FR_TYPE_PAIR_CURSOR] = sizeof(void *),
169
170 [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
171};
172
173#define ARRAY_BEG(_type) { [_type] = true,
174#define ARRAY_MID(_type) [_type] = true,
175#define ARRAY_END(_type) [_type] = true }
176
181
183
187
192
193#define O(_x) [FR_TYPE_ ## _x] = true
194
195/*
196 * Can we promote [src][dst] -> dst
197 * dst is not octets / string
198 * src and dst are both FR_TYPE_VALUE
199 */
202 O(IPV4_PREFIX),
203 O(IPV6_ADDR),
204 O(IPV6_PREFIX),
205 O(COMBO_IP_ADDR),
206 O(COMBO_IP_PREFIX),
207 O(UINT32), /* ipv4 addresses are uint32 */
208 },
210 O(IPV4_ADDR), /* if the prefix is /32 */
211 O(IPV6_ADDR),
212 O(IPV6_PREFIX),
213 O(COMBO_IP_ADDR),
214 O(COMBO_IP_PREFIX)
215 },
217 O(IPV6_PREFIX),
218 O(COMBO_IP_ADDR),
219 O(COMBO_IP_PREFIX)
220 },
222 O(IPV6_ADDR), /* if the prefix is /128 */
223 O(COMBO_IP_ADDR),
224 O(COMBO_IP_PREFIX)
225 },
227 O(IPV4_ADDR),
228 O(IPV4_PREFIX),
229 O(IPV6_ADDR),
230 O(IPV6_PREFIX),
231 O(COMBO_IP_PREFIX)
232 },
234 O(IPV4_ADDR),
235 O(IPV4_PREFIX),
236 O(IPV6_ADDR),
237 O(IPV6_PREFIX),
238 O(COMBO_IP_ADDR) /* if the prefix is /128 or /32 */
239 },
240
241 [FR_TYPE_ETHERNET] = {
242 O(UINT64),
243 },
244
245 [FR_TYPE_UINT64] = {
246 O(ETHERNET),
247 },
248
249 [FR_TYPE_DATE] = { /* in 2021, dates always have values 2^31 or more */
250 O(UINT32),
251 O(UINT64),
252 O(INT32),
253 O(INT64),
254 O(SIZE),
255 O(FLOAT32),
256 O(FLOAT64),
257 O(TIME_DELTA),
258 },
259
261 O(DATE),
262 },
263
264 [FR_TYPE_UINT32] = {
265 O(IPV4_ADDR),
266 },
267
268};
269
270/*
271 * This is different from FR_TYPE_NUMERIC, largely in that it
272 * doesn't include FR_TYPE_DATE. Because we know that dates
273 * always have values 2^31 or greater, so casts exclude some of
274 * the smaller integer types.
275 */
276static const bool type_is_number[FR_TYPE_MAX] = {
277 O(BOOL), O(SIZE), O(FLOAT32), O(FLOAT64),
278 O(UINT8), O(UINT16), O(UINT32), O(UINT64),
279 O(INT8), O(INT16), O(INT32), O(INT64),
280 O(TIME_DELTA),
281};
282
283/** Return if we're allowed to cast the types.
284 *
285 * @param dst the destination type we wish to cast to
286 * @param src the source type we wish to cast to
287 *
288 */
290{
291 /*
292 * Invalid casts.
293 */
294 switch (dst) {
295 case FR_TYPE_NON_LEAF:
296 return false;
297
298 default:
299 break;
300 }
301
302 switch (src) {
303 case FR_TYPE_NON_LEAF:
304 return false;
305
306 default:
307 break;
308 }
309
310 if (src == dst) return true;
311
312 /*
313 * Anything can be converted to octets or strings.
314 */
315 if (dst == FR_TYPE_OCTETS) return true;
316 if (dst == FR_TYPE_STRING) return true;
317
318 /*
319 * Strings and octets can be converted to anything. We
320 * do run-time checks on the values to see if they fit.
321 */
322 if (src == FR_TYPE_OCTETS) return true;
323 if (src == FR_TYPE_STRING) return true;
324
325 /*
326 * Any integer-style thing can be cast to any other
327 * integer-style thing. Mostly. We do run-time checks
328 * on values to see if they fit.
329 */
330 if (type_is_number[src] && type_is_number[dst]) {
331 return true;
332 }
333
334 /*
335 * That takes care of the simple cases. :( Now to the
336 * complex ones. Instead of masses of if / then / else,
337 * we just use a lookup table.
338 */
339 return type_cast_table[src][dst];
340}
341
342#undef O
343#define O(_x) [FR_TYPE_ ## _x] = FR_TYPE_ ## _x
344
345/** promote (a,b) -> a or b
346 * a/b are not octets / string
347 * a and b are both FR_TYPE_VALUE
348 *
349 * Note that this table can return a type which is _not_ a or b.
350 *
351 * Many lookups of table[a][b] will return b. Some will return a.
352 * Others will return a type which is compatible with both a and b.
353 */
356 O(IPV4_PREFIX),
357 O(IPV6_ADDR),
358 O(IPV6_PREFIX),
360 },
361
364 O(IPV4_PREFIX),
366 O(IPV6_PREFIX),
367 },
368
370 O(IPV6_PREFIX),
371 },
372
375 },
376
377 /* unsigned integers */
378
379 [FR_TYPE_BOOL] = {
380 O(UINT8),
381 O(UINT16),
382 O(UINT32),
383 O(UINT64),
384 O(INT8),
385 O(INT16),
386 O(INT32),
387 O(INT64),
388 O(SIZE),
389 O(FLOAT32),
390 O(FLOAT64),
391 O(TIME_DELTA),
392 },
393
394 [FR_TYPE_UINT8] = {
396 O(UINT16),
397 O(UINT32),
398 O(UINT64),
400 O(INT16),
401 O(INT32),
402 O(INT64),
403 O(SIZE),
404 O(FLOAT32),
405 O(FLOAT64),
406 O(TIME_DELTA),
407 },
408
409 [FR_TYPE_UINT16] = {
412 O(UINT32),
413 O(UINT64),
415 O(INT32),
416 O(INT64),
417 O(SIZE),
418 O(FLOAT32),
419 O(FLOAT64),
420 O(TIME_DELTA),
421 },
422
423 [FR_TYPE_UINT32] = {
425 O(IPV4_ADDR),
428 O(UINT64),
430 O(INT64),
431 O(SIZE),
432 O(FLOAT32),
433 O(FLOAT64),
434 O(TIME_DELTA),
435 O(DATE),
436 },
437
438 [FR_TYPE_UINT64] = {
443
448 O(SIZE),
450 O(FLOAT64),
451 O(TIME_DELTA),
452 O(DATE),
453 },
454
455 /* signed integers */
456 [FR_TYPE_INT8] = {
458 O(UINT8),
459 O(UINT16),
460 O(UINT32),
461 O(UINT64),
462 O(INT16),
463 O(INT32),
464 O(INT64),
465 O(SIZE),
466 O(FLOAT32),
467 O(FLOAT64),
468 O(TIME_DELTA),
469 },
470
471 [FR_TYPE_INT16] = {
474 O(UINT16),
475 O(UINT32),
476 O(UINT64),
478 O(INT32),
479 O(INT64),
480 O(SIZE),
481 O(FLOAT32),
482 O(FLOAT64),
483 O(TIME_DELTA),
484 },
485
486 [FR_TYPE_INT32] = {
490 O(UINT32),
491 O(UINT64),
494 O(INT64),
495 O(SIZE),
496 O(FLOAT32),
497 O(FLOAT64),
498 O(TIME_DELTA),
499 O(DATE),
500 },
501
502 [FR_TYPE_INT64] = {
506 O(UINT64),
507 O(SIZE),
512 O(FLOAT64),
513 O(TIME_DELTA),
514 O(DATE),
515 },
516
524
529
533 },
534
535 [FR_TYPE_DATE] = {
539
542
545 O(TIME_DELTA),
546 },
547
548 [FR_TYPE_SIZE] = {
559 O(FLOAT64),
561 O(DATE),
562 }
563};
564
565/** Return the promoted type
566 *
567 * We presume that the two types are compatible, as checked by
568 * calling fr_type_cast(). The main difference here is that the two
569 * types don't have any src / dst relationship. Instead, we just
570 * pick one which best suits any value-box comparisons
571 *
572 * Note that this function can return a type which is _not_ a or b.
573 *
574 * @param a type one
575 * @param b type two
576 * @return the promoted type
577 */
579{
580 if (!fr_type_is_leaf(a) || !fr_type_is_leaf(b)) return FR_TYPE_NULL;
581
582 if (a == b) return a;
583
584 /*
585 * string / octets and "type", the un-typed data gets cast to
586 * "type".
587 *
588 * We prefer to cast raw data to real types. We also
589 * prefer to _parse_ strings, and do the type checking on
590 * the real types. That way we have things like: "000" == 0
591 */
592 if (a == FR_TYPE_OCTETS) return b;
593 if (b == FR_TYPE_OCTETS) return a;
594
595 /*
596 * Check for string after octets, because we want to cast
597 * octets to string, and not vice versa.
598 */
599 if (a == FR_TYPE_STRING) return b;
600 if (b == FR_TYPE_STRING) return a;
601
602 /*
603 * Otherwise bad things happen. :(
604 */
605 if (unlikely(type_promote_table[a][b] != type_promote_table[b][a])) {
606 fr_strerror_printf("Inverse type mapping inconsistent for a = %s, b = %s",
608 fr_type_to_str(b));
609
610 return FR_TYPE_NULL;
611 }
612
614 fr_strerror_printf("No type promotions for a = %s, b = %s",
616 fr_type_to_str(b));
617 return FR_TYPE_NULL;
618 }
619
620 /*
621 * That takes care of the simple cases. :( Now to the
622 * complex ones. Instead of masses of if / then / else,
623 * we just use a lookup table.
624 */
625 return type_promote_table[a][b];
626}
627
628/** Allocate an array of a given type
629 *
630 * @param[in] ctx to allocate array in.
631 * @param[in] type array to allocate.
632 * @param[in] count The number of elements to allocate.
633 * @return
634 * - NULL on error.
635 * - A new talloc array.
636 */
637void **fr_type_array_alloc(TALLOC_CTX *ctx, fr_type_t type, size_t count)
638{
639 char const *c_type;
640
641 c_type = fr_type_to_c_type[type];
642 if (c_type == NULL) {
643 fr_strerror_printf("Type %s does not have a C type equivalent", fr_type_to_str(type));
644 return NULL;
645 }
646
647 return _talloc_zero_array(ctx, fr_type_to_c_size[type], count, c_type);
648 }
#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:193
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:188
#define ARRAY_MID(_type)
Definition types.c:174
bool const fr_type_non_leaf[FR_TYPE_MAX+1]
Definition types.c:191
bool fr_type_cast(fr_type_t dst, fr_type_t src)
Return if we're allowed to cast the types.
Definition types.c:289
bool const fr_type_signed[FR_TYPE_MAX+1]
Definition types.c:180
bool const fr_type_integer[FR_TYPE_MAX+1]
Definition types.c:178
bool const fr_type_variable_size[FR_TYPE_MAX+1]
Definition types.c:185
bool const fr_type_numeric[FR_TYPE_MAX+1]
Definition types.c:179
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:354
bool const fr_type_ip[FR_TYPE_MAX+1]
Definition types.c:182
static const bool type_is_number[FR_TYPE_MAX]
Definition types.c:276
bool const fr_type_fixed_size[FR_TYPE_MAX+1]
Definition types.c:184
#define ARRAY_END(_type)
Definition types.c:175
bool const fr_type_integer_except_bool[FR_TYPE_MAX+1]
Definition types.c:177
bool const fr_type_quoted[FR_TYPE_MAX+1]
Definition types.c:186
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:637
bool const fr_type_leaf[FR_TYPE_MAX+1]
Definition types.c:190
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:133
fr_type_t fr_type_promote(fr_type_t a, fr_type_t b)
Return the promoted type.
Definition types.c:578
static const bool type_cast_table[FR_TYPE_MAX][FR_TYPE_MAX]
Definition types.c:200
#define ARRAY_BEG(_type)
Definition types.c:173
bool const fr_type_structural[FR_TYPE_MAX+1]
Definition types.c:189
#define FR_TYPE_NON_LEAF_DEF(_beg, _mid, _end)
Types which do not represent leaf values.
Definition types.h:284
#define FR_TYPE_IP_DEF(_beg, _mid, _end)
Types which can fit in an fr_ipaddr_t.
Definition types.h:166
#define FR_TYPE_FIXED_SIZE_DEF(_beg, _mid, _end)
Match all fixed length types.
Definition types.h:180
@ FR_TYPE_VALUE_BOX_CURSOR
cursor over a fr_value_box_t
Definition types.h:87
@ FR_TYPE_PAIR_CURSOR
cursor over a fr_pair_t
Definition types.h:89
#define FR_TYPE_STRUCTURAL_EXCEPT_VSA_DEF(_beg, _mid, _end)
Stupid hack for things which produce special error messages for VSAs.
Definition types.h:218
#define FR_TYPE_NON_LEAF
Definition types.h:314
#define FR_TYPE_SIGNED_DEF(_beg, _mid, _end)
Signed values.
Definition types.h:135
#define FR_TYPE_VARIABLE_SIZE_DEF(_beg, _mid, _end)
Match all variable length types.
Definition types.h:198
#define FR_TYPE_NUMERIC_DEF(_beg, _mid, _end)
Naturally numeric types.
Definition types.h:152
#define FR_TYPE_INTEGER_EXCEPT_BOOL_DEF(_beg, _mid, _end)
All integer types except bool.
Definition types.h:105
#define FR_TYPE_LEAF_DEF(_beg, _mid, _end)
Types which represent concrete values.
Definition types.h:256
#define fr_type_is_leaf(_x)
Definition types.h:389
#define FR_TYPE_STRUCTURAL_DEF(_beg, _mid, _end)
Match all non value types in case statements.
Definition types.h:245
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:450
#define FR_TYPE_QUOTED_DEF(_beg, _mid, _end)
Types which should be wrapped in double quotes when printed.
Definition types.h:207
#define FR_TYPE_INTEGER_DEF(_beg, _mid, _end)
Signed or unsigned integers.
Definition types.h:125