From: Arran Cudbard-Bell Date: Fri, 17 Jun 2022 21:38:20 +0000 (-0500) Subject: Add useful utility functions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3af4bcc6d298e1d66287ae95469a6f7c30c7e761;p=thirdparty%2Ffreeradius-server.git Add useful utility functions --- diff --git a/src/lib/server/cf_util.c b/src/lib/server/cf_util.c index 2d487280dea..25d92d30e4b 100644 --- a/src/lib/server/cf_util.c +++ b/src/lib/server/cf_util.c @@ -1351,7 +1351,7 @@ static void _pair_count(int *count, CONF_SECTION const *cs) * @param[in] cs to search for items in. * @return The number of pairs nested within section. */ -int cf_pair_count(CONF_SECTION const *cs) +unsigned int cf_pair_count_descendents(CONF_SECTION const *cs) { int count = 0; @@ -1360,6 +1360,59 @@ int cf_pair_count(CONF_SECTION const *cs) return count; } +/** Count the number of times an attribute occurs in a parent section + * + * @param[in] cs to search for items in. + * @param[in] attr to search for. + * @return The number of pairs of that attribute type. + */ +unsigned int cf_pair_count(CONF_SECTION const *cs, char const *attr) +{ + size_t i; + CONF_PAIR *cp = NULL; + + for (i = 0; (cp = cf_pair_find_next(cs, cp, attr)); i++); + + return i; +} + +/** Concatenate the values of any pairs with name attr + * + * @param[out] out where to write the concatenated values. + * @param[in] cs to search in. + * @param[in] attr to search for. + * @param[in] sep to use to separate values + * @return + * - Length of the data written to out on success. + * - < 0 on failure. Number of additional bytes required in buffer. + */ +fr_slen_t cf_pair_values_concat(fr_sbuff_t *out, CONF_SECTION const *cs, char const *attr, char const *sep) +{ + fr_sbuff_t our_out = FR_SBUFF(out); + CONF_PAIR *cp; + fr_slen_t slen = 0; + fr_sbuff_escape_rules_t e_rules = { + .name = __FUNCTION__, + .chr = '\\' + }; + + if (sep) e_rules.subs[(uint8_t)*sep] = *sep; + + for (cp = cf_pair_find(cs, attr); cp;) { + slen = fr_sbuff_in_escape(&our_out, cf_pair_value(cp), + strlen(cf_pair_value(cp)), &e_rules); + if (slen < 0) return slen; + + cp = cf_pair_find_next(cs, cp, attr); + if (cp && sep) { + slen = fr_sbuff_in_strcpy(&our_out, sep); + if (slen < 0) return slen; + } + } + + return fr_sbuff_set(out, &our_out); +} + /** Return the attr of a #CONF_PAIR * * Return the LHS value of a pair (the attribute). diff --git a/src/lib/server/cf_util.h b/src/lib/server/cf_util.h index 76b71d72601..65425552fcb 100644 --- a/src/lib/server/cf_util.h +++ b/src/lib/server/cf_util.h @@ -172,17 +172,28 @@ fr_token_t cf_section_argv_quote(CONF_SECTION const *cs, int argc); */ CONF_PAIR *cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, fr_token_t op, fr_token_t lhs_type, fr_token_t rhs_type); + CONF_PAIR *cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp); + int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value); + void cf_pair_mark_parsed(CONF_PAIR *cp); bool cf_pair_is_parsed(CONF_PAIR *cp); CONF_PAIR *cf_pair_next(CONF_SECTION const *cs, CONF_PAIR const *prev); + CONF_PAIR *cf_pair_find(CONF_SECTION const *cs, char const *name); + CONF_PAIR *cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *name); + CONF_PAIR *cf_pair_find_in_parent(CONF_SECTION const *cs, char const *attr); -int cf_pair_count(CONF_SECTION const *cs); + +unsigned int cf_pair_count_descendents(CONF_SECTION const *cs); + +unsigned int cf_pair_count(CONF_SECTION const *cs, char const *attr); + +fr_slen_t cf_pair_values_concat(fr_sbuff_t *sbuff, CONF_SECTION const *cs, char const *attr, char const *sep); /** @hidecallergraph */ char const *cf_pair_attr(CONF_PAIR const *pair);