From: Arran Cudbard-Bell Date: Wed, 14 Aug 2019 21:28:44 +0000 (-0400) Subject: Efficient table lookups, phase 2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8d3ea334213dfb52fdbcde5b37e655e985c4095f;p=thirdparty%2Ffreeradius-server.git Efficient table lookups, phase 2 --- diff --git a/src/lib/eap/tls.h b/src/lib/eap/tls.h index d671e6f0b3a..6e26b68229c 100644 --- a/src/lib/eap/tls.h +++ b/src/lib/eap/tls.h @@ -148,7 +148,7 @@ typedef struct { size_t record_in_recvd_len; //!< How much of the record we've received so far. } eap_tls_session_t; -extern fr_table_t const eap_tls_status_table[]; +extern fr_table_ordered_t const eap_tls_status_table[]; extern size_t eap_tls_status_table_len; /* diff --git a/src/lib/server/tmpl.h b/src/lib/server/tmpl.h index 4d62c272a12..b25b98c768c 100644 --- a/src/lib/server/tmpl.h +++ b/src/lib/server/tmpl.h @@ -94,7 +94,7 @@ typedef enum pair_list_e { PAIR_LIST_UNKNOWN //!< Unknown list. } pair_list_t; -extern fr_table_t const pair_list_table[]; +extern fr_table_ordered_t const pair_list_table[]; extern size_t pair_list_table_len; typedef enum requests_ref_e { diff --git a/src/lib/server/xlat_func.c b/src/lib/server/xlat_func.c index 0332eabf1d4..bfefa1c6aa0 100644 --- a/src/lib/server/xlat_func.c +++ b/src/lib/server/xlat_func.c @@ -465,8 +465,8 @@ static ssize_t xlat_func_debug_attr(UNUSED TALLOC_CTX *ctx, UNUSED char **out, U for (vp = tmpl_cursor_init(NULL, &cursor, request, vpt); vp; vp = fr_cursor_next(&cursor)) { - fr_dict_vendor_t const *vendor; - fr_table_t const *type; + fr_dict_vendor_t const *vendor; + fr_table_ordered_t const *type; if (vp->da->flags.has_tag) { RIDEBUG2("&%s:%s:%i %s %pV", diff --git a/src/lib/unlang/interpret.c b/src/lib/unlang/interpret.c index 6af5b50af86..0e89fae5cdc 100644 --- a/src/lib/unlang/interpret.c +++ b/src/lib/unlang/interpret.c @@ -33,7 +33,7 @@ RCSID("$Id$") #include "parallel_priv.h" #include "module_priv.h" -static fr_table_t unlang_action_table[] = { +static fr_table_t const unlang_action_table[] = { { "break", UNLANG_ACTION_BREAK }, { "calculate-result", UNLANG_ACTION_CALCULATE_RESULT }, { "next", UNLANG_ACTION_EXECUTE_NEXT }, diff --git a/src/lib/util/dict.c b/src/lib/util/dict.c index 6d764f0ab05..0fddcabe138 100644 --- a/src/lib/util/dict.c +++ b/src/lib/util/dict.c @@ -5615,8 +5615,8 @@ int fr_dict_internal_afrom_file(fr_dict_t **out, char const *dict_subdir) * that function does too many checks. */ for (i = 0; i < fr_value_box_type_table_len; i++) { - fr_dict_attr_t *n; - fr_table_t const *p = &fr_value_box_type_table[i]; + fr_dict_attr_t *n; + fr_table_ordered_t const *p = &fr_value_box_type_table[i]; type_name = talloc_typed_asprintf(NULL, "Tmp-Cast-%s", p->name); diff --git a/src/lib/util/log.h b/src/lib/util/log.h index 6f88204b51d..7309e18ec20 100644 --- a/src/lib/util/log.h +++ b/src/lib/util/log.h @@ -46,7 +46,7 @@ void fr_canonicalize_error(TALLOC_CTX *ctx, char **spaces, char **text, ssize_t extern int fr_debug_lvl; /* 0 = no debugging information */ extern bool log_dates_utc; -extern fr_table_t const fr_log_levels[]; +extern fr_table_ordered_t const fr_log_levels[]; extern size_t fr_log_levels_len; typedef enum { diff --git a/src/lib/util/table.c b/src/lib/util/table.c index 5d4eb227547..59aa951c855 100644 --- a/src/lib/util/table.c +++ b/src/lib/util/table.c @@ -27,31 +27,108 @@ RCSID("$Id$") #include -/** Convert a string to an integer + +/** Convert a string to an integer using a lexicographically sorted table + * + * @param[in] table to search in. + * @param[in] table_len The number of elements in the table. + * @param[in] name to resolve to a number. + * @param[in] def Default value if no entry matched. + * @return + * - num value of matching entry. + * - def if no matching entries. + */ +int fr_table_sorted_num_by_str(fr_table_t const *table, size_t table_len, + char const *name, int def) +{ + ssize_t start = 0; + ssize_t end = table_len - 1; + ssize_t mid; + + int ret; + + if (!name) return def; + + while (start <= end) { + mid = start + ((end - start) / 2); /* Avoid overflow */ + + ret = strcasecmp(name, table[mid].name); + if (ret == 0) return table[mid].number; + + if (ret < 0) { + end = mid - 1; + } else { + start = mid + 1; + } + } + + return def; +} + +/** Convert a string to an integer using an arbitrarily ordered table + * + * @param[in] table to search in. + * @param[in] table_len The number of elements in the table. + * @param[in] name to resolve to a number. + * @param[in] def Default value if no entry matched. + * @return + * - num value of matching entry. + * - def if no matching entries. + */ +int fr_table_ordered_num_by_str(fr_table_ordered_t const *table, size_t table_len, + char const *name, int def) +{ + size_t i; + + if (!name) return def; + + for (i = 0; i < table_len; i++) if (strcasecmp(name, table[i].name) == 0) return table[i].number; + + return def; +} + +/** Convert a string matching part of name to an integer using a lexicographically sorted table * * @param[in] table to search in. * @param[in] table_len The number of elements in the table. * @param[in] name to locate. + * @param[in] name_len the maximum amount of name that should be matched. * @param[in] def Value to return if there are no matches. * @return * - num value of matching entry. * - def if no matching entries. */ -int _fr_table_num_by_str(fr_table_t const *table, size_t table_len, - char const *name, int def) +int fr_table_sorted_num_by_substr(fr_table_t const *table, size_t table_len, + char const *name, size_t name_len, int def) { - size_t i; + ssize_t start = 0; + ssize_t end = table_len - 1; + ssize_t mid; + + int ret; if (!name) return def; - for (i = 0; i < table_len; i++) { - if (strcasecmp(table[i].name, name) == 0) return table[i].number; + while (start <= end) { + mid = start + ((end - start) / 2); /* Avoid overflow */ + + /* + * Match up to the length of the table entry if len is < 0. + */ + ret = strncasecmp(name, table[mid].name, (name_len < 0) ? strlen(table[mid].name) : name_len); + if (ret == 0) return table[mid].number; + + if (ret < 0) { + end = mid - 1; + } else { + start = mid + 1; + } } return def; } -/** Convert a string matching part of name to an integer +/** Convert a string matching part of name to an integer using an arbitrarily ordered table * * @param[in] table to search in. * @param[in] table_len The number of elements in the table. @@ -62,11 +139,10 @@ int _fr_table_num_by_str(fr_table_t const *table, size_t table_len, * - num value of matching entry. * - def if no matching entries. */ -int _fr_table_num_by_substr(fr_table_t const *table, size_t table_len, - char const *name, ssize_t name_len, int def) +int fr_table_ordered_num_by_substr(fr_table_ordered_t const *table, size_t table_len, + char const *name, ssize_t name_len, int def) { size_t i; - size_t max; if (!name) return def; @@ -83,9 +159,7 @@ int _fr_table_num_by_substr(fr_table_t const *table, size_t table_len, /* * Match up to the length of the table entry if len is < 0. */ - max = (name_len < 0) ? tlen : (unsigned)name_len; - - if (strncasecmp(table[i].name, name, max) == 0) return table[i].number; + if (strncasecmp(name, table[i].name, (name_len < 0) ? tlen : name_len) == 0) return table[i].number; } return def; @@ -109,20 +183,22 @@ int _fr_table_num_by_substr(fr_table_t const *table, size_t table_len, * - num value of matching entry. * - def if no matching entries. */ -int _fr_table_lex_num_by_longest_prefix(fr_table_t const *table, size_t table_len, +int _fr_table_sorted_num_by_longest_prefix(fr_table_t const *table, size_t table_len, char const *name, size_t name_len, int def) { - size_t start = 0; - size_t end = table_len - 1; - size_t mid; + ssize_t start = 0; + ssize_t end = table_len - 1; + ssize_t mid; int ret; int num = def; + if (!name) return def; + while (start <= end) { mid = start + ((end - start) / 2); /* Avoid overflow */ - ret = strncasecmp(table[mid].name, name, name_len); + ret = strncasecmp(name, table[mid].name, name_len); if (ret == 0) { size_t tlen; @@ -155,42 +231,6 @@ int _fr_table_lex_num_by_longest_prefix(fr_table_t const *table, size_t table_le return num; } -/** Efficient string lookup in lexicographically sorted fr_table_t table - * - * @param[in] table to search in. - * @param[in] table_len The number of elements in the table. - * @param[in] name to locate. - * @param[in] name_len the maximum amount of name that should be matched. - * @param[in] def Value to return if there are no matches. - * @return - * - num value of matching entry. - * - def if no matching entries. - */ -int _fr_table_lex_num_by_str(fr_table_t const *table, size_t table_len, - char const *name, size_t name_len, int def) -{ - size_t start = 0; - size_t end = table_len - 1; - size_t mid; - - int ret; - - while (start <= end) { - mid = start + ((end - start) / 2); /* Avoid overflow */ - - ret = strncasecmp(table[mid].name, name, name_len); - if (ret == 0) return table[mid].number; - - if (ret < 0) { - end = mid - 1; - } else { - start = mid + 1; - } - } - - return def; -} - /** Convert an integer to a string * * @param[in] table to search in. @@ -201,7 +241,7 @@ int _fr_table_lex_num_by_str(fr_table_t const *table, size_t table_len, * - string value of matching entry. * - def if no matching entries. */ -char const *_fr_table_str_by_num(fr_table_t const *table, size_t table_len, +char const *_fr_table_str_by_num(fr_table_ordered_t const *table, size_t table_len, int number, char const *def) { size_t i; diff --git a/src/lib/util/table.h b/src/lib/util/table.h index 732913934ed..d0fffc00d54 100644 --- a/src/lib/util/table.h +++ b/src/lib/util/table.h @@ -34,69 +34,100 @@ extern "C" { #include #include -struct fr_table_s { +typedef struct { char const *name; int32_t number; -}; +} fr_table_t; -typedef struct fr_table_s fr_table_t; -typedef struct fr_table_s fr_table_ordered_t; +typedef struct { + char const *name; + int32_t number; +} fr_table_ordered_t; /** Macro to use as dflt * */ #define NAME_NUMBER_NOT_FOUND INT32_MIN -int _fr_table_num_by_str(fr_table_t const *table, size_t table_len, - char const *name, int def); - -int _fr_table_num_by_substr(fr_table_t const *table, size_t table_len, - char const *name, ssize_t name_len, int def); - -int _fr_table_lex_num_by_longest_prefix(fr_table_t const *table, size_t table_len, - char const *name, size_t name_len, int def); - -int _fr_table_lex_num_by_str(fr_table_t const *table, size_t table_len, - char const *name, size_t name_len, int def); -char const *_fr_table_str_by_num(fr_table_t const *table, size_t table_len, - int number, char const *def); +int fr_table_sorted_num_by_str(fr_table_t const *table, size_t table_len, + char const *name, int def); +int fr_table_ordered_num_by_str(fr_table_ordered_t const *table, size_t table_len, + char const *name, int def); -/** Convert a string to an integer +/** Convert a string to an integer using a sorted or ordered table * - * @copybrief _fr_table_num_by_str + * @param[in] _table to search in. + * @param[in] _name to resolve to a number. + * @param[in] _def Default value if no entry matched. + * @return + * - _def if name matched no entries in the table. + * - the numeric value of the matching entry. */ -#define fr_table_num_by_str(_table, _name, _def) \ - _fr_table_num_by_str(_table, _table ## _len, _name, _def) +#define fr_table_num_by_str(_table, _name, _def) \ +_Generic((_table), \ + fr_table_t const * : fr_table_sorted_num_by_str, \ + fr_table_ordered_t const * : fr_table_ordered_num_by_str, \ + fr_table_t * : fr_table_sorted_num_by_str, \ + fr_table_ordered_t * : fr_table_ordered_num_by_str \ +)(_table, _table ## _len, _name, _def) + +int fr_table_sorted_num_by_substr(fr_table_t const *table, size_t table_len, + char const *name, size_t name_len, int def); -/** Convert a string matching part of name to an integer +int fr_table_ordered_num_by_substr(fr_table_ordered_t const *table, size_t table_len, + char const *name, ssize_t name_len, int def); + +/** Convert a partial string to an integer using an ordered or sorted table * - * @copybrief _fr_table_num_by_substr + * @param[in] _table to search in. + * @param[in] _name to resolve to a number. + * @param[in] _name_len The amount of name to match. + * @param[in] _def Default value if no entry matched. + * @return + * - _def if name matched no entries in the table. + * - the numeric value of the matching entry. */ -#define fr_table_num_by_substr(_table, _name, _name_len, _def) \ - _fr_table_num_by_substr(_table, _table ## _len, _name, _name_len, _def) +#define fr_table_num_by_substr(_table, _name, _name_len, _def) \ +_Generic((_table), \ + fr_table_t const * : fr_table_sorted_num_by_substr, \ + fr_table_ordered_t const * : fr_table_ordered_num_by_substr, \ + fr_table_t * : fr_table_sorted_num_by_substr, \ + fr_table_ordered_t * : fr_table_ordered_num_by_substr \ +)(_table, _table ## _len, _name, _name_len, _def) + +int _fr_table_sorted_num_by_longest_prefix(fr_table_t const *table, size_t table_len, + char const *name, size_t name_len, int def); /** Find the longest string match in a lexicographically sorted fr_table_t table * - * @copybrief _fr_table_lex_num_by_longest_prefix + * @copybrief _fr_table_sorted_num_by_longest_prefix */ -#define fr_table_lex_num_by_longest_prefix(_table, _name, _name_len, _def) \ - _fr_table_lex_num_by_longest_prefix(_table, _table ## _len, _name, _name_len, _def) +#define fr_table_sorted_num_by_longest_prefix(_table, _name, _name_len, _def) \ + _fr_table_sorted_num_by_longest_prefix(_table, , _name, _name_len, _def) -/** Efficient string lookup in lexicographically sorted fr_table_t table - * - * @copybrief _fr_table_lex_num_by_str - */ -#define fr_table_lex_num_by_str(_table, _name, _name_len, _def) \ - _fr_table_lex_num_by_str(_table, _table ## _len, _name, _name_len, _def) + +char const *_fr_table_str_by_num(fr_table_ordered_t const *table, size_t table_len, + int number, char const *def); /** Convert an integer to a string * - * @copybrief _fr_table_str_from_int + * @param[in] _table to search in. + * @param[in] _number to resolve to a string. + * @param[in] _def Default string to return if there's no match. + * @return + * - _def if _number name matched no entries in the table. + * - the string value of the matching entry. */ -#define fr_table_str_by_num(_table, _number, _def) \ - _fr_table_str_by_num(_table, _table ## _len, _number, _def) +#define fr_table_str_by_num(_table, _number, _def) \ +_Generic((_table), \ + fr_table_t const * : _fr_table_str_by_num, \ + fr_table_ordered_t const * : _fr_table_str_by_num, \ + fr_table_t * : _fr_table_str_by_num, \ + fr_table_ordered_t * : _fr_table_str_by_num \ +)((fr_table_ordered_t const *)_table, _table ## _len, _number, _def) + #ifdef __cplusplus } #endif diff --git a/src/lib/util/token.c b/src/lib/util/token.c index 4a921fc2e37..7eb0eb72107 100644 --- a/src/lib/util/token.c +++ b/src/lib/util/token.c @@ -254,7 +254,7 @@ const bool fr_str_tok[] = { * Returns 0 or special token value. */ static FR_TOKEN getthing(char const **ptr, char *buf, int buflen, bool tok, - fr_table_t const *tokenlist, size_t tokenlist_len, bool unescape) + fr_table_ordered_t const *tokenlist, size_t tokenlist_len, bool unescape) { char *s; char const *p; diff --git a/src/lib/util/token.h b/src/lib/util/token.h index 53d67af6676..899a6c5c14e 100644 --- a/src/lib/util/token.h +++ b/src/lib/util/token.h @@ -76,7 +76,7 @@ typedef enum fr_token { */ #define FR_TABLE_NOT_FOUND INT32_MIN -extern fr_table_t const fr_tokens_table[]; +extern fr_table_ordered_t const fr_tokens_table[]; extern size_t fr_tokens_table_len; extern fr_table_t const fr_token_quotes_table[]; extern size_t fr_token_quotes_table_len; diff --git a/src/lib/util/value.h b/src/lib/util/value.h index a1bed7ec2e5..57f9d1781e4 100644 --- a/src/lib/util/value.h +++ b/src/lib/util/value.h @@ -51,7 +51,7 @@ typedef struct value_box fr_value_box_t; extern "C" { #endif -extern fr_table_t const fr_value_box_type_table[]; +extern fr_table_ordered_t const fr_value_box_type_table[]; extern size_t fr_value_box_type_table_len; extern size_t const fr_value_box_field_sizes[];