From: Arran Cudbard-Bell Date: Sat, 23 Jan 2021 12:12:10 +0000 (+0000) Subject: Move type functions into a separate source file X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c4fad31304d0712dfec071e3087deff6bea37fb4;p=thirdparty%2Ffreeradius-server.git Move type functions into a separate source file --- diff --git a/src/lib/util/types.c b/src/lib/util/types.c new file mode 100644 index 00000000000..e050906931e --- /dev/null +++ b/src/lib/util/types.c @@ -0,0 +1,436 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** Boxed value structures and functions to manipulate them + * + * @file src/lib/util/types.c + * + * @copyright 2021 The FreeRADIUS server project + */ +RCSID("$Id$") + +#include + +#define O(_x) [FR_TYPE_ ## _x] = true + +/* + * Can we promote [src][dst] -> dst + * dst is not octets / string + * src and dst are both FR_TYPE_VALUE + */ +static const bool type_cast_table[FR_TYPE_MAX][FR_TYPE_MAX] = { + [FR_TYPE_IPV4_ADDR] = { + O(IPV4_PREFIX), + O(IPV6_ADDR), + O(IPV6_PREFIX), + O(UINT32), /* ipv4 addresses are uint32 */ + }, + [FR_TYPE_IPV4_PREFIX] = { + O(IPV4_ADDR), /* if the prefix is /32 */ + O(IPV6_ADDR), + O(IPV6_PREFIX), + }, + [FR_TYPE_IPV6_ADDR] = { + O(IPV6_PREFIX), + }, + [FR_TYPE_IPV6_PREFIX] = { + O(IPV6_ADDR), /* if the prefix is /128 */ + }, + + [FR_TYPE_ETHERNET] = { + O(UINT64), + }, + + [FR_TYPE_UINT64] = { + O(ETHERNET), + }, + + [FR_TYPE_DATE] = { /* in 2021, dates always have values 2^31 or more */ + O(UINT32), + O(UINT64), + O(INT32), + O(INT64), + O(SIZE), + O(FLOAT32), + O(FLOAT64), + O(TIME_DELTA), + }, + + [FR_TYPE_TIME_DELTA] = { + O(DATE), + }, + + [FR_TYPE_UINT32] = { + O(IPV4_ADDR), + }, + +}; + +/* + * This is different from FR_TYPE_NUMERIC, largely in that it + * doesn't include FR_TYPE_DATE. Because we know that dates + * always have values 2^31 or greater, so casts exclude some of + * the smaller integer types. + */ +static const bool type_is_number[FR_TYPE_MAX] = { + O(BOOL), O(SIZE), O(FLOAT32), O(FLOAT64), + O(UINT8), O(UINT16), O(UINT32), O(UINT64), + O(INT8), O(INT16), O(INT32), O(INT64), + O(TIME_DELTA), +}; + +/** Return if we're allowed to cast the types. + * + * @param dst the destination type we wish to cast to + * @param src the source type we wish to cast to + * + */ +bool fr_type_cast(fr_type_t dst, fr_type_t src) +{ + /* + * Invalid casts. + */ + switch (dst) { + case FR_TYPE_NON_VALUES: + return false; + + default: + break; + } + + switch (src) { + case FR_TYPE_NON_VALUES: + return false; + + default: + break; + } + + if (src == dst) return true; + + /* + * Anything can be converted to octets or strings. + */ + if (dst == FR_TYPE_OCTETS) return true; + if (dst == FR_TYPE_STRING) return true; + + /* + * Strings and octets can be converted to anything. We + * do run-time checks on the values to see if they fit. + */ + if (src == FR_TYPE_OCTETS) return true; + if (src == FR_TYPE_STRING) return true; + + /* + * Any integer-style thing can be cast to any other + * integer-style thing. Mostly. We do run-time checks + * on values to see if they fit. + */ + if (type_is_number[src] && type_is_number[dst]) { + return true; + } + + /* + * That takes care of the simple cases. :( Now to the + * complex ones. Instead of masses of if / then / else, + * we just use a lookup table. + */ + return type_cast_table[src][dst]; +} + +#undef O +#define O(_x) [FR_TYPE_ ## _x] = FR_TYPE_ ## _x + +/** promote (a,b) -> a or b + * a/b are not octets / string + * a and b are both FR_TYPE_VALUE + * + * Note that this table can return a type which is _not_ a or b. + * + * Many lookups of table[a][b] will return b. Some will return a. + * Others will return a type which is compatible with both a and b. + */ +static fr_type_t type_promote_table[FR_TYPE_MAX][FR_TYPE_MAX] = { + [FR_TYPE_IPV4_ADDR] = { + O(IPV4_PREFIX), + O(IPV6_ADDR), + O(IPV6_PREFIX), + [FR_TYPE_UINT32] = FR_TYPE_IPV4_ADDR, + }, + + [FR_TYPE_IPV4_PREFIX] = { + [FR_TYPE_IPV4_ADDR] = FR_TYPE_IPV4_PREFIX, + O(IPV4_PREFIX), + [FR_TYPE_IPV6_ADDR] = FR_TYPE_IPV6_PREFIX, + O(IPV6_PREFIX), + }, + + [FR_TYPE_IPV6_ADDR] = { + O(IPV6_PREFIX), + }, + + [FR_TYPE_IPV6_PREFIX] = { + [FR_TYPE_IPV6_ADDR] = FR_TYPE_IPV6_PREFIX, + }, + + /* unsigned integers */ + + [FR_TYPE_BOOL] = { + O(UINT8), + O(UINT16), + O(UINT32), + O(UINT64), + O(INT8), + O(INT16), + O(INT32), + O(INT64), + O(SIZE), + O(FLOAT32), + O(FLOAT64), + O(TIME_DELTA), + }, + + [FR_TYPE_UINT8] = { + O(UINT16), + O(UINT32), + O(UINT64), + [FR_TYPE_INT8] = FR_TYPE_UINT8, + O(INT16), + O(INT32), + O(INT64), + O(SIZE), + O(FLOAT32), + O(FLOAT64), + O(TIME_DELTA), + }, + + [FR_TYPE_UINT16] = { + [FR_TYPE_UINT8] = FR_TYPE_UINT16, + O(UINT32), + O(UINT64), + [FR_TYPE_INT16] = FR_TYPE_UINT16, + O(INT32), + O(INT64), + O(SIZE), + O(FLOAT32), + O(FLOAT64), + O(TIME_DELTA), + }, + + [FR_TYPE_UINT32] = { + O(IPV4_ADDR), + [FR_TYPE_UINT8] = FR_TYPE_UINT32, + [FR_TYPE_UINT16] = FR_TYPE_UINT32, + O(UINT64), + [FR_TYPE_INT32] = FR_TYPE_UINT32, + O(INT64), + O(SIZE), + O(FLOAT32), + O(FLOAT64), + O(TIME_DELTA), + O(DATE), + }, + + [FR_TYPE_UINT64] = { + [FR_TYPE_UINT8] = FR_TYPE_UINT64, + [FR_TYPE_UINT16] = FR_TYPE_UINT64, + [FR_TYPE_UINT32] = FR_TYPE_UINT64, + + [FR_TYPE_INT8] = FR_TYPE_UINT64, + [FR_TYPE_INT16] = FR_TYPE_UINT64, + [FR_TYPE_INT32] = FR_TYPE_UINT64, + [FR_TYPE_INT64] = FR_TYPE_UINT64, + O(SIZE), + [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT64, + O(FLOAT64), + O(TIME_DELTA), + O(DATE), + }, + + [FR_TYPE_SIZE] = { + [FR_TYPE_UINT8] = FR_TYPE_SIZE, + [FR_TYPE_UINT16] = FR_TYPE_SIZE, + [FR_TYPE_UINT32] = FR_TYPE_SIZE, + [FR_TYPE_UINT64] = FR_TYPE_SIZE, + [FR_TYPE_INT8] = FR_TYPE_SIZE, + [FR_TYPE_INT16] = FR_TYPE_SIZE, + [FR_TYPE_INT32] = FR_TYPE_SIZE, + [FR_TYPE_INT64] = FR_TYPE_SIZE, + [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT64, + O(FLOAT64), + [FR_TYPE_TIME_DELTA] = FR_TYPE_SIZE, + O(DATE), + }, + + /* signed integers */ + [FR_TYPE_INT8] = { + O(UINT8), + O(UINT16), + O(UINT32), + O(UINT64), + O(INT16), + O(INT32), + O(INT64), + O(SIZE), + O(FLOAT32), + O(FLOAT64), + O(TIME_DELTA), + }, + + [FR_TYPE_INT16] = { + [FR_TYPE_UINT8] = FR_TYPE_INT16, + O(UINT16), + O(UINT32), + O(UINT64), + [FR_TYPE_INT8] = FR_TYPE_INT16, + O(INT32), + O(INT64), + O(SIZE), + O(FLOAT32), + O(FLOAT64), + O(TIME_DELTA), + }, + + [FR_TYPE_INT32] = { + [FR_TYPE_UINT8] = FR_TYPE_INT32, + [FR_TYPE_UINT16] = FR_TYPE_INT32, + O(UINT32), + O(UINT64), + [FR_TYPE_INT8] = FR_TYPE_INT32, + [FR_TYPE_INT16] = FR_TYPE_INT32, + O(INT64), + O(SIZE), + O(FLOAT32), + O(FLOAT64), + O(TIME_DELTA), + O(DATE), + }, + + [FR_TYPE_INT64] = { + [FR_TYPE_UINT8] = FR_TYPE_UINT64, + [FR_TYPE_UINT16] = FR_TYPE_UINT64, + [FR_TYPE_UINT32] = FR_TYPE_UINT64, + O(UINT64), + O(SIZE), + [FR_TYPE_INT8] = FR_TYPE_UINT64, + [FR_TYPE_INT16] = FR_TYPE_UINT64, + [FR_TYPE_INT32] = FR_TYPE_UINT64, + [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT64, + O(FLOAT64), + O(TIME_DELTA), + O(DATE), + }, + + [FR_TYPE_TIME_DELTA] = { + [FR_TYPE_BOOL] = FR_TYPE_TIME_DELTA, + [FR_TYPE_UINT8] = FR_TYPE_TIME_DELTA, + [FR_TYPE_UINT16] = FR_TYPE_TIME_DELTA, + [FR_TYPE_UINT32] = FR_TYPE_TIME_DELTA, + [FR_TYPE_UINT64] = FR_TYPE_TIME_DELTA, + [FR_TYPE_SIZE] = FR_TYPE_TIME_DELTA, + + [FR_TYPE_INT8] = FR_TYPE_TIME_DELTA, + [FR_TYPE_INT16] = FR_TYPE_TIME_DELTA, + [FR_TYPE_INT32] = FR_TYPE_TIME_DELTA, + [FR_TYPE_INT64] = FR_TYPE_TIME_DELTA, + + [FR_TYPE_FLOAT32] = FR_TYPE_TIME_DELTA, + [FR_TYPE_FLOAT64] = FR_TYPE_TIME_DELTA, + [FR_TYPE_DATE] = FR_TYPE_TIME_DELTA, + }, + + [FR_TYPE_DATE] = { + [FR_TYPE_UINT32] = FR_TYPE_DATE, + [FR_TYPE_UINT64] = FR_TYPE_DATE, + [FR_TYPE_SIZE] = FR_TYPE_DATE, + + [FR_TYPE_INT32] = FR_TYPE_DATE, + [FR_TYPE_INT64] = FR_TYPE_DATE, + + [FR_TYPE_FLOAT32] = FR_TYPE_DATE, + [FR_TYPE_FLOAT64] = FR_TYPE_DATE, + O(TIME_DELTA), + }, +}; + +/** Return the promoted type + * + * We presume that the two types are compatible, as checked by + * calling fr_type_cast(). The main difference here is that the two + * types don't have any src / dst relationship. Instead, we just + * pick one which best suits any value-box comparisons + * + * Note that this function can return a type which is _not_ a or b. + * + * @param a type one + * @param b type two + * @return the promoted type + */ +fr_type_t fr_type_promote(fr_type_t a, fr_type_t b) +{ + /* + * Invalid types + */ + switch (a) { + case FR_TYPE_NON_VALUES: + return FR_TYPE_INVALID; + + default: + break; + } + + switch (b) { + case FR_TYPE_NON_VALUES: + return FR_TYPE_INVALID; + + default: + break; + } + + if (a == b) return a; + + /* + * string / octets and "type", the un-typed data gets cast to + * "type". + * + * We prefer to cast raw data to real types. We also + * prefer to _parse_ strings, and do the type checking on + * the real types. That way we have things like: "000" == 0 + */ + if (a == FR_TYPE_OCTETS) return b; + if (b == FR_TYPE_OCTETS) return a; + + /* + * Check for string after octets, because we want to cast + * octets to string, and not vice versa. + */ + if (a == FR_TYPE_STRING) return b; + if (b == FR_TYPE_STRING) return a; + + /* + * Otherwise bad things happen. :( + */ + if (unlikely(type_promote_table[a][b] != type_promote_table[b][a])) return FR_TYPE_INVALID; + + if (unlikely(type_promote_table[a][b] == FR_TYPE_INVALID)) return FR_TYPE_INVALID; + + /* + * That takes care of the simple cases. :( Now to the + * complex ones. Instead of masses of if / then / else, + * we just use a lookup table. + */ + return type_promote_table[a][b]; +} diff --git a/src/lib/util/types.h b/src/lib/util/types.h index 38835300638..998448230e8 100644 --- a/src/lib/util/types.h +++ b/src/lib/util/types.h @@ -16,9 +16,6 @@ */ /** Types of values contained within an #fr_value_box_t - * - * These are in a separate header file to avoid circular dependencies. - * DO NOT ADD FUNCTION DECLARATIONS IN THIS FILE. * * @file src/lib/util/types.h * @@ -214,6 +211,9 @@ typedef enum { FR_TYPE_STRING: \ case FR_TYPE_DATE +bool fr_type_cast(fr_type_t dst, fr_type_t src); +fr_type_t fr_type_promote(fr_type_t a, fr_type_t b); + #ifdef __cplusplus } #endif diff --git a/src/lib/util/value.c b/src/lib/util/value.c index 475fcd8bb68..953aac0d19d 100644 --- a/src/lib/util/value.c +++ b/src/lib/util/value.c @@ -561,7 +561,7 @@ int fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b) #define CHECK(_type) do { \ if (a->datum._type < b->datum._type) { compare = -1; \ } else if (a->datum._type > b->datum._type) { compare = +1; } \ - } while (0) + } while (0) case FR_TYPE_BOOL: CHECK(boolean); @@ -5185,414 +5185,3 @@ fr_value_box_t *fr_value_box_list_get(fr_value_box_t *head, int index) return head; } - -#define O(_x) [FR_TYPE_ ## _x] = true - -/* - * Can we promote [src][dst] -> dst - * dst is not octets / string - * src and dst are both FR_TYPE_VALUE - */ -static const bool type_cast_table[FR_TYPE_MAX][FR_TYPE_MAX] = { - [FR_TYPE_IPV4_ADDR] = { - O(IPV4_PREFIX), - O(IPV6_ADDR), - O(IPV6_PREFIX), - O(UINT32), /* ipv4 addresses are uint32 */ - }, - [FR_TYPE_IPV4_PREFIX] = { - O(IPV4_ADDR), /* if the prefix is /32 */ - O(IPV6_ADDR), - O(IPV6_PREFIX), - }, - [FR_TYPE_IPV6_ADDR] = { - O(IPV6_PREFIX), - }, - [FR_TYPE_IPV6_PREFIX] = { - O(IPV6_ADDR), /* if the prefix is /128 */ - }, - - [FR_TYPE_ETHERNET] = { - O(UINT64), - }, - - [FR_TYPE_UINT64] = { - O(ETHERNET), - }, - - [FR_TYPE_DATE] = { /* in 2021, dates always have values 2^31 or more */ - O(UINT32), - O(UINT64), - O(INT32), - O(INT64), - O(SIZE), - O(FLOAT32), - O(FLOAT64), - O(TIME_DELTA), - }, - - [FR_TYPE_TIME_DELTA] = { - O(DATE), - }, - - [FR_TYPE_UINT32] = { - O(IPV4_ADDR), - }, - -}; - -/* - * This is different from FR_TYPE_NUMERIC, largely in that it - * doesn't include FR_TYPE_DATE. Because we know that dates - * always have values 2^31 or greater, so casts exclude some of - * the smaller integer types. - */ -static const bool type_is_number[FR_TYPE_MAX] = { - O(BOOL), O(SIZE), O(FLOAT32), O(FLOAT64), - O(UINT8), O(UINT16), O(UINT32), O(UINT64), - O(INT8), O(INT16), O(INT32), O(INT64), - O(TIME_DELTA), -}; - -/** Return if we're allowed to cast the types. - * - * @param dst the destination type we wish to cast to - * @param src the source type we wish to cast to - * - */ -bool fr_type_cast(fr_type_t dst, fr_type_t src) -{ - /* - * Invalid casts. - */ - switch (dst) { - case FR_TYPE_NON_VALUES: - return false; - - default: - break; - } - - switch (src) { - case FR_TYPE_NON_VALUES: - return false; - - default: - break; - } - - if (src == dst) return true; - - /* - * Anything can be converted to octets or strings. - */ - if (dst == FR_TYPE_OCTETS) return true; - if (dst == FR_TYPE_STRING) return true; - - /* - * Strings and octets can be converted to anything. We - * do run-time checks on the values to see if they fit. - */ - if (src == FR_TYPE_OCTETS) return true; - if (src == FR_TYPE_STRING) return true; - - /* - * Any integer-style thing can be cast to any other - * integer-style thing. Mostly. We do run-time checks - * on values to see if they fit. - */ - if (type_is_number[src] && type_is_number[dst]) { - return true; - } - - /* - * That takes care of the simple cases. :( Now to the - * complex ones. Instead of masses of if / then / else, - * we just use a lookup table. - */ - return type_cast_table[src][dst]; -} - -#undef O -#define O(_x) [FR_TYPE_ ## _x] = FR_TYPE_ ## _x - -/** promote (a,b) -> a or b - * a/b are not octets / string - * a and b are both FR_TYPE_VALUE - * - * Note that this table can return a type which is _not_ a or b. - * - * Many lookups of table[a][b] will return b. Some will return a. - * Others will return a type which is compatible with both a and b. - */ -static fr_type_t type_promote_table[FR_TYPE_MAX][FR_TYPE_MAX] = { - [FR_TYPE_IPV4_ADDR] = { - O(IPV4_PREFIX), - O(IPV6_ADDR), - O(IPV6_PREFIX), - [FR_TYPE_UINT32] = FR_TYPE_IPV4_ADDR, - }, - - [FR_TYPE_IPV4_PREFIX] = { - [FR_TYPE_IPV4_ADDR] = FR_TYPE_IPV4_PREFIX, - O(IPV4_PREFIX), - [FR_TYPE_IPV6_ADDR] = FR_TYPE_IPV6_PREFIX, - O(IPV6_PREFIX), - }, - - [FR_TYPE_IPV6_ADDR] = { - O(IPV6_PREFIX), - }, - - [FR_TYPE_IPV6_PREFIX] = { - [FR_TYPE_IPV6_ADDR] = FR_TYPE_IPV6_PREFIX, - }, - - /* unsigned integers */ - - [FR_TYPE_BOOL] = { - O(UINT8), - O(UINT16), - O(UINT32), - O(UINT64), - O(INT8), - O(INT16), - O(INT32), - O(INT64), - O(SIZE), - O(FLOAT32), - O(FLOAT64), - O(TIME_DELTA), - }, - - [FR_TYPE_UINT8] = { - O(UINT16), - O(UINT32), - O(UINT64), - [FR_TYPE_INT8] = FR_TYPE_UINT8, - O(INT16), - O(INT32), - O(INT64), - O(SIZE), - O(FLOAT32), - O(FLOAT64), - O(TIME_DELTA), - }, - - [FR_TYPE_UINT16] = { - [FR_TYPE_UINT8] = FR_TYPE_UINT16, - O(UINT32), - O(UINT64), - [FR_TYPE_INT16] = FR_TYPE_UINT16, - O(INT32), - O(INT64), - O(SIZE), - O(FLOAT32), - O(FLOAT64), - O(TIME_DELTA), - }, - - [FR_TYPE_UINT32] = { - O(IPV4_ADDR), - [FR_TYPE_UINT8] = FR_TYPE_UINT32, - [FR_TYPE_UINT16] = FR_TYPE_UINT32, - O(UINT64), - [FR_TYPE_INT32] = FR_TYPE_UINT32, - O(INT64), - O(SIZE), - O(FLOAT32), - O(FLOAT64), - O(TIME_DELTA), - O(DATE), - }, - - [FR_TYPE_UINT64] = { - [FR_TYPE_UINT8] = FR_TYPE_UINT64, - [FR_TYPE_UINT16] = FR_TYPE_UINT64, - [FR_TYPE_UINT32] = FR_TYPE_UINT64, - - [FR_TYPE_INT8] = FR_TYPE_UINT64, - [FR_TYPE_INT16] = FR_TYPE_UINT64, - [FR_TYPE_INT32] = FR_TYPE_UINT64, - [FR_TYPE_INT64] = FR_TYPE_UINT64, - O(SIZE), - [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT64, - O(FLOAT64), - O(TIME_DELTA), - O(DATE), - }, - - [FR_TYPE_SIZE] = { - [FR_TYPE_UINT8] = FR_TYPE_SIZE, - [FR_TYPE_UINT16] = FR_TYPE_SIZE, - [FR_TYPE_UINT32] = FR_TYPE_SIZE, - [FR_TYPE_UINT64] = FR_TYPE_SIZE, - [FR_TYPE_INT8] = FR_TYPE_SIZE, - [FR_TYPE_INT16] = FR_TYPE_SIZE, - [FR_TYPE_INT32] = FR_TYPE_SIZE, - [FR_TYPE_INT64] = FR_TYPE_SIZE, - [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT64, - O(FLOAT64), - [FR_TYPE_TIME_DELTA] = FR_TYPE_SIZE, - O(DATE), - }, - - /* signed integers */ - [FR_TYPE_INT8] = { - O(UINT8), - O(UINT16), - O(UINT32), - O(UINT64), - O(INT16), - O(INT32), - O(INT64), - O(SIZE), - O(FLOAT32), - O(FLOAT64), - O(TIME_DELTA), - }, - - [FR_TYPE_INT16] = { - [FR_TYPE_UINT8] = FR_TYPE_INT16, - O(UINT16), - O(UINT32), - O(UINT64), - [FR_TYPE_INT8] = FR_TYPE_INT16, - O(INT32), - O(INT64), - O(SIZE), - O(FLOAT32), - O(FLOAT64), - O(TIME_DELTA), - }, - - [FR_TYPE_INT32] = { - [FR_TYPE_UINT8] = FR_TYPE_INT32, - [FR_TYPE_UINT16] = FR_TYPE_INT32, - O(UINT32), - O(UINT64), - [FR_TYPE_INT8] = FR_TYPE_INT32, - [FR_TYPE_INT16] = FR_TYPE_INT32, - O(INT64), - O(SIZE), - O(FLOAT32), - O(FLOAT64), - O(TIME_DELTA), - O(DATE), - }, - - [FR_TYPE_INT64] = { - [FR_TYPE_UINT8] = FR_TYPE_UINT64, - [FR_TYPE_UINT16] = FR_TYPE_UINT64, - [FR_TYPE_UINT32] = FR_TYPE_UINT64, - O(UINT64), - O(SIZE), - [FR_TYPE_INT8] = FR_TYPE_UINT64, - [FR_TYPE_INT16] = FR_TYPE_UINT64, - [FR_TYPE_INT32] = FR_TYPE_UINT64, - [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT64, - O(FLOAT64), - O(TIME_DELTA), - O(DATE), - }, - - [FR_TYPE_TIME_DELTA] = { - [FR_TYPE_BOOL] = FR_TYPE_TIME_DELTA, - [FR_TYPE_UINT8] = FR_TYPE_TIME_DELTA, - [FR_TYPE_UINT16] = FR_TYPE_TIME_DELTA, - [FR_TYPE_UINT32] = FR_TYPE_TIME_DELTA, - [FR_TYPE_UINT64] = FR_TYPE_TIME_DELTA, - [FR_TYPE_SIZE] = FR_TYPE_TIME_DELTA, - - [FR_TYPE_INT8] = FR_TYPE_TIME_DELTA, - [FR_TYPE_INT16] = FR_TYPE_TIME_DELTA, - [FR_TYPE_INT32] = FR_TYPE_TIME_DELTA, - [FR_TYPE_INT64] = FR_TYPE_TIME_DELTA, - - [FR_TYPE_FLOAT32] = FR_TYPE_TIME_DELTA, - [FR_TYPE_FLOAT64] = FR_TYPE_TIME_DELTA, - [FR_TYPE_DATE] = FR_TYPE_TIME_DELTA, - }, - - [FR_TYPE_DATE] = { - [FR_TYPE_UINT32] = FR_TYPE_DATE, - [FR_TYPE_UINT64] = FR_TYPE_DATE, - [FR_TYPE_SIZE] = FR_TYPE_DATE, - - [FR_TYPE_INT32] = FR_TYPE_DATE, - [FR_TYPE_INT64] = FR_TYPE_DATE, - - [FR_TYPE_FLOAT32] = FR_TYPE_DATE, - [FR_TYPE_FLOAT64] = FR_TYPE_DATE, - O(TIME_DELTA), - }, -}; - -/** Return the promoted type - * - * We presume that the two types are compatible, as checked by - * calling fr_type_cast(). The main difference here is that the two - * types don't have any src / dst relationship. Instead, we just - * pick one which best suits any value-box comparisons - * - * Note that this function can return a type which is _not_ a or b. - * - * @param a type one - * @param b type two - * @return the promoted type - */ -fr_type_t fr_type_promote(fr_type_t a, fr_type_t b) -{ - /* - * Invalid types - */ - switch (a) { - case FR_TYPE_NON_VALUES: - return FR_TYPE_INVALID; - - default: - break; - } - - switch (b) { - case FR_TYPE_NON_VALUES: - return FR_TYPE_INVALID; - - default: - break; - } - - if (a == b) return a; - - /* - * string / octets and "type", the un-typed data gets cast to - * "type". - * - * We prefer to cast raw data to real types. We also - * prefer to _parse_ strings, and do the type checking on - * the real types. That way we have things like: "000" == 0 - */ - if (a == FR_TYPE_OCTETS) return b; - if (b == FR_TYPE_OCTETS) return a; - - /* - * Check for string after octets, because we want to cast - * octets to string, and not vice versa. - */ - if (a == FR_TYPE_STRING) return b; - if (b == FR_TYPE_STRING) return a; - - /* - * Otherwise bad things happen. :( - */ - fr_assert(type_promote_table[a][b] == type_promote_table[b][a]); - - fr_assert(type_promote_table[a][b] != FR_TYPE_INVALID); - - /* - * That takes care of the simple cases. :( Now to the - * complex ones. Instead of masses of if / then / else, - * we just use a lookup table. - */ - return type_promote_table[a][b]; -} diff --git a/src/lib/util/value.h b/src/lib/util/value.h index 7b025941e98..aeeb1ff0b47 100644 --- a/src/lib/util/value.h +++ b/src/lib/util/value.h @@ -770,9 +770,6 @@ static inline size_t fr_value_box_aprint_quoted(TALLOC_CTX *ctx, char **out, uint32_t fr_value_box_hash_update(fr_value_box_t const *vb, uint32_t hash); /** @} */ -bool fr_type_cast(fr_type_t dst, fr_type_t src); -fr_type_t fr_type_promote(fr_type_t a, fr_type_t b); - #undef _CONST #ifdef __cplusplus