The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
table.h
Go to the documentation of this file.
1#pragma once
2/*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16 */
17
18/**
19 * $Id: 38c2d2be6e904ae2d086d3947245f6eb9305acd9 $
20 *
21 * @file lib/util/table.h
22 * @brief Lookup table functions
23 *
24 * @copyright 2019 The FreeRADIUS server project
25 * @copyright 2019 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
26 */
27RCSIDH(table_h, "$Id: 38c2d2be6e904ae2d086d3947245f6eb9305acd9 $")
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33#include <ctype.h>
34#include <string.h>
35#include <stddef.h>
36#include <stdint.h>
37#include <sys/types.h>
38
39DIAG_OFF(unused-function)
40
41typedef struct {
42 char const *str; //!< Literal string.
43 size_t len; //!< Literal string length.
45
46/** An element in a lexicographically sorted array of name to num mappings
47 *
48 */
53
54/** An element in an arbitrarily ordered array of name to num mappings
55 *
56 */
61
62/** An element in a lexicographically sorted array of name to ptr mappings
63 *
64 */
65typedef struct {
67 void const *value;
69
70/** An element in an arbitrarily ordered array of name to ptr mappings
71 *
72 */
73typedef struct {
75 void const *value;
77
78/** An element in a table indexed by bit position
79 *
80 * i.e. if only the first bit is set in a bitfield, the entry at index 0
81 * will be returned.
82 */
87
88/** An element in a table indexed by numeric value
89 *
90 * i.e. if the value is 0, we return the string mapped to the first element of the table.
91 */
92typedef struct {
94 unsigned int value;
96
97/** Build a single fr_table_num_indexed_t entry from an enum identifier.
98 *
99 * Expands to `[FOO] = { L("FOO"), FOO }` so the identifier doesn't have
100 * to be written three times. Use with a typed
101 * `fr_table_num_indexed_t const []` initialiser to map enum-value-to-name
102 * lookups via fr_table_str_by_value().
103 *
104 * static fr_table_num_indexed_t const my_table[] = {
105 * FR_TABLE_INDEXED_ENTRY(FR_TYPE_STRING),
106 * FR_TABLE_INDEXED_ENTRY(FR_TYPE_OCTETS),
107 * ...
108 * };
109 */
110#define FR_TABLE_INDEXED_ENTRY(_v) [_v] = { L(STRINGIFY(_v)), _v }
111
112/** Build a single fr_table_num_indexed_bit_pos_t entry from an enum identifier.
113 *
114 * `_v` is a single-bit mask of the form `(1 << N)`; the entry's table
115 * index is `N + 1` (matching what `fr_table_indexed_str_by_bit_field`
116 * computes via `fr_high_bit_pos()`). The compile-time `__builtin_ctz`
117 * keeps the position-arithmetic out of the call site:
118 *
119 * static fr_table_num_indexed_bit_pos_t const my_flags[] = {
120 * FR_TABLE_INDEXED_BIT_POS_ENTRY(CONF_FLAG_REQUIRED),
121 * FR_TABLE_INDEXED_BIT_POS_ENTRY(CONF_FLAG_MULTI),
122 * ...
123 * };
124 */
125#define FR_TABLE_INDEXED_BIT_POS_ENTRY(_v) [__builtin_ctz(_v) + 1] = { L(STRINGIFY(_v)), _v }
126
127/** Macro to use as dflt
128 *
129 */
130#define NAME_NUMBER_NOT_FOUND INT32_MIN
131
132char const *_fr_table_ptr_by_str_value(fr_table_ptr_sorted_t const *table, size_t table_len, char const *str_val, char const *def);
133
134#define TABLE_IDX(_table, _idx, _element_size) (((uint8_t const *)(_table)) + ((_idx) * (_element_size)))
135#define ELEM_STR(_offset) (*((fr_table_elem_name_t const *)(_offset))).str
136#define ELEM_LEN(_offset) (*((fr_table_elem_name_t const *)(_offset))).len
137
138/** Create a type-specific name-to-value function
139 *
140 * @param[in] _func Used for resolving the name portion of an array element to a value.
141 * Should be one of the following:
142 * - table_sorted_value_by_str - for lexicographically sorted tables.
143 * - table_ordered_value_by_str - for arbitrarily ordered tables.
144 * @param[in] _our_table_type C type of the table elements.
145 * @param[in] _our_name name of the search function to define.
146 * @param[in] _our_def_type C type of the default value.
147 * @param[in] _our_return_type C type of the return value, i.e. the value part of the element.
148 */
149#define TABLE_TYPE_NAME_FUNC(_func, _our_table_type, _our_name, _our_def_type, _our_return_type) \
150_our_return_type _our_name(_our_table_type table, size_t table_len, char const *name, _our_def_type def) \
151{ \
152 _our_return_type ret; \
153 _our_table_type found; \
154 found = (_our_table_type)_func(table, table_len, sizeof(((_our_table_type)0)[0]), name); \
155 if (!found) { \
156 memcpy(&ret, &def, sizeof(ret)); \
157 return ret; \
158 } \
159 memcpy(&ret, &found->value, sizeof(ret)); \
160 return ret; \
161}
162
163/** Create a type-specific name-to-value function
164 *
165 * @param[in] _func Used for resolving the name portion of an array element to a value.
166 * Should be one of the following:
167 * - table_sorted_value_by_str - for lexicographically sorted tables.
168 * - table_ordered_value_by_str - for arbitrarily ordered tables.
169 * @param[in] _our_table_type C type of the table elements.
170 * @param[in] _our_name name of the search function to define.
171 * @param[in] _our_def_type C type of the default value.
172 * @param[in] _our_out_type C type of the return/output value, i.e. the value part of the element.
173 */
174#define TABLE_TYPE_NAME_FUNC_RPTR(_func, _our_table_type, _our_name, _our_def_type, _our_out_type) \
175bool _our_name(_our_out_type *out, _our_table_type table, size_t table_len, char const *name, _our_def_type def) \
176{ \
177 _our_table_type found; \
178 found = (_our_table_type)_func(table, table_len, sizeof(((_our_table_type)0)[0]), name); \
179 if (!found) { \
180 *out = def; \
181 return false; \
182 } \
183 *out = &found->value; \
184 return true; \
185}
186
187/** Create a type-specific name-to-value function that can perform substring matching with a 'name_len' argument
188 *
189 * @param[in] _func Used for resolving the name portion of an array element to a value.
190 * Should be one of the following:
191 * - table_sorted_value_by_substr - for lexicographically sorted tables
192 * with partial matching.
193 * - table_ordered_value_by_substr - for arbitrarily ordered tables.
194 * with partial matching.
195 * @param[in] _our_table_type C type of the table elements.
196 * Must contain two fields, an #fr_table_elem_name_t called name
197 * and an arbitraryily typed field called value.
198 * A pointer to thi
199 * @param[in] _our_name name of the search function to define.
200 * @param[in] _our_def_type C type of the default value.
201 * @param[in] _our_return_type C type of the return value, i.e. the value part of the element.
202 */
203#define TABLE_TYPE_NAME_LEN_FUNC(_func, _our_table_type, _our_name, _our_def_type, _our_return_type) \
204_our_return_type _our_name(_our_table_type table, size_t table_len, char const *name, ssize_t name_len, _our_def_type def) \
205{ \
206 _our_return_type ret; \
207 _our_table_type found; \
208 found = (_our_table_type)_func(table, table_len, sizeof(((_our_table_type)0)[0]), name, name_len); \
209 if (!found) { \
210 memcpy(&ret, &def, sizeof(ret)); \
211 return ret; \
212 } \
213 memcpy(&ret, &found->value, sizeof(ret)); \
214 return ret; \
215}
216
217/** Create a type-specific name-to-value function that can perform substring matching with a 'name_len' argument
218 *
219 * @note The functions created by this macro return true on a match, false on no match, and write a
220 * pointer to the value field of the table element to the 'out' argument.
221 *
222 * @param[in] _func Used for resolving the name portion of an array element to a value.
223 * Should be one of the following:
224 * - table_sorted_value_by_substr - for lexicographically sorted tables
225 * with partial matching.
226 * - table_ordered_value_by_substr - for arbitrarily ordered tables.
227 * with partial matching.
228 * @param[in] _our_table_type C type of the table elements.
229 * Must contain two fields, an #fr_table_elem_name_t called name
230 * and an arbitraryily typed field called value.
231 * A pointer to thi
232 * @param[in] _our_name name of the search function to define.
233 * @param[in] _our_def_type C type of the default value.
234 * @param[in] _our_out_type C type of the return/output value, i.e. the value part of the element.
235 */
236#define TABLE_TYPE_NAME_LEN_FUNC_RPTR(_func, _our_table_type, _our_name, _our_def_type, _our_out_type) \
237bool _our_name(_our_out_type *out, _our_table_type table, size_t table_len, char const *name, ssize_t name_len, _our_def_type def) \
238{ \
239 _our_table_type found; \
240 found = (_our_table_type)_func(table, table_len, sizeof(((_our_table_type)0)[0]), name, name_len); \
241 if (!found) { \
242 *out = def; \
243 return false; \
244 } \
245 *out = &found->value; \
246 return true; \
247}
248
249/** Create a type-specific name-to-value function that can perform substring matching with a 'name_len' argument, and passes back the length of the matched string
250 *
251 * @note The functions created by this macro return the value field of the table element.
252 *
253 * @param[in] _func Used for resolving the name portion of an array element to a value.
254 * Should be one of the following:
255 * - table_sorted_value_by_longest_prefix - for lexicographically sorted tables
256 * with longest prefix match.
257 * - table_ordered_value_by_longest_prefix - for arbitrarily ordered tables
258 * with longest prefix match.
259 * @param[in] _our_table_type C type of the table elements.
260 * @param[in] _our_name name of the search function to define.
261 * @param[in] _our_def_type C type of the default value.
262 * @param[in] _our_return_type C type of the return value, i.e. the value part of the element.
263 */
264#define TABLE_TYPE_NAME_MATCH_LEN_FUNC(_func, _our_table_type, _our_name, _our_def_type, _our_return_type) \
265_our_return_type _our_name(size_t *match_len, _our_table_type table, size_t table_len, char const *name, ssize_t name_len, _our_def_type def) \
266{ \
267 _our_return_type ret; \
268 _our_table_type found; \
269 found = (_our_table_type)_func(match_len, table, table_len, sizeof(((_our_table_type)0)[0]), name, name_len); \
270 if (!found) { \
271 memcpy(&ret, &def, sizeof(ret)); \
272 return ret; \
273 } \
274 memcpy(&ret, &found->value, sizeof(ret)); \
275 return ret; \
276}
277
278/** Create a type-specific name-to-value function that can perform substring matching with a 'name_len' argument, and passes back the length of the matched string
279 *
280 * @note The functions created by this macro return true on a match, false on no match, and write a
281 * pointer to the value field of the table element to the 'out' argument.
282 *
283 * @param[in] _func Used for resolving the name portion of an array element to a value.
284 * Should be one of the following:
285 * - table_sorted_value_by_longest_prefix - for lexicographically sorted tables
286 * with longest prefix match.
287 * - table_ordered_value_by_longest_prefix - for arbitrarily ordered tables
288 * with longest prefix match.
289 * @param[in] _our_table_type C type of the table elements.
290 * @param[in] _our_name name of the search function to define.
291 * @param[in] _our_def_type C type of the default value.
292 * @param[in] _our_out_type C type of the return/output value, i.e. the value part of the element.
293 */
294#define TABLE_TYPE_NAME_MATCH_LEN_FUNC_RPTR(_func, _our_table_type, _our_name, _our_def_type, _our_out_type) \
295bool _our_name(size_t *match_len, _our_out_type *out, _our_table_type table, size_t table_len, char const *name, ssize_t name_len, _our_def_type def) \
296{ \
297 _our_table_type found; \
298 found = (_our_table_type)_func(match_len, table, table_len, sizeof(((_our_table_type)0)[0]), name, name_len); \
299 if (!found) { \
300 *out = def; \
301 return false; \
302 } \
303 *out = &found->value; \
304 return true; \
305}
306
307/** Create a type-specific value-to-name function
308 *
309 * @param[in] _our_table_type C type of the table elements.
310 * @param[in] _our_name name of the search function to define.
311 * @param[in] _our_value_type C type of the value field of the table element.
312 */
313#define TABLE_TYPE_VALUE_FUNC(_our_table_type, _our_name, _our_value_type) \
314char const *_our_name(_our_table_type table, size_t table_len, _our_value_type value, char const *def) \
315{ \
316 size_t i; \
317 for (i = 0; i < table_len; i++) if (table[i].value == value) return table[i].name.str; \
318 return def; \
319}
320
321/** Create a type-specific value-to-name function, which uses the highest bit set in the value as an index into the table
322 *
323 * @param[in] _our_table_type C type of the table elements.
324 * @param[in] _our_name name of the search function to define.
325 * @param[in] _our_value_type C type of the value field of the table element.
326 */
327#define TABLE_TYPE_VALUE_INDEX_BIT_FIELD_FUNC(_our_table_type, _our_name, _our_value_type) \
328char const *_our_name(_our_table_type table, size_t table_len, _our_value_type value, char const *def) \
329{ \
330 uint8_t idx = fr_high_bit_pos(value); \
331 if (idx >= table_len) return def; \
332 if (!table[idx].name.str) return def; /* sparse table: unpopulated slot */ \
333 return table[idx].name.str; \
334}
335
336/** Create a type-specific value-to-name function, which uses the value as an index into the table
337 *
338 * @param[in] _our_table_type C type of the table elements.
339 * @param[in] _our_name name of the search function to define.
340 * @param[in] _our_value_type C type of the value field of the table element.
341 */
342#define TABLE_TYPE_VALUE_INDEX_FUNC(_our_table_type, _our_name, _our_value_type) \
343char const *_our_name(_our_table_type table, size_t table_len, _our_value_type value, char const *def) \
344{ \
345 if (value >= table_len) return def; \
346 if (!table[value].name.str) return def; /* sparse table: unpopulated slot */ \
347 return table[value].name.str; \
348}
349
350/** Convert a string to a value using a lexicographically sorted table
351 *
352 * @param[in] table to search in.
353 * @param[in] table_len The number of elements in the table.
354 * @param[in] element_size Size of elements in the table.
355 * @param[in] name to resolve to a value.
356 * @return
357 * - value of matching entry.
358 * - NULL if no matching entries.
359 */
360static void const *table_sorted_value_by_str(void const *table, size_t table_len, size_t element_size,
361 char const *name)
362{
363 ssize_t start = 0;
364 ssize_t end = table_len - 1;
365 ssize_t mid;
366
367 int ret;
368
369 if (!name) return NULL;
370
371 while (start <= end) {
372 void const *offset;
373
374 mid = start + ((end - start) / 2); /* Avoid overflow */
375
376 offset = TABLE_IDX(table, mid, element_size);
377 ret = strcasecmp(name, ELEM_STR(offset));
378 if (ret == 0) return offset;
379 if (ret < 0) {
380 end = mid - 1;
381 } else {
382 start = mid + 1;
383 }
384 }
385
386 return NULL;
387}
388
389/** Convert a string to a value using an arbitrarily ordered table
390 *
391 * @param[in] table to search in.
392 * @param[in] table_len The number of elements in the table.
393 * @param[in] element_size Size of elements in the table.
394 * @param[in] name to resolve to a number.
395 * @return
396 * - value of matching entry.
397 * - NULL if no matching entries.
398 */
399static void const *table_ordered_value_by_str(void const *table, size_t table_len, size_t element_size,
400 char const *name)
401{
402 size_t i;
403
404 if (!name) return NULL;
405
406 for (i = 0; i < table_len; i++) {
407 void const *offset = TABLE_IDX(table, i, element_size);
408 if (strcasecmp(name, ELEM_STR(offset)) == 0) return offset;
409 }
410
411 return NULL;
412}
413
414/** Convert a string matching part of name to an integer using a lexicographically sorted table
415 *
416 * @param[in] table to search in.
417 * @param[in] table_len The number of elements in the table.
418 * @param[in] element_size Size of elements in the table.
419 * @param[in] name to locate.
420 * @param[in] name_len the maximum amount of name that should be matched.
421 * If < 0, the length of the name in the table offsetent
422 * will be used as the maximum match length.
423 * @return
424 * - value of matching entry.
425 * - NULL if no matching entries.
426 */
427static void const *table_sorted_value_by_substr(void const *table, size_t table_len, size_t element_size,
428 char const *name, ssize_t name_len)
429{
430 ssize_t start = 0;
431 ssize_t end = table_len - 1;
432 ssize_t mid;
433
434 int ret;
435
436 if (!name) return NULL;
437
438 while (start <= end) {
439 void const *offset;
440
441 mid = start + ((end - start) / 2); /* Avoid overflow */
442
443 offset = TABLE_IDX(table, mid, element_size);
444
445 /*
446 * Match up to the length of the table entry if len is < 0.
447 */
448 ret = strncasecmp(name, ELEM_STR(offset),
449 (name_len < 0) ? ELEM_LEN(offset) : (size_t)name_len);
450 if (ret == 0) return offset;
451
452 if (ret < 0) {
453 end = mid - 1;
454 } else {
455 start = mid + 1;
456 }
457 }
458
459 return NULL;
460}
461
462/** Convert a string matching part of name to an integer using an arbitrarily ordered table
463 *
464 * @param[in] table to search in.
465 * @param[in] table_len The number of elements in the table.
466 * @param[in] element_size Size of elements in the table.
467 * @param[in] name to locate.
468 * @param[in] name_len the maximum amount of name that should be matched.
469 * If < 0, the length of the name in the table offsetent
470 * will be used as the maximum match length.
471 * @return
472 * - value of matching entry.
473 * - NULL if no matching entries.
474 */
475static void const *table_ordered_value_by_substr(void const *table, size_t table_len, size_t element_size,
476 char const *name, ssize_t name_len)
477{
478 size_t i;
479
480 if (!name) return NULL;
481
482 for (i = 0; i < table_len; i++) {
483 void const *offset;
484 size_t tlen;
485
486 offset = TABLE_IDX(table, i, element_size);
487
488 tlen = ELEM_LEN(offset);
489
490 /*
491 * Don't match "request" to user input "req".
492 */
493 if ((name_len > 0) && (name_len < (int) tlen)) continue;
494
495 /*
496 * Match up to the length of the table entry if len is < 0.
497 */
498 if (strncasecmp(name, ELEM_STR(offset),
499 (name_len < 0) ? tlen : (size_t)name_len) == 0) return offset;
500 }
501
502 return NULL;
503}
504
505/** Find the longest string match using a lexicographically sorted table
506 *
507 * Performs a binary search in the specified table, returning the longest
508 * offsetent which is a prefix of name.
509 *
510 * i.e. given name of "food", and table of f, foo, of - foo would be returned.
511 *
512 * @note The table *MUST* be sorted lexicographically, else the result may be incorrect.
513 *
514 * @param[out] match_len How much of the input string matched.
515 * @param[in] table to search in.
516 * @param[in] table_len The number of elements in the table.
517 * @param[in] element_size Size of elements in the table.
518 * @param[in] name to locate.
519 * @param[in] name_len the maximum amount of name that should be matched.
520 * @return
521 * - num value of matching entry.
522 * - NULL if no matching entries.
523 */
524static void const *table_sorted_value_by_longest_prefix(size_t *match_len,
525 void const *table, size_t table_len, size_t element_size,
526 char const *name, ssize_t name_len)
527{
528 ssize_t start = 0;
529 ssize_t end = table_len - 1;
530 ssize_t mid;
531
532 int ret;
533 void const *found = NULL;
534
535 if (!name) return NULL;
536 if (name_len < 0) name_len = strlen(name);
537
538 while (start <= end) {
539 void const *offset;
540 char const *elem;
541 size_t tlen;
542
543 mid = start + ((end - start) / 2); /* Avoid overflow */
544
545 offset = TABLE_IDX(table, mid, element_size);
546 elem = ELEM_STR(offset);
547 tlen = ELEM_LEN(offset);
548
549 ret = strncasecmp(name, elem, tlen < (size_t)name_len ? tlen : (size_t)name_len);
550 if (ret == 0) {
551 /*
552 * Exact match
553 */
554 if (tlen == (size_t)name_len) {
555 if (match_len) *match_len = tlen;
556 return offset;
557 }
558
559 /*
560 * Partial match.
561 * Name we're searching for is longer.
562 * This might be the longest prefix,
563 * so record it.
564 */
565 if (tlen < (size_t)name_len) {
566 found = offset;
567 if (match_len) *match_len = tlen;
568 ret = 1;
569 } else {
570 ret = -1;
571 }
572 }
573
574 if (ret < 0) {
575 end = mid - 1;
576 } else {
577 start = mid + 1;
578 }
579 }
580
581 if (!found && match_len) *match_len = 0;
582
583 return found;
584}
585
586/** Find the longest string match using an arbitrarily ordered table
587 *
588 * i.e. given name of "food", and table of f, foo, of - foo would be returned.
589 *
590 * @param[out] match_len How much of the input string matched.
591 * @param[in] table to search in.
592 * @param[in] table_len The number of elements in the table.
593 * @param[in] element_size Size of elements in the table.
594 * @param[in] name to locate.
595 * @param[in] name_len the maximum amount of name that should be matched.
596 * @return
597 * - num value of matching entry.
598 * - def if no matching entries.
599 */
600static void const *table_ordered_value_by_longest_prefix(size_t *match_len,
601 void const *table, size_t table_len, size_t element_size,
602 char const *name, ssize_t name_len)
603{
604 size_t i;
605 size_t found_len = 0;
606 void const *found = NULL;
607
608 if (!name) return NULL;
609 if (name_len < 0) name_len = strlen(name);
610
611 for (i = 0; i < table_len; i++) {
612 void const *offset;
613 size_t j;
614
615 offset = TABLE_IDX(table, i, element_size);
616
617 for (j = 0; (j < (size_t)name_len) && (j < ELEM_LEN(offset)) &&
618 (tolower(name[j]) == tolower((ELEM_STR(offset))[j])); j++);
619
620 /*
621 * If we didn't get to the end of the
622 * table string, then continue.
623 */
624 if ((ELEM_STR(offset))[j] != '\0') continue;
625
626 /*
627 * Exact match
628 */
629 if (j == (size_t)name_len) {
630 if (match_len) *match_len = name_len;
631 return offset;
632 }
633
634 /*
635 * Partial match.
636 * Name we're searching for is longer.
637 * This might be the longest prefix,
638 * so record it.
639 */
640 if (j > found_len) {
641 found_len = j;
642 found = offset;
643 }
644 }
645
646 if (match_len) *match_len = found_len;
647
648 return found;
649}
650
651/** Brute force search a sorted or ordered ptr table, assuming the pointers are strings
652 *
653 * @param[in] _table to search in.
654 * @param[in] _str_value to compare against the ptr field.
655 * @param[in] _def default value.
656 */
657#define fr_table_str_by_str_value(_table, _str_value, _def) \
658_Generic((_table), \
659 fr_table_ptr_sorted_t const * : _fr_table_ptr_by_str_value((fr_table_ptr_sorted_t const *)_table, _table ## _len, _str_value, _def), \
660 fr_table_ptr_ordered_t const * : _fr_table_ptr_by_str_value((fr_table_ptr_sorted_t const *)_table, _table ## _len, _str_value, _def), \
661 fr_table_ptr_sorted_t * : _fr_table_ptr_by_str_value((fr_table_ptr_sorted_t const *)_table, _table ## _len, _str_value, _def), \
662 fr_table_ptr_ordered_t * : _fr_table_ptr_by_str_value((fr_table_ptr_sorted_t const *)_table, _table ## _len, _str_value, _def))
663
664int fr_table_sorted_num_by_str(fr_table_num_sorted_t const *table, size_t table_len,
665 char const *name, int def);
666
667int fr_table_ordered_num_by_str(fr_table_num_ordered_t const *table, size_t table_len,
668 char const *name, int def);
669
670void *fr_table_sorted_ptr_by_str(fr_table_ptr_sorted_t const *table, size_t table_len,
671 char const *name, void const *def);
672
673void *fr_table_ordered_ptr_by_str(fr_table_ptr_ordered_t const *table, size_t table_len,
674 char const *name, void const *def);
675
676/** Convert a string to a value using a sorted or ordered table
677 *
678 * @param[in] _table to search in.
679 * @param[in] _name to resolve to a number.
680 * @param[in] _def Default value if no entry matched.
681 * @return
682 * - _def if name matched no entries in the table.
683 * - the numeric value of the matching entry.
684 */
685#define fr_table_value_by_str(_table, _name, _def) \
686_Generic((_table), \
687 fr_table_num_sorted_t const * : fr_table_sorted_num_by_str, \
688 fr_table_num_ordered_t const * : fr_table_ordered_num_by_str, \
689 fr_table_num_sorted_t * : fr_table_sorted_num_by_str, \
690 fr_table_num_ordered_t * : fr_table_ordered_num_by_str, \
691 fr_table_ptr_sorted_t const * : fr_table_sorted_ptr_by_str, \
692 fr_table_ptr_ordered_t const * : fr_table_ordered_ptr_by_str, \
693 fr_table_ptr_sorted_t * : fr_table_sorted_ptr_by_str, \
694 fr_table_ptr_ordered_t * : fr_table_ordered_ptr_by_str, \
695 fr_table_num_indexed_bit_pos_t * : fr_table_ordered_num_by_str, \
696 fr_table_num_indexed_bit_pos_t const * : fr_table_ordered_num_by_str, \
697 fr_table_num_indexed_t * : fr_table_ordered_num_by_str, \
698 fr_table_num_indexed_t const * : fr_table_ordered_num_by_str \
699)(_table, _table ## _len, _name, _def)
700
701int fr_table_sorted_num_by_substr(fr_table_num_sorted_t const *table, size_t table_len,
702 char const *name, ssize_t name_len, int def);
703
705 char const *name, ssize_t name_len, int def);
706
707void *fr_table_sorted_ptr_by_substr(fr_table_ptr_sorted_t const *table, size_t table_len,
708 char const *name, ssize_t name_len, void const *def);
709
710void *fr_table_ordered_ptr_by_substr(fr_table_ptr_ordered_t const *table, size_t table_len,
711 char const *name, ssize_t name_len, void const *def);
712
713/** Convert a partial string to a value using an ordered or sorted table
714 *
715 * @param[in] _table to search in.
716 * @param[in] _name to resolve to a number.
717 * @param[in] _name_len The amount of name to match.
718 * If < 0, the length of the name in the table element
719 * will be used as the maximum match length.
720 * @param[in] _def Default value if no entry matched.
721 * @return
722 * - _def if name matched no entries in the table.
723 * - the numeric value of the matching entry.
724 */
725#define fr_table_value_by_substr(_table, _name, _name_len, _def) \
726_Generic((_table), \
727 fr_table_num_sorted_t const * : fr_table_sorted_num_by_substr, \
728 fr_table_num_ordered_t const * : fr_table_ordered_num_by_substr, \
729 fr_table_num_sorted_t * : fr_table_sorted_num_by_substr, \
730 fr_table_num_ordered_t * : fr_table_ordered_num_by_substr, \
731 fr_table_ptr_sorted_t const * : fr_table_sorted_ptr_by_substr, \
732 fr_table_ptr_ordered_t const * : fr_table_ordered_ptr_by_substr, \
733 fr_table_ptr_sorted_t * : fr_table_sorted_ptr_by_substr, \
734 fr_table_ptr_ordered_t * : fr_table_ordered_ptr_by_substr, \
735 fr_table_num_indexed_bit_pos_t * : fr_table_ordered_num_by_substr, \
736 fr_table_num_indexed_bit_pos_t const * : fr_table_ordered_num_by_substr, \
737 fr_table_num_indexed_t * : fr_table_ordered_num_by_substr, \
738 fr_table_num_indexed_t const * : fr_table_ordered_num_by_substr \
739)(_table, _table ## _len, _name, _name_len, _def)
740
741int fr_table_sorted_num_by_longest_prefix(size_t *match_len, fr_table_num_sorted_t const *table, size_t table_len,
742 char const *name, ssize_t name_len, int def);
743
744int fr_table_ordered_num_by_longest_prefix(size_t *match_len, fr_table_num_ordered_t const *table, size_t table_len,
745 char const *name, ssize_t name_len, int def);
746
747void *fr_table_sorted_ptr_by_longest_prefix(size_t *match_len, fr_table_ptr_sorted_t const *table, size_t table_len,
748 char const *name, ssize_t name_len, void const *def);
749
750void *fr_table_ordered_ptr_by_longest_prefix(size_t *match_len, fr_table_ptr_ordered_t const *table, size_t table_len,
751 char const *name, ssize_t name_len, void const *def);
752
753/** Find the longest string match using a sorted or ordered table
754 *
755 * @param[out] _match_len How much of the input string matched.
756 * @param[in] _table to search in.
757 * @param[in] _name to resolve to a number.
758 * @param[in] _name_len The amount of name to match.
759 * @param[in] _def Default value if no entry matched.
760 * @return
761 * - _def if name matched no entries in the table.
762 * - the value of the matching entry.
763 */
764#define fr_table_value_by_longest_prefix(_match_len, _table, _name, _name_len, _def) \
765_Generic((_table), \
766 fr_table_num_sorted_t const * : fr_table_sorted_num_by_longest_prefix, \
767 fr_table_num_ordered_t const * : fr_table_ordered_num_by_longest_prefix, \
768 fr_table_num_sorted_t * : fr_table_sorted_num_by_longest_prefix, \
769 fr_table_num_ordered_t * : fr_table_ordered_num_by_longest_prefix, \
770 fr_table_ptr_sorted_t const * : fr_table_sorted_ptr_by_longest_prefix, \
771 fr_table_ptr_ordered_t const * : fr_table_ordered_ptr_by_longest_prefix, \
772 fr_table_ptr_sorted_t * : fr_table_sorted_ptr_by_longest_prefix, \
773 fr_table_ptr_ordered_t * : fr_table_ordered_ptr_by_longest_prefix, \
774 fr_table_num_indexed_bit_pos_t * : fr_table_ordered_num_by_longest_prefix, \
775 fr_table_num_indexed_bit_pos_t const * : fr_table_ordered_num_by_longest_prefix, \
776 fr_table_num_indexed_t * : fr_table_ordered_num_by_longest_prefix, \
777 fr_table_num_indexed_t const * : fr_table_ordered_num_by_longest_prefix \
778)(_match_len, _table, _table ## _len, _name, _name_len, _def)
779
780char const *fr_table_ordered_str_by_num(fr_table_num_ordered_t const *table, size_t table_len,
781 int number, char const *def);
782char const *fr_table_sorted_str_by_num(fr_table_num_sorted_t const *table, size_t table_len,
783 int number, char const *def);
784char const *fr_table_ordered_str_by_ptr(fr_table_ptr_ordered_t const *table, size_t table_len,
785 void const *ptr, char const *def);
786char const *fr_table_sorted_str_by_ptr(fr_table_ptr_sorted_t const *table, size_t table_len,
787 void const *ptr, char const *def);
788
789char const *fr_table_indexed_str_by_bit_field(fr_table_num_indexed_bit_pos_t const *table, size_t table_len,
790 uint64_t number, char const *def);
791
792char const *fr_table_indexed_str_by_num(fr_table_num_indexed_t const *table, size_t table_len,
793 unsigned int number, char const *def);
794
795/** Convert an integer to a string
796 *
797 * @param[in] _table to search in.
798 * @param[in] _number to resolve to a string.
799 * @param[in] _def Default string to return if there's no match.
800 * @return
801 * - _def if _number name matched no entries in the table.
802 * - the string value of the matching entry.
803 */
804#define fr_table_str_by_value(_table, _number, _def) \
805_Generic((_table), \
806 fr_table_num_sorted_t const * : fr_table_sorted_str_by_num, \
807 fr_table_num_ordered_t const * : fr_table_ordered_str_by_num, \
808 fr_table_num_sorted_t * : fr_table_sorted_str_by_num, \
809 fr_table_num_ordered_t * : fr_table_ordered_str_by_num, \
810 fr_table_ptr_sorted_t const * : fr_table_sorted_str_by_ptr, \
811 fr_table_ptr_ordered_t const * : fr_table_ordered_str_by_ptr, \
812 fr_table_ptr_sorted_t * : fr_table_sorted_str_by_ptr, \
813 fr_table_ptr_ordered_t * : fr_table_ordered_str_by_ptr, \
814 fr_table_num_indexed_bit_pos_t * : fr_table_indexed_str_by_bit_field, \
815 fr_table_num_indexed_bit_pos_t const * : fr_table_indexed_str_by_bit_field, \
816 fr_table_num_indexed_t * : fr_table_indexed_str_by_num, \
817 fr_table_num_indexed_t const * : fr_table_indexed_str_by_num \
818)(_table, _table ## _len, _number, _def)
819
820#define TABLE_TYPE_NEEDLE_LEN_FUNC(_our_table_type, _our_name) \
821static inline size_t _our_name(_our_table_type table, size_t table_len) \
822{ \
823 size_t i, max = 0; \
824 for (i = 0; i < table_len; i++) if (table[i].name.len > max) max = table[i].name.len; \
825 return max; \
826}
827
828TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_num_sorted_t const *, fr_table_num_sorted_max_needle_len)
829TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_num_ordered_t const *, fr_table_num_ordered_max_needle_len)
830TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_ptr_sorted_t const *, fr_table_ptr_sorted_max_needle_len)
831TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_ptr_ordered_t const *, fr_table_ptr_ordered_max_needle_len)
832TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_num_indexed_bit_pos_t const *, fr_table_num_indexed_bit_pos_max_needle_len)
833TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_num_indexed_t const *, fr_table_num_indexed_max_needle_len)
834
835#define fr_table_max_needle_len(_table) \
836_Generic((_table), \
837 fr_table_num_sorted_t const * : fr_table_num_sorted_max_needle_len, \
838 fr_table_num_ordered_t const * : fr_table_num_ordered_max_needle_len, \
839 fr_table_num_sorted_t * : fr_table_num_sorted_max_needle_len, \
840 fr_table_num_ordered_t * : fr_table_num_ordered_max_needle_len, \
841 fr_table_ptr_sorted_t const * : fr_table_ptr_sorted_max_needle_len, \
842 fr_table_ptr_ordered_t const * : fr_table_ptr_ordered_max_needle_len, \
843 fr_table_ptr_sorted_t * : fr_table_ptr_sorted_max_needle_len, \
844 fr_table_ptr_ordered_t * : fr_table_ptr_ordered_max_needle_len, \
845 fr_table_num_indexed_bit_pos_t * : fr_table_num_indexed_bit_pos_max_needle_len, \
846 fr_table_num_indexed_bit_pos_t const * : fr_table_num_indexed_bit_pos_max_needle_len, \
847 fr_table_num_indexed_t * : fr_table_num_indexed_max_needle_len, \
848 fr_table_num_indexed_t const * : fr_table_num_indexed_max_needle_len \
849)(_table, _table ## _len)
850
851#ifdef __cplusplus
852}
853#endif
#define RCSIDH(h, id)
Definition build.h:513
#define DIAG_OFF(_x)
Definition build.h:486
long int ssize_t
unsigned long int size_t
int strncasecmp(char *s1, char *s2, int n)
Definition missing.c:35
int strcasecmp(char *s1, char *s2)
Definition missing.c:65
static char const * name
void * fr_table_ordered_ptr_by_longest_prefix(size_t *match_len, fr_table_ptr_ordered_t const *table, size_t table_len, char const *name, ssize_t name_len, void const *def)
char const * str
Literal string.
Definition table.h:42
int fr_table_ordered_num_by_substr(fr_table_num_ordered_t const *table, size_t table_len, char const *name, ssize_t name_len, int def)
void * fr_table_sorted_ptr_by_substr(fr_table_ptr_sorted_t const *table, size_t table_len, char const *name, ssize_t name_len, void const *def)
#define ELEM_STR(_offset)
Definition table.h:135
unsigned int value
Definition table.h:94
char const * fr_table_indexed_str_by_bit_field(fr_table_num_indexed_bit_pos_t const *table, size_t table_len, uint64_t number, char const *def)
static void const * table_ordered_value_by_longest_prefix(size_t *match_len, void const *table, size_t table_len, size_t element_size, char const *name, ssize_t name_len)
Find the longest string match using an arbitrarily ordered table.
Definition table.h:600
char const * fr_table_ordered_str_by_ptr(fr_table_ptr_ordered_t const *table, size_t table_len, void const *ptr, char const *def)
char const * fr_table_sorted_str_by_num(fr_table_num_sorted_t const *table, size_t table_len, int number, char const *def)
int fr_table_ordered_num_by_longest_prefix(size_t *match_len, fr_table_num_ordered_t const *table, size_t table_len, char const *name, ssize_t name_len, int def)
void * fr_table_ordered_ptr_by_str(fr_table_ptr_ordered_t const *table, size_t table_len, char const *name, void const *def)
#define TABLE_TYPE_NEEDLE_LEN_FUNC(_our_table_type, _our_name)
Definition table.h:820
static void const * table_ordered_value_by_substr(void const *table, size_t table_len, size_t element_size, char const *name, ssize_t name_len)
Convert a string matching part of name to an integer using an arbitrarily ordered table.
Definition table.h:475
char const * _fr_table_ptr_by_str_value(fr_table_ptr_sorted_t const *table, size_t table_len, char const *str_val, char const *def)
Brute force search a sorted or ordered ptr table, assuming the pointers are strings.
Definition table.c:36
char const * fr_table_sorted_str_by_ptr(fr_table_ptr_sorted_t const *table, size_t table_len, void const *ptr, char const *def)
static void const * table_sorted_value_by_substr(void const *table, size_t table_len, size_t element_size, char const *name, ssize_t name_len)
Convert a string matching part of name to an integer using a lexicographically sorted table.
Definition table.h:427
int fr_table_sorted_num_by_substr(fr_table_num_sorted_t const *table, size_t table_len, char const *name, ssize_t name_len, int def)
fr_table_elem_name_t name
Definition table.h:66
fr_table_elem_name_t name
Definition table.h:93
void const * value
Definition table.h:75
void const * value
Definition table.h:67
static void const * table_ordered_value_by_str(void const *table, size_t table_len, size_t element_size, char const *name)
Convert a string to a value using an arbitrarily ordered table.
Definition table.h:399
fr_table_elem_name_t name
Definition table.h:84
fr_table_elem_name_t name
Definition table.h:74
int fr_table_sorted_num_by_str(fr_table_num_sorted_t const *table, size_t table_len, char const *name, int def)
static void const * table_sorted_value_by_longest_prefix(size_t *match_len, void const *table, size_t table_len, size_t element_size, char const *name, ssize_t name_len)
Find the longest string match using a lexicographically sorted table.
Definition table.h:524
static void const * table_sorted_value_by_str(void const *table, size_t table_len, size_t element_size, char const *name)
Convert a string to a value using a lexicographically sorted table.
Definition table.h:360
int fr_table_ordered_num_by_str(fr_table_num_ordered_t const *table, size_t table_len, char const *name, int def)
#define TABLE_IDX(_table, _idx, _element_size)
Definition table.h:134
void * fr_table_sorted_ptr_by_str(fr_table_ptr_sorted_t const *table, size_t table_len, char const *name, void const *def)
void * fr_table_ordered_ptr_by_substr(fr_table_ptr_ordered_t const *table, size_t table_len, char const *name, ssize_t name_len, void const *def)
fr_table_elem_name_t name
Definition table.h:50
fr_table_elem_name_t name
Definition table.h:58
size_t len
Literal string length.
Definition table.h:43
char const * fr_table_indexed_str_by_num(fr_table_num_indexed_t const *table, size_t table_len, unsigned int number, char const *def)
#define ELEM_LEN(_offset)
Definition table.h:136
void * fr_table_sorted_ptr_by_longest_prefix(size_t *match_len, fr_table_ptr_sorted_t const *table, size_t table_len, char const *name, ssize_t name_len, void const *def)
int fr_table_sorted_num_by_longest_prefix(size_t *match_len, fr_table_num_sorted_t const *table, size_t table_len, char const *name, ssize_t name_len, int def)
char const * fr_table_ordered_str_by_num(fr_table_num_ordered_t const *table, size_t table_len, int number, char const *def)
An element in a table indexed by bit position.
Definition table.h:83
An element in a table indexed by numeric value.
Definition table.h:92
An element in an arbitrarily ordered array of name to num mappings.
Definition table.h:57
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
An element in an arbitrarily ordered array of name to ptr mappings.
Definition table.h:73
An element in a lexicographically sorted array of name to ptr mappings.
Definition table.h:65