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