The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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  */
27 RCSIDH(table_h, "$Id: 5d94d934fbd9666fabd2f3152c4c4e3a9ffa7829 $")
28 
29 #ifdef __cplusplus
30 extern "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 
39 DIAG_OFF(unused-function)
40 
41 typedef 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  */
49 typedef struct {
51  int value;
53 
54 /** An element in an arbitrarily ordered array of name to num mappings
55  *
56  */
57 typedef struct {
59  int value;
61 
62 /** An element in a lexicographically sorted array of name to ptr mappings
63  *
64  */
65 typedef struct {
67  void const *value;
69 
70 /** An element in an arbitrarily ordered array of name to ptr mappings
71  *
72  */
73 typedef 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  */
83 typedef struct {
85  uint64_t value;
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  */
92 typedef struct {
94  unsigned int value;
96 
97 /** Macro to use as dflt
98  *
99  */
100 #define NAME_NUMBER_NOT_FOUND INT32_MIN
101 
102 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);
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) \
145 bool _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) \
207 bool _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) \
265 bool _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) \
284 char 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) \
298 char 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) \
312 char 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  */
328 static 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  */
367 static 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  */
395 static 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  */
443 static 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  */
492 static 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  */
568 static 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 
632 int fr_table_sorted_num_by_str(fr_table_num_sorted_t const *table, size_t table_len,
633  char const *name, int def);
634 
635 int fr_table_ordered_num_by_str(fr_table_num_ordered_t const *table, size_t table_len,
636  char const *name, int def);
637 
638 void *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 
641 void *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 
669 int 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 
672 int fr_table_ordered_num_by_substr(fr_table_num_ordered_t const *table, size_t table_len,
673  char const *name, ssize_t name_len, int def);
674 
675 void *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 
678 void *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 
709 int 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 
712 int 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 
715 void *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 
718 void *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 
748 char const *fr_table_ordered_str_by_num(fr_table_num_ordered_t const *table, size_t table_len,
749  int number, char const *def);
750 char const *fr_table_sorted_str_by_num(fr_table_num_sorted_t const *table, size_t table_len,
751  int number, char const *def);
752 char 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);
754 char 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 
757 char 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 
760 char 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) \
789 static 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 
796 TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_num_sorted_t const *, fr_table_num_sorted_max_needle_len)
797 TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_num_ordered_t const *, fr_table_num_ordered_max_needle_len)
798 TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_ptr_sorted_t const *, fr_table_ptr_sorted_max_needle_len)
799 TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_ptr_ordered_t const *, fr_table_ptr_ordered_max_needle_len)
800 TABLE_TYPE_NEEDLE_LEN_FUNC(fr_table_num_indexed_bit_pos_t const *, fr_table_num_indexed_bit_pos_max_needle_len)
801 TABLE_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:482
#define DIAG_OFF(_x)
Definition: build.h:455
long int ssize_t
Definition: merged_model.c:24
unsigned long int size_t
Definition: merged_model.c:25
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
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)
#define ELEM_STR(_offset)
Definition: table.h:105
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
unsigned int value
Definition: table.h:94
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)
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)
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)
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
#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
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)
char const * fr_table_ordered_str_by_num(fr_table_num_ordered_t const *table, size_t table_len, int number, char const *def)
void * fr_table_sorted_ptr_by_str(fr_table_ptr_sorted_t const *table, size_t table_len, char const *name, void const *def)
fr_table_elem_name_t name
Definition: table.h:66
fr_table_elem_name_t name
Definition: table.h:93
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)
void const * value
Definition: table.h:75
void const * value
Definition: table.h:67
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)
char const * fr_table_sorted_str_by_num(fr_table_num_sorted_t const *table, size_t table_len, int number, char const *def)
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)
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)
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)
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
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
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
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
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)
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
#define ELEM_LEN(_offset)
Definition: table.h:106
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)
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)
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
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