/** * Iterates through the entries pairs in the map, * invoking a callback for each that matches a given prefix. * The call back gets a key, value for each and returns an integer stop value. * If the callback returns non-zero, then the iteration stops. * @arg t The tree to iterate over * @arg prefix The prefix of keys to read * @arg prefix_len The length of the prefix * @arg cb The callback function to invoke * @arg data Opaque handle passed to the callback * @return 0 on success, or the return of the callback. */ int art_iter_prefix(art_tree *t, const unsigned char *key, int key_len, art_callback cb, void *data) { art_node **child; art_node *n = t->root; int prefix_len, depth = 0; while (n) { // Might be a leaf if (IS_LEAF(n)) { n = (art_node*)LEAF_RAW(n); // Check if the expanded path matches if (!leaf_prefix_matches((art_leaf*)n, key, key_len)) { art_leaf *l = (art_leaf*)n; return cb(data, (const unsigned char*)l->key, l->key_len, l->value); } return 0; } // If the depth matches the prefix, we need to handle this node if (depth == key_len) { art_leaf *l = minimum(n); if (!leaf_prefix_matches(l, key, key_len)) return recursive_iter(n, cb, data); return 0; } // Bail if the prefix does not match if (n->partial_len) { prefix_len = prefix_mismatch(n, key, key_len, depth); // If there is no match, search is terminated if (!prefix_len) return 0; // If we've matched the prefix, iterate on this node else if (depth + prefix_len == key_len) { return recursive_iter(n, cb, data); } // if there is a full match, go deeper depth = depth + n->partial_len; } // Recursively search child = find_child(n, key[depth]); n = (child) ? *child : NULL; depth++; } return 0; }
// Recursively iterates over the tree static int recursive_iter(art_node *n, art_callback cb, void *data) { // Handle base cases if (!n) return 0; if (IS_LEAF(n)) { art_leaf *l = LEAF_RAW(n); return cb(data, (const unsigned char*)l->key, l->key_len, l->value); } int idx, res; switch (n->type) { case NODE4: for (int i=0; i < n->num_children; i++) { res = recursive_iter(((art_node4*)n)->children[i], cb, data); if (res) return res; } break; case NODE16: for (int i=0; i < n->num_children; i++) { res = recursive_iter(((art_node16*)n)->children[i], cb, data); if (res) return res; } break; case NODE48: for (int i=0; i < 256; i++) { idx = ((art_node48*)n)->keys[i]; if (!idx) continue; res = recursive_iter(((art_node48*)n)->children[idx-1], cb, data); if (res) return res; } break; case NODE256: for (int i=0; i < 256; i++) { if (!((art_node256*)n)->children[i]) continue; res = recursive_iter(((art_node256*)n)->children[i], cb, data); if (res) return res; } break; default: abort(); } return 0; }
// Recursively iterates static int recursive_iter(radix_node *n, void *data, int(*iter_func)(void *data, char *key, void *value)) { int ret = 0; if (n->edges[0]) { radix_leaf *leaf = n->edges[0]; ret = iter_func(data, leaf->key, leaf->value); } radix_node *child; for (int i=1; !ret && i < 256; i++) { child = (radix_node*)n->edges[i]; if (!child) continue; ret = recursive_iter(child, data, iter_func); } return ret; }
/** * Iterates through all the nodes in the radix tree * @arg t The tree to iter through * @arg iter_func A callback function to iterate through. Returns * non-zero to stop iteration. * @return 0 on sucess. 1 if the iteration was stopped. */ int radix_foreach(radix_tree *t, void *data, int(*iter_func)(void* data, char *key, void *value)) { return recursive_iter(&t->root, data, iter_func); }
/** * Iterates through the entries pairs in the map, * invoking a callback for each. The call back gets a * key, value for each and returns an integer stop value. * If the callback returns non-zero, then the iteration stops. * @arg t The tree to iterate over * @arg cb The callback function to invoke * @arg data Opaque handle passed to the callback * @return 0 on success, or the return of the callback. */ int art_iter(art_tree *t, art_callback cb, void *data) { return recursive_iter(t->root, cb, data); }