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: 5d94d934fbd9666fabd2f3152c4c4e3a9ffa7829 $
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: 5d94d934fbd9666fabd2f3152c4c4e3a9ffa7829 $")
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/** Macro to use as dflt
98 *
99 */
100#define NAME_NUMBER_NOT_FOUND INT32_MIN
101
102char 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);
103
104#define TABLE_IDX(_table, _idx, _element_size) (((uint8_t const *)(_table)) + ((_idx) * (_element_size)))
105#define ELEM_STR(_offset) (*((fr_table_elem_name_t const *)(_offset))).str
106#define ELEM_LEN(_offset) (*((fr_table_elem_name_t const *)(_offset))).len
107
108/** Create a type-specific name-to-value function
109 *
110 * @param[in] _func Used for resolving the name portion of an array element to a value.
111 * Should be one of the following:
112 * - table_sorted_value_by_str - for lexicographically sorted tables.
113 * - table_ordered_value_by_str - for arbitrarily ordered tables.
114 * @param[in] _our_table_type C type of the table elements.
115 * @param[in] _our_name name of the search function to define.
116 * @param[in] _our_def_type C type of the default value.
117 * @param[in] _our_return_type C type of the return value, i.e. the value part of the element.
118 */
119#define TABLE_TYPE_NAME_FUNC(_func, _our_table_type, _our_name, _our_def_type, _our_return_type) \
120_our_return_type _our_name(_our_table_type table, size_t table_len, char const *name, _our_def_type def) \
121{ \
122 _our_return_type ret; \
123 _our_table_type found; \
124 found = (_our_table_type)_func(table, table_len, sizeof(((_our_table_type)0)[0]), name); \
125 if (!found) { \
126 memcpy(&ret, &def, sizeof(ret)); \
127 return ret; \
128 } \
129 memcpy(&ret, &found->value, sizeof(ret)); \
130 return ret; \
131}
132
133/** Create a type-specific name-to-value function
134 *
135 * @param[in] _func Used for resolving the name portion of an array element to a value.
136 * Should be one of the following:
137 * - table_sorted_value_by_str - for lexicographically sorted tables.
138 * - table_ordered_value_by_str - for arbitrarily ordered tables.
139 * @param[in] _our_table_type C type of the table elements.
140 * @param[in] _our_name name of the search function to define.
141 * @param[in] _our_def_type C type of the default value.
142 * @param[in] _our_out_type C type of the return/output value, i.e. the value part of the element.
143 */
144#define TABLE_TYPE_NAME_FUNC_RPTR(_func, _our_table_type, _our_name, _our_def_type, _our_out_type) \
145bool _our_name(_our_out_type *out, _our_table_type table, size_t table_len, char const *name, _our_def_type def) \
146{ \
147 _our_table_type found; \
148 found = (_our_table_type)_func(table, table_len, sizeof(((_our_table_type)0)[0]), name); \
149 if (!found) { \
150 *out = def; \
151 return false; \
152 } \
153 *out = &found->value; \
154 return true; \
155}
156
157/** Create a type-specific name-to-value function that can perform substring matching with a 'name_len' argument
158 *
159 * @param[in] _func Used for resolving the name portion of an array element to a value.
160 * Should be one of the following:
161 * - table_sorted_value_by_substr - for lexicographically sorted tables
162 * with partial matching.
163 * - table_ordered_value_by_substr - for arbitrarily ordered tables.
164 * with partial matching.
165 * @param[in] _our_table_type C type of the table elements.
166 * Must contain two fields, an #fr_table_elem_name_t called name
167 * and an arbitraryily typed field called value.
168 * A pointer to thi
169 * @param[in] _our_name name of the search function to define.
170 * @param[in] _our_def_type C type of the default value.
171 * @param[in] _our_return_type C type of the return value, i.e. the value part of the element.
172 */
173#define TABLE_TYPE_NAME_LEN_FUNC(_func, _our_table_type, _our_name, _our_def_type, _our_return_type) \
174_our_return_type _our_name(_our_table_type table, size_t table_len, char const *name, ssize_t name_len, _our_def_type def) \
175{ \
176 _our_return_type ret; \
177 _our_table_type found; \
178 found = (_our_table_type)_func(table, table_len, sizeof(((_our_table_type)0)[0]), name, name_len); \
179 if (!found) { \
180 memcpy(&ret, &def, sizeof(ret)); \
181 return ret; \
182 } \
183 memcpy(&ret, &found->value, sizeof(ret)); \
184 return ret; \
185}
186
187/** Create a type-specific name-to-value function that can perform substring matching with a 'name_len' argument
188 *
189 * @note The functions created by this macro return true on a match, false on no match, and write a
190 * pointer to the value field of the table element to the 'out' argument.
191 *
192 * @param[in] _func Used for resolving the name portion of an array element to a value.
193 * Should be one of the following:
194 * - table_sorted_value_by_substr - for lexicographically sorted tables
195 * with partial matching.
196 * - table_ordered_value_by_substr - for arbitrarily ordered tables.
197 * with partial matching.
198 * @param[in] _our_table_type C type of the table elements.
199 * Must contain two fields, an #fr_table_elem_name_t called name
200 * and an arbitraryily typed field called value.
201 * A pointer to thi
202 * @param[in] _our_name name of the search function to define.
203 * @param[in] _our_def_type C type of the default value.
204 * @param[in] _our_out_type C type of the return/output value, i.e. the value part of the element.
205 */
206#define TABLE_TYPE_NAME_LEN_FUNC_RPTR(_func, _our_table_type, _our_name, _our_def_type, _our_out_type) \
207bool _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) \
208{ \
209 _our_table_type found; \
210 found = (_our_table_type)_func(table, table_len, sizeof(((_our_table_type)0)[0]), name, name_len); \
211 if (!found) { \
212 *out = def; \
213 return false; \
214 } \
215 *out = &found->value; \
216 return true; \
217}
218
219/** 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
220 *
221 * @note The functions created by this macro return the value field of the table element.
222 *
223 * @param[in] _func Used for resolving the name portion of an array element to a value.
224 * Should be one of the following:
225 * - table_sorted_value_by_longest_prefix - for lexicographically sorted tables
226 * with longest prefix match.
227 * - table_ordered_value_by_longest_prefix - for arbitrarily ordered tables
228 * with longest prefix match.
229 * @param[in] _our_table_type C type of the table elements.
230 * @param[in] _our_name name of the search function to define.
231 * @param[in] _our_def_type C type of the default value.
232 * @param[in] _our_return_type C type of the return value, i.e. the value part of the element.
233 */
234#define TABLE_TYPE_NAME_MATCH_LEN_FUNC(_func, _our_table_type, _our_name, _our_def_type, _our_return_type) \
235_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) \
236{ \
237 _our_return_type ret; \
238 _our_table_type found; \
239 found = (_our_table_type)_func(match_len, table, table_len, sizeof(((_our_table_type)0)[0]), name, name_len); \
240 if (!found) { \
241 memcpy(&ret, &def, sizeof(ret)); \
242 return ret; \
243 } \
244 memcpy(&ret, &found->value, sizeof(ret)); \
245 return ret; \
246}
247
248/** 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
249 *
250 * @note The functions created by this macro return true on a match, false on no match, and write a
251 * pointer to the value field of the table element to the 'out' argument.
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_out_type C type of the return/output value, i.e. the value part of the element.
263 */
264#define TABLE_TYPE_NAME_MATCH_LEN_FUNC_RPTR(_func, _our_table_type, _our_name, _our_def_type, _our_out_type) \
265bool _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) \
266{ \
267 _our_table_type found; \
268 found = (_our_table_type)_func(match_len, table, table_len, sizeof(((_our_table_type)0)[0]), name, name_len); \
269 if (!found) { \
270 *out = def; \
271 return false; \
272 } \
273 *out = &found->value; \
274 return true; \
275}
276
277/** Create a type-specific value-to-name function
278 *
279 * @param[in] _our_table_type C type of the table elements.
280 * @param[in] _our_name name of the search function to define.
281 * @param[in] _our_return_type C type of the value field of the table element.
282 */
283#define TABLE_TYPE_VALUE_FUNC(_our_table_type, _our_name, _our_value_type) \
284char const *_our_name(_our_table_type table, size_t table_len, _our_value_type value, char const *def) \
285{ \
286 size_t i; \
287 for (i = 0; i < table_len; i++) if (table[i].value == value) return table[i].name.str; \
288 return def; \
289}
290
291/** Create a type-specific value-to-name function, which uses the highest bit set in the value as an index into the table
292 *
293 * @param[in] _our_table_type C type of the table elements.
294 * @param[in] _our_name name of the search function to define.
295 * @param[in] _our_return_type C type of the value field of the table element.
296 */
297#define TABLE_TYPE_VALUE_INDEX_BIT_FIELD_FUNC(_our_table_type, _our_name, _our_value_type) \
298char const *_our_name(_our_table_type table, size_t table_len, _our_value_type value, char const *def) \
299{ \
300 uint8_t idx = fr_high_bit_pos(value); \
301 if (idx >= table_len) return def; \
302 return table[idx].name.str; \
303}
304
305/** Create a type-specific value-to-name function, which uses the value as an index into the table
306 *
307 * @param[in] _our_table_type C type of the table elements.
308 * @param[in] _our_name name of the search function to define.
309 * @param[in] _our_return_type C type of the value field of the table element.
310 */
311#define TABLE_TYPE_VALUE_INDEX_FUNC(_our_table_type, _our_name, _our_value_type) \
312char const *_our_name(_our_table_type table, size_t table_len, _our_value_type value, char const *def) \
313{ \
314 if (value >= table_len) return def; \
315 return table[value].name.str; \
316}
317
318/** Convert a string to a value using a lexicographically sorted table
319 *
320 * @param[in] table to search in.
321 * @param[in] table_len The number of elements in the table.
322 * @param[in] element_size Size of elements in the table.
323 * @param[in] name to resolve to a value.
324 * @return
325 * - value of matching entry.
326 * - NULL if no matching entries.
327 */
328static void const *table_sorted_value_by_str(void const *table, size_t table_len, size_t element_size,
329 char const *name)
330{
331 ssize_t start = 0;
332 ssize_t end = table_len - 1;
333 ssize_t mid;
334
335 int ret;
336
337 if (!name) return NULL;
338
339 while (start <= end) {
340 void const *offset;
341
342 mid = start + ((end - start) / 2); /* Avoid overflow */
343
344 offset = TABLE_IDX(table, mid, element_size);
345 ret = strcasecmp(name, ELEM_STR(offset));
346 if (ret == 0) return offset;
347 if (ret < 0) {
348 end = mid - 1;
349 } else {
350 start = mid + 1;
351 }
352 }
353
354 return NULL;
355}
356
357/** Convert a string to a value using an arbitrarily ordered table
358 *
359 * @param[in] table to search in.
360 * @param[in] table_len The number of elements in the table.
361 * @param[in] element_size Size of elements in the table.
362 * @param[in] name to resolve to a number.
363 * @return
364 * - value of matching entry.
365 * - NULL if no matching entries.
366 */
367static void const *table_ordered_value_by_str(void const *table, size_t table_len, size_t element_size,
368 char const *name)
369{
370 size_t i;
371
372 if (!name) return NULL;
373
374 for (i = 0; i < table_len; i++) {
375 void const *offset = TABLE_IDX(table, i, element_size);
376 if (strcasecmp(name, ELEM_STR(offset)) == 0) return offset;
377 }
378
379 return NULL;
380}
381
382/** Convert a string matching part of name to an integer using a lexicographically sorted table
383 *
384 * @param[in] table to search in.
385 * @param[in] table_len The number of elements in the table.
386 * @param[in] element_size Size of elements in the table.
387 * @param[in] name to locate.
388 * @param[in] name_len the maximum amount of name that should be matched.
389 * If < 0, the length of the name in the table offsetent
390 * will be used as the maximum match length.
391 * @return
392 * - value of matching entry.
393 * - NULL if no matching entries.
394 */
395static void const *table_sorted_value_by_substr(void const *table, size_t table_len, size_t element_size,
396 char const *name, ssize_t name_len)
397{
398 ssize_t start = 0;
399 ssize_t end = table_len - 1;
400 ssize_t mid;
401
402 int ret;
403
404 if (!name) return NULL;
405
406 while (start <= end) {
407 void const *offset;
408
409 mid = start + ((end - start) / 2); /* Avoid overflow */
410
411 offset = TABLE_IDX(table, mid, element_size);
412
413 /*
414 * Match up to the length of the table entry if len is < 0.
415 */
416 ret = strncasecmp(name, ELEM_STR(offset),
417 (name_len < 0) ? ELEM_LEN(offset) : (size_t)name_len);
418 if (ret == 0) return offset;
419
420 if (ret < 0) {
421 end = mid - 1;
422 } else {
423 start = mid + 1;
424 }
425 }
426
427 return NULL;
428}
429
430/** Convert a string matching part of name to an integer using an arbitrarily ordered table
431 *
432 * @param[in] table to search in.
433 * @param[in] table_len The number of elements in the table.
434 * @param[in] element_size Size of elements in the table.
435 * @param[in] name to locate.
436 * @param[in] name_len the maximum amount of name that should be matched.
437 * If < 0, the length of the name in the table offsetent
438 * will be used as the maximum match length.
439 * @return
440 * - value of matching entry.
441 * - NULL if no matching entries.
442 */
443static void const *table_ordered_value_by_substr(void const *table, size_t table_len, size_t element_size,
444 char const *name, ssize_t name_len)
445{
446 size_t i;
447
448 if (!name) return NULL;
449
450 for (i = 0; i < table_len; i++) {
451 void const *offset;
452 size_t tlen;
453
454 offset = TABLE_IDX(table, i, element_size);
455
456 tlen = ELEM_LEN(offset);
457
458 /*
459 * Don't match "request" to user input "req".
460 */
461 if ((name_len > 0) && (name_len < (int) tlen)) continue;
462
463 /*
464 * Match up to the length of the table entry if len is < 0.
465 */
466 if (strncasecmp(name, ELEM_STR(offset),
467 (name_len < 0) ? tlen : (size_t)name_len) == 0) return offset;
468 }
469
470 return NULL;
471}
472
473/** Find the longest string match using a lexicographically sorted table
474 *
475 * Performs a binary search in the specified table, returning the longest
476 * offsetent which is a prefix of name.
477 *
478 * i.e. given name of "food", and table of f, foo, of - foo would be returned.
479 *
480 * @note The table *MUST* be sorted lexicographically, else the result may be incorrect.
481 *
482 * @param[out] match_len How much of the input string matched.
483 * @param[in] table to search in.
484 * @param[in] table_len The number of elements in the table.
485 * @param[in] element_size Size of elements in the table.
486 * @param[in] name to locate.
487 * @param[in] name_len the maximum amount of name that should be matched.
488 * @return
489 * - num value of matching entry.
490 * - NULL if no matching entries.
491 */
492static void const *table_sorted_value_by_longest_prefix(size_t *match_len,
493 void const *table, size_t table_len, size_t element_size,
494 char const *name, ssize_t name_len)
495{
496 ssize_t start = 0;
497 ssize_t end = table_len - 1;
498 ssize_t mid;
499
500 int ret;
501 void const *found = NULL;
502
503 if (!name) return NULL;
504 if (name_len < 0) name_len = strlen(name);
505
506 while (start <= end) {
507 void const *offset;
508 char const *elem;
509 size_t tlen;
510
511 mid = start + ((end - start) / 2); /* Avoid overflow */
512
513 offset = TABLE_IDX(table, mid, element_size);
514 elem = ELEM_STR(offset);
515 tlen = ELEM_LEN(offset);
516
517 ret = strncasecmp(name, elem, tlen < (size_t)name_len ? tlen : (size_t)name_len);
518 if (ret == 0) {
519 /*
520 * Exact match
521 */
522 if (tlen == (size_t)name_len) {
523 if (match_len) *match_len = tlen;
524 return offset;
525 }
526
527 /*
528 * Partial match.
529 * Name we're searching for is longer.
530 * This might be the longest prefix,
531 * so record it.
532 */
533 if (tlen < (size_t)name_len) {
534 found = offset;
535 if (match_len) *match_len = tlen;
536 ret = 1;
537 } else {
538 ret = -1;
539 }
540 }
541
542 if (ret < 0) {
543 end = mid - 1;
544 } else {
545 start = mid + 1;
546 }
547 }
548
549 if (!found && match_len) *match_len = 0;
550
551 return found;
552}
553
554/** Find the longest string match using an arbitrarily ordered table
555 *
556 * i.e. given name of "food", and table of f, foo, of - foo would be returned.
557 *
558 * @param[out] match_len How much of the input string matched.
559 * @param[in] table to search in.
560 * @param[in] table_len The number of elements in the table.
561 * @param[in] element_size Size of elements in the table.
562 * @param[in] name to locate.
563 * @param[in] name_len the maximum amount of name that should be matched.
564 * @return
565 * - num value of matching entry.
566 * - def if no matching entries.
567 */
568static void const *table_ordered_value_by_longest_prefix(size_t *match_len,
569 void const *table, size_t table_len, size_t element_size,
570 char const *name, ssize_t name_len)
571{
572 size_t i;
573 size_t found_len = 0;
574 void const *found = NULL;
575
576 if (!name) return NULL;
577 if (name_len < 0) name_len = strlen(name);
578
579 for (i = 0; i < table_len; i++) {
580 void const *offset;
581 size_t j;
582
583 offset = TABLE_IDX(table, i, element_size);
584
585 for (j = 0; (j < (size_t)name_len) && (j < ELEM_LEN(offset)) &&
586 (tolower(name[j]) == tolower((ELEM_STR(offset))[j])); j++);
587
588 /*
589 * If we didn't get to the end of the
590 * table string, then continue.
591 */
592 if ((ELEM_STR(offset))[j] != '\0') continue;
593
594 /*
595 * Exact match
596 */
597 if (j == (size_t)name_len) {
598 if (match_len) *match_len = name_len;
599 return offset;
600 }
601
602 /*
603 * Partial match.
604 * Name we're searching for is longer.
605 * This might be the longest prefix,
606 * so record it.
607 */
608 if (j > found_len) {
609 found_len = j;
610 found = offset;
611 }
612 }
613
614 if (match_len) *match_len = found_len;
615
616 return found;
617}
618
619/** Brute force search a sorted or ordered ptr table, assuming the pointers are strings
620 *
621 * @param[in] _table to search in.
622 * @param[in] _str_value to compare against the ptr field.
623 * @param[in] _def default value.
624 */
625#define fr_table_str_by_str_value(_table, _str_value, _def) \
626_Generic((_table), \
627 fr_table_ptr_sorted_t const * : _fr_table_ptr_by_str_value((fr_table_ptr_sorted_t const *)_table, _table ## _len, _str_value, _def), \
628 fr_table_ptr_ordered_t const * : _fr_table_ptr_by_str_value((fr_table_ptr_sorted_t const *)_table, _table ## _len, _str_value, _def), \
629 fr_table_ptr_sorted_t * : _fr_table_ptr_by_str_value((fr_table_ptr_sorted_t const *)_table, _table ## _len, _str_value, _def), \
630 fr_table_ptr_ordered_t * : _fr_table_ptr_by_str_value((fr_table_ptr_sorted_t const *)_table, _table ## _len, _str_value, _def))
631
632int fr_table_sorted_num_by_str(fr_table_num_sorted_t const *table, size_t table_len,
633 char const *name, int def);
634
635int fr_table_ordered_num_by_str(fr_table_num_ordered_t const *table, size_t table_len,
636 char const *name, int def);
637
638void *fr_table_sorted_ptr_by_str(fr_table_ptr_sorted_t const *table, size_t table_len,
639 char const *name, void const *def);
640
641void *fr_table_ordered_ptr_by_str(fr_table_ptr_ordered_t const *table, size_t table_len,
642 char const *name, void const *def);
643
644/** Convert a string to a value using a sorted or ordered table
645 *
646 * @param[in] _table to search in.
647 * @param[in] _name to resolve to a number.
648 * @param[in] _def Default value if no entry matched.
649 * @return
650 * - _def if name matched no entries in the table.
651 * - the numeric value of the matching entry.
652 */
653#define fr_table_value_by_str(_table, _name, _def) \
654_Generic((_table), \
655 fr_table_num_sorted_t const * : fr_table_sorted_num_by_str, \
656 fr_table_num_ordered_t const * : fr_table_ordered_num_by_str, \
657 fr_table_num_sorted_t * : fr_table_sorted_num_by_str, \
658 fr_table_num_ordered_t * : fr_table_ordered_num_by_str, \
659 fr_table_ptr_sorted_t const * : fr_table_sorted_ptr_by_str, \
660 fr_table_ptr_ordered_t const * : fr_table_ordered_ptr_by_str, \
661 fr_table_ptr_sorted_t * : fr_table_sorted_ptr_by_str, \
662 fr_table_ptr_ordered_t * : fr_table_ordered_ptr_by_str, \
663 fr_table_num_indexed_bit_pos_t * : fr_table_ordered_num_by_str, \
664 fr_table_num_indexed_bit_pos_t const * : fr_table_ordered_num_by_str, \
665 fr_table_num_indexed_t * : fr_table_ordered_num_by_str, \
666 fr_table_num_indexed_t const * : fr_table_ordered_num_by_str \
667)(_table, _table ## _len, _name, _def)
668
669int fr_table_sorted_num_by_substr(fr_table_num_sorted_t const *table, size_t table_len,
670 char const *name, ssize_t name_len, int def);
671
673 char const *name, ssize_t name_len, int def);
674
675void *fr_table_sorted_ptr_by_substr(fr_table_ptr_sorted_t const *table, size_t table_len,
676 char const *name, ssize_t name_len, void const *def);
677
678void *fr_table_ordered_ptr_by_substr(fr_table_ptr_ordered_t const *table, size_t table_len,
679 char const *name, ssize_t name_len, void const *def);
680
681/** Convert a partial string to a value using an ordered or sorted table
682 *
683 * @param[in] _table to search in.
684 * @param[in] _name to resolve to a number.
685 * @param[in] _name_len The amount of name to match.
686 * If < 0, the length of the name in the table element
687 * will be used as the maximum match length.
688 * @param[in] _def Default value if no entry matched.
689 * @return
690 * - _def if name matched no entries in the table.
691 * - the numeric value of the matching entry.
692 */
693#define fr_table_value_by_substr(_table, _name, _name_len, _def) \
694_Generic((_table), \
695 fr_table_num_sorted_t const * : fr_table_sorted_num_by_substr, \
696 fr_table_num_ordered_t const * : fr_table_ordered_num_by_substr, \
697 fr_table_num_sorted_t * : fr_table_sorted_num_by_substr, \
698 fr_table_num_ordered_t * : fr_table_ordered_num_by_substr, \
699 fr_table_ptr_sorted_t const * : fr_table_sorted_ptr_by_substr, \
700 fr_table_ptr_ordered_t const * : fr_table_ordered_ptr_by_substr, \
701 fr_table_ptr_sorted_t * : fr_table_sorted_ptr_by_substr, \
702 fr_table_ptr_ordered_t * : fr_table_ordered_ptr_by_substr, \
703 fr_table_num_indexed_bit_pos_t * : fr_table_ordered_num_by_substr, \
704 fr_table_num_indexed_bit_pos_t const * : fr_table_ordered_num_by_substr, \
705 fr_table_num_indexed_t * : fr_table_ordered_num_by_substr, \
706 fr_table_num_indexed_t const * : fr_table_ordered_num_by_substr \
707)(_table, _table ## _len, _name, _name_len, _def)
708
709int fr_table_sorted_num_by_longest_prefix(size_t *match_len, fr_table_num_sorted_t const *table, size_t table_len,
710 char const *name, ssize_t name_len, int def);
711
712int fr_table_ordered_num_by_longest_prefix(size_t *match_len, fr_table_num_ordered_t const *table, size_t table_len,
713 char const *name, ssize_t name_len, int def);
714
715void *fr_table_sorted_ptr_by_longest_prefix(size_t *match_len, fr_table_ptr_sorted_t const *table, size_t table_len,
716 char const *name, ssize_t name_len, void const *def);
717
718void *fr_table_ordered_ptr_by_longest_prefix(size_t *match_len, fr_table_ptr_ordered_t const *table, size_t table_len,
719 char const *name, ssize_t name_len, void const *def);
720
721/** Find the longest string match using a sorted or ordered table
722 *
723 * @param[out] _match_len How much of the input string matched.
724 * @param[in] _table to search in.
725 * @param[in] _name to resolve to a number.
726 * @param[in] _name_len The amount of name to match.
727 * @param[in] _def Default value if no entry matched.
728 * @return
729 * - _def if name matched no entries in the table.
730 * - the value of the matching entry.
731 */
732#define fr_table_value_by_longest_prefix(_match_len, _table, _name, _name_len, _def) \
733_Generic((_table), \
734 fr_table_num_sorted_t const * : fr_table_sorted_num_by_longest_prefix, \
735 fr_table_num_ordered_t const * : fr_table_ordered_num_by_longest_prefix, \
736 fr_table_num_sorted_t * : fr_table_sorted_num_by_longest_prefix, \
737 fr_table_num_ordered_t * : fr_table_ordered_num_by_longest_prefix, \
738 fr_table_ptr_sorted_t const * : fr_table_sorted_ptr_by_longest_prefix, \
739 fr_table_ptr_ordered_t const * : fr_table_ordered_ptr_by_longest_prefix, \
740 fr_table_ptr_sorted_t * : fr_table_sorted_ptr_by_longest_prefix, \
741 fr_table_ptr_ordered_t * : fr_table_ordered_ptr_by_longest_prefix, \
742 fr_table_num_indexed_bit_pos_t * : fr_table_ordered_num_by_longest_prefix, \
743 fr_table_num_indexed_bit_pos_t const * : fr_table_ordered_num_by_longest_prefix, \
744 fr_table_num_indexed_t * : fr_table_ordered_num_by_longest_prefix, \
745 fr_table_num_indexed_t const * : fr_table_ordered_num_by_longest_prefix \
746)(_match_len, _table, _table ## _len, _name, _name_len, _def)
747
748char const *fr_table_ordered_str_by_num(fr_table_num_ordered_t const *table, size_t table_len,
749 int number, char const *def);
750char const *fr_table_sorted_str_by_num(fr_table_num_sorted_t const *table, size_t table_len,
751 int number, char const *def);
752char const *fr_table_ordered_str_by_ptr(fr_table_ptr_ordered_t const *table, size_t table_len,
753 void const *ptr, char const *def);
754char const *fr_table_sorted_str_by_ptr(fr_table_ptr_sorted_t const *table, size_t table_len,
755 void const *ptr, char const *def);
756
757char const *fr_table_indexed_str_by_bit_field(fr_table_num_indexed_bit_pos_t const *table, size_t table_len,
758 uint64_t number, char const *def);
759
760char const *fr_table_indexed_str_by_num(fr_table_num_indexed_t const *table, size_t table_len,
761 unsigned int number, char const *def);
762
763/** Convert an integer to a string
764 *
765 * @param[in] _table to search in.
766 * @param[in] _number to resolve to a string.
767 * @param[in] _def Default string to return if there's no match.
768 * @return
769 * - _def if _number name matched no entries in the table.
770 * - the string value of the matching entry.
771 */
772#define fr_table_str_by_value(_table, _number, _def) \
773_Generic((_table), \
774 fr_table_num_sorted_t const * : fr_table_sorted_str_by_num, \
775 fr_table_num_ordered_t const * : fr_table_ordered_str_by_num, \
776 fr_table_num_sorted_t * : fr_table_sorted_str_by_num, \
777 fr_table_num_ordered_t * : fr_table_ordered_str_by_num, \
778 fr_table_ptr_sorted_t const * : fr_table_sorted_str_by_ptr, \
779 fr_table_ptr_ordered_t const * : fr_table_ordered_str_by_ptr, \
780 fr_table_ptr_sorted_t * : fr_table_sorted_str_by_ptr, \
781 fr_table_ptr_ordered_t * : fr_table_ordered_str_by_ptr, \
782 fr_table_num_indexed_bit_pos_t * : fr_table_indexed_str_by_bit_field, \
783 fr_table_num_indexed_bit_pos_t const * : fr_table_indexed_str_by_bit_field, \
784 fr_table_num_indexed_t * : fr_table_indexed_str_by_num, \
785 fr_table_num_indexed_t const * : fr_table_indexed_str_by_num \
786)(_table, _table ## _len, _number, _def)
787
788#define TABLE_TYPE_NEEDLE_LEN_FUNC(_our_table_type, _our_name) \
789static inline size_t _our_name(_our_table_type table, size_t table_len) \
790{ \
791 size_t i, max = 0; \
792 for (i = 0; i < table_len; i++) if (table->name.len > max) max = table->name.len; \
793 return max; \
794}
795
796TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_num_sorted_t const *, fr_table_num_sorted_max_needle_len)
797TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_num_ordered_t const *, fr_table_num_ordered_max_needle_len)
798TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_ptr_sorted_t const *, fr_table_ptr_sorted_max_needle_len)
799TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_ptr_ordered_t const *, fr_table_ptr_ordered_max_needle_len)
800TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_num_indexed_bit_pos_t const *, fr_table_num_indexed_bit_pos_max_needle_len)
801TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_num_indexed_t const *, fr_table_num_indexed_max_needle_len)
802
803#define fr_table_max_needle_len(_table) \
804_Generic((_table), \
805 fr_table_num_sorted_t const * : fr_table_num_sorted_max_needle_len, \
806 fr_table_num_ordered_t const * : fr_table_num_ordered_max_needle_len, \
807 fr_table_num_sorted_t * : fr_table_num_sorted_max_needle_len, \
808 fr_table_num_ordered_t * : fr_table_num_ordered_max_needle_len, \
809 fr_table_ptr_sorted_t const * : fr_table_ptr_sorted_max_needle_len, \
810 fr_table_ptr_ordered_t const * : fr_table_ptr_ordered_max_needle_len, \
811 fr_table_ptr_sorted_t * : fr_table_ptr_sorted_max_needle_len, \
812 fr_table_ptr_ordered_t * : fr_table_ptr_ordered_max_needle_len, \
813 fr_table_num_indexed_bit_pos_t * : fr_table_num_indexed_bit_pos_max_needle_len, \
814 fr_table_num_indexed_bit_pos_t const * : fr_table_num_indexed_bit_pos_max_needle_len, \
815 fr_table_num_indexed_t * : fr_table_num_indexed_max_needle_len, \
816 fr_table_num_indexed_t const * : fr_table_num_indexed_max_needle_len \
817)(_table, _table ## _len)
818
819#ifdef __cplusplus
820}
821#endif
#define RCSIDH(h, id)
Definition build.h:484
#define DIAG_OFF(_x)
Definition build.h:457
long int ssize_t
unsigned long int size_t
int strncasecmp(char *s1, char *s2, int n)
Definition missing.c:36
int strcasecmp(char *s1, char *s2)
Definition missing.c:66
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:105
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:568
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:788
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:443
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:395
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:367
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:492
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:328
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:104
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:106
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