/** Return the next child that's of the specified type with the specified identifiers * * @param[in] parent The section we're searching in. * @param[in] type of #CONF_ITEM we're searching for. * @param[in] ident1 The first identifier. * @param[in] ident2 The second identifier. Special value CF_IDENT_ANY * can be used to match any ident2 value. * @return * - The first matching item. * - NULL if no items matched. */ static CONF_ITEM *cf_find(CONF_ITEM const *parent, CONF_ITEM_TYPE type, char const *ident1, char const *ident2) { CONF_SECTION cs_find; CONF_PAIR cp_find; CONF_DATA cd_find; CONF_ITEM *find; if (!parent) return NULL; if (!parent->child) return NULL; /* No children */ if (!ident1) return cf_next(parent, NULL, type); switch (type) { case CONF_ITEM_SECTION: memset(&cs_find, 0, sizeof(cs_find)); cs_find.item.type = CONF_ITEM_SECTION; cs_find.name1 = ident1; if (!IS_WILDCARD(ident2)) cs_find.name2 = ident2; find = (CONF_ITEM *)&cs_find; break; case CONF_ITEM_PAIR: rad_assert((ident2 == NULL) || IS_WILDCARD(ident2)); memset(&cp_find, 0, sizeof(cp_find)); cp_find.item.type = CONF_ITEM_PAIR; cp_find.attr = ident1; find = (CONF_ITEM *)&cp_find; break; case CONF_ITEM_DATA: memset(&cd_find, 0, sizeof(cd_find)); cd_find.item.type = CONF_ITEM_DATA; cd_find.type = ident1; if (!IS_WILDCARD(ident2)) cd_find.name = ident2; find = (CONF_ITEM *)&cd_find; break; default: if (!fr_cond_assert(0)) return NULL; } /* * No ident1, iterate over the child list */ if (IS_WILDCARD(ident1)) { CONF_ITEM *ci; for (ci = parent->child; ci && (cf_ident2_cmp(find, ci) != 0); ci = ci->next); return ci; } /* * No ident2, use the ident1 tree. */ if (IS_WILDCARD(ident2)) return rbtree_finddata(parent->ident1, find); /* * Both ident1 and ident2 use the ident2 tree. */ return rbtree_finddata(parent->ident2, find); }
/** * \brief Testing the continued fractions generator. * * */ void test_cf(void) { bigfraction_t x = {NULL, NULL}; cf_t* f; size_t i; bigfraction_t *it; BIGNUM* expected; f = cf_new(); x.h = BN_new(); x.k = BN_new(); expected = BN_new(); /* * Testing aᵢ * * 1 * √2 = 1 + ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ * 1 * 2 + ⎽⎽⎽⎽⎽⎽ * 2 + … * */ BN_dec2bn(&x.h, "14142135623730951"); BN_dec2bn(&x.k, "10000000000000000"); BN_dec2bn(&expected, "2"); cf_init(f, x.h, x.k); it = cf_next(f); assert(BN_is_one(f->a)); for (i=0; i!=5 && it; i++) { it = cf_next(f); assert(!BN_cmp(f->a, expected)); } assert(i==5); /* * Testing hᵢ/kᵢ * * 1 * φ = (1+√5)/2 = 1 + ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ * 1 * 1 + ⎽⎽⎽⎽⎽ * 1 + … */ const char* fib[] = {"1", "1", "2", "3", "5", "8", "13"}; BN_dec2bn(&x.h, "323606797749979"); BN_dec2bn(&x.k, "200000000000000"); cf_init(f, x.h, x.k); it = cf_next(f); for (i=1; i!=7; i++) { BN_dec2bn(&expected, fib[i]); assert(!BN_cmp(it->h, expected)); BN_dec2bn(&expected, fib[i-1]); assert(!BN_cmp(it->k, expected)); it=cf_next(f); } BN_dec2bn(&x.h, "60728973"); BN_dec2bn(&x.k, "160523347"); cf_init(f, x.h, x.k); /* 0 */ it = cf_next(f); /* 1 / 2 */ it = cf_next(f); BN_dec2bn(&expected, "2"); assert(BN_is_one(it->h) && !BN_cmp(it->k, expected)); /* 1 / 3 */ it = cf_next(f); BN_dec2bn(&expected, "3"); assert(BN_is_one(it->h) && !BN_cmp(it->k, expected)); /* 2 / 5 */ it = cf_next(f); BN_dec2bn(&expected, "2"); assert(!BN_cmp(expected, it->h)); BN_dec2bn(&expected, "5"); assert(!BN_cmp(expected, it->k)); /* 3 / 8 */ it = cf_next(f); BN_dec2bn(&expected, "3"); assert(!BN_cmp(expected, it->h)); BN_dec2bn(&expected, "8"); assert(!BN_cmp(expected, it->k)); /* 14/ 37 */ it = cf_next(f); BN_dec2bn(&expected, "14"); assert(!BN_cmp(expected, it->h)); BN_dec2bn(&expected, "37"); assert(!BN_cmp(expected, it->k)); }
/** Return the next child that's of the specified type with the specified identifiers * * @param[in] parent The section we're searching in. * @param[in] prev item we found, or NULL to start from the beginning. * @param[in] type of #CONF_ITEM we're searching for. * @param[in] ident1 The first identifier. * @param[in] ident2 The second identifier. Special value CF_IDENT_ANY * can be used to match any ident2 value. * @return * - The first matching item. * - NULL if no items matched. */ static CONF_ITEM *cf_find_next(CONF_ITEM const *parent, CONF_ITEM const *prev, CONF_ITEM_TYPE type, char const *ident1, char const *ident2) { CONF_SECTION cs_find; CONF_PAIR cp_find; CONF_DATA cd_find; CONF_ITEM *find; CONF_ITEM *ci; if (!parent) return NULL; if (!prev) { if (!ident1) return cf_next(parent, NULL, type); return cf_find(parent, type, ident1, ident2); } if (!ident1) return cf_next(parent, prev, type); switch (type) { case CONF_ITEM_SECTION: memset(&cs_find, 0, sizeof(cs_find)); cs_find.item.type = CONF_ITEM_SECTION; cs_find.name1 = ident1; if (!IS_WILDCARD(ident2)) cs_find.name2 = ident2; find = (CONF_ITEM *)&cs_find; break; case CONF_ITEM_PAIR: rad_assert((ident2 == NULL) || IS_WILDCARD(ident2)); memset(&cp_find, 0, sizeof(cp_find)); cp_find.item.type = CONF_ITEM_PAIR; cp_find.attr = ident1; find = (CONF_ITEM *)&cp_find; break; case CONF_ITEM_DATA: memset(&cd_find, 0, sizeof(cd_find)); cd_find.item.type = CONF_ITEM_DATA; cd_find.type = ident1; if (!IS_WILDCARD(ident2)) cd_find.name = ident2; find = (CONF_ITEM *)&cd_find; break; default: if (!fr_cond_assert(0)) return NULL; } if (IS_WILDCARD(ident1)) { for (ci = prev->next; ci && (cf_ident2_cmp(ci, find) != 0); ci = ci->next); return ci; } if (IS_WILDCARD(ident2)) { for (ci = prev->next; ci && (_cf_ident1_cmp(ci, find) != 0); ci = ci->next) { rad_assert(ci->next != ci); } return ci; } for (ci = prev->next; ci && (_cf_ident2_cmp(ci, find) != 0); ci = ci->next); return ci; }