The tree is implemented as a red-black tree, as inspired by Julienne Walker (http://eternallyconfuzzled.com/tuts/redblack.html).
Jason Tang jtang@tresys.com
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
Definition in file bst.c.
#include <apol/bst.h>
#include <apol/vector.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "vector-internal.h"
Go to the source code of this file.
Classes | |
| struct | bst_node |
| struct | apol_bst |
| Generic binary search tree structure. More... | |
Typedefs | |
| typedef bst_node | bst_node_t |
Functions | |
| apol_bst_t * | apol_bst_create (apol_bst_comp_func *cmp, apol_bst_free_func *fr) |
| Allocate and initialize an empty binary search tree. | |
| void | bst_node_free (bst_node_t *node, apol_bst_free_func *fr) |
| Free the data stored within a bst node, recurse through the node's children, and then the node itself. | |
| void | apol_bst_destroy (apol_bst_t **b) |
| Free a BST and any memory used by it. | |
| int | bst_node_to_vector (bst_node_t *node, apol_vector_t *v) |
| Given a BST node, traverse the node infix, appending the node's element to vector v. | |
| apol_vector_t * | apol_bst_get_vector (apol_bst_t *b, int change_owner) |
| Allocate and return a vector that has been initialized with the contents of a binary search tree. | |
| size_t | apol_bst_get_size (const apol_bst_t *b) |
| Get the number of elements stored in the BST. | |
| int | apol_bst_get_element (const apol_bst_t *b, const void *elem, void *data, void **result) |
| Find an element within a BST and return it. | |
| bst_node_t * | bst_node_make (apol_bst_t *b, void *elem) |
| Allocate and return a new BST node, with data set to elem and color to red. | |
| int | bst_node_is_red (bst_node_t *node) |
| Determines if a node is red or not. | |
| bst_node_t * | bst_rotate_single (bst_node_t *root, int dir) |
| bst_node_t * | bst_rotate_double (bst_node_t *root, int dir) |
| bst_node_t * | bst_insert_recursive (apol_bst_t *b, bst_node_t *root, void **elem, void *data, apol_bst_free_func *fr, int *not_uniq) |
| int | apol_bst_insert (apol_bst_t *b, void *elem, void *data) |
| Insert an element to the BST. | |
| int | apol_bst_insert_and_get (apol_bst_t *b, void **elem, void *data) |
| Insert an element into the BST, and then get the element back out. | |
| int | bst_inorder_map (const bst_node_t *node, int(*fn)(void *, void *), void *data) |
| int | apol_bst_inorder_map (const apol_bst_t *b, int(*fn)(void *, void *), void *data) |
| Map a function across all the elements of the BST. | |
|
|
||||||||||||
|
Allocate and initialize an empty binary search tree. The tree must have a comparison function, used when comparing nodes so as to determine how to sort them.
Definition at line 58 of file bst.c. References apol_bst_t, apol_bst::cmp, and apol_bst::fr. Referenced by apol_avrule_list_to_syn_avrules(), apol_domain_trans_table_new(), apol_infoflow_graph_create(), apol_infoflow_graph_create_required_types(), apol_terule_list_to_syn_terules(), avrule_get_items(), db_convert::db_convert(), dom_node_create(), ep_node_create(), poldiff_build_bsts(), role_allow_get_items(), seaudit_log_clear(), seaudit_log_create(), seaudit_model_create(), sefs_fclist::sefs_fclist(), and terule_get_items(). 00059 {
00060 apol_bst_t *b = NULL;
00061 if ((b = calloc(1, sizeof(*b))) == NULL) {
00062 return NULL;
00063 }
00064 b->cmp = cmp;
00065 b->fr = fr;
00066 return b;
00067 }
|
|
||||||||||||
|
Free the data stored within a bst node, recurse through the node's children, and then the node itself.
Definition at line 77 of file bst.c. References bst_node_t, bst_node::child, and bst_node::elem. Referenced by apol_bst_destroy(). 00078 {
00079 if (node != NULL) {
00080 if (fr != NULL) {
00081 fr(node->elem);
00082 }
00083 bst_node_free(node->child[0], fr);
00084 bst_node_free(node->child[1], fr);
00085 free(node);
00086 }
00087 }
|
|
|
||||||||||||
|
Given a BST node, traverse the node infix, appending the node's element to vector v.
Definition at line 108 of file bst.c. References apol_vector_append(), apol_vector_t, bst_node_t, bst_node::child, and bst_node::elem. Referenced by apol_bst_get_vector(). 00109 {
00110 int retval;
00111 if (node == NULL) {
00112 return 0;
00113 }
00114 if ((retval = bst_node_to_vector(node->child[0], v)) < 0) {
00115 return retval;
00116 }
00117 if ((retval = apol_vector_append(v, node->elem)) < 0) {
00118 return retval;
00119 }
00120 return bst_node_to_vector(node->child[1], v);
00121 }
|
|
||||||||||||
|
Allocate and return a vector that has been initialized with the contents of a binary search tree. If change_owner is zero then this function will make a shallow copy of the BST's contents; the BST will still own the objects. Otherwise the victor will gain ownership of the items; the BST can then be destroyed safely without affecting the vector. (The resulting vector will be sorted as per the BST's comparison function.)
Definition at line 123 of file bst.c. References apol_bst_t, apol_vector_create_with_capacity(), apol_vector_destroy(), apol_vector_t, bst_node_to_vector(), apol_bst::fr, apol_bst::head, apol_bst::size, and vector_set_free_func(). Referenced by apol_avrule_list_to_syn_avrules(), apol_infoflow_graph_create(), apol_terule_list_to_syn_terules(), avrule_get_items(), domain_trans_table_find_orphan_type_transitions(), domain_trans_table_get_all_forward_trans(), domain_trans_table_get_all_reverse_trans(), role_allow_get_items(), seaudit_log_get_classes(), seaudit_log_get_roles(), seaudit_log_get_types(), seaudit_log_get_users(), and terule_get_items(). 00124 {
00125 apol_vector_t *v = NULL;
00126 if (!b) {
00127 errno = EINVAL;
00128 return NULL;
00129 }
00130 if ((v = apol_vector_create_with_capacity(b->size, NULL)) == NULL) {
00131 return NULL;
00132 }
00133 if (bst_node_to_vector(b->head, v) < 0) {
00134 int error = errno;
00135 apol_vector_destroy(&v);
00136 errno = error;
00137 return NULL;
00138 }
00139 if (change_owner) {
00140 vector_set_free_func(v, b->fr);
00141 b->fr = NULL;
00142 }
00143 return v;
00144 }
|
|
|
Get the number of elements stored in the BST.
Definition at line 146 of file bst.c. References apol_bst_t, and apol_bst::size. 00147 {
00148 if (!b) {
00149 errno = EINVAL;
00150 return 0;
00151 } else {
00152 return b->size;
00153 }
00154 }
|
|
||||||||||||||||||||
|
Find an element within a BST and return it.
Definition at line 156 of file bst.c. References apol_bst_t, bst_node_t, bst_node::child, apol_bst::cmp, bst_node::elem, and apol_bst::head. Referenced by apol_domain_trans_table_verify_trans(), apol_infoflow_graph_check_types(), apol_infoflow_graph_create_node(), apol_infoflow_graph_create_nodes(), avrule_add_to_bst(), avrule_build_cond(), domain_trans_table_find_orphan_type_transitions(), domain_trans_table_get_all_forward_trans(), domain_trans_table_get_all_reverse_trans(), sefs_fclist::getContext(), db_convert::getID(), model_refresh(), table_add_avrule(), table_add_terule(), terule_add_to_bst(), and terule_build_cond(). 00157 {
00158 bst_node_t *node;
00159 int compval;
00160 if (!b || !result) {
00161 errno = EINVAL;
00162 return -1;
00163 }
00164 node = b->head;
00165 while (node != NULL) {
00166 if (b->cmp != NULL) {
00167 compval = b->cmp(node->elem, elem, data);
00168 } else {
00169 char *p1 = (char *)node->elem;
00170 char *p2 = (char *)elem;
00171 if (p1 < p2) {
00172 compval = -1;
00173 } else if (p1 > p2) {
00174 compval = 1;
00175 } else {
00176 compval = 0;
00177 }
00178 }
00179 if (compval == 0) {
00180 *result = node->elem;
00181 return 0;
00182 } else if (compval > 0) {
00183 node = node->child[0];
00184 } else {
00185 node = node->child[1];
00186 }
00187 }
00188 return -1;
00189 }
|
|
||||||||||||
|
Allocate and return a new BST node, with data set to elem and color to red. Also increment the tree's size.
Definition at line 201 of file bst.c. References apol_bst_t, bst_node_t, bst_node::elem, bst_node::is_red, and apol_bst::size. Referenced by bst_insert_recursive(). 00202 {
00203 bst_node_t *new_node;
00204 if ((new_node = calloc(1, sizeof(*new_node))) == NULL) {
00205 return NULL;
00206 }
00207 new_node->elem = elem;
00208 new_node->is_red = 1;
00209 b->size++;
00210 return new_node;
00211 }
|
|
|
Determines if a node is red or not.
Definition at line 220 of file bst.c. References bst_node_t, and bst_node::is_red. Referenced by bst_insert_recursive(). 00221 {
00222 return node != NULL && node->is_red;
00223 }
|
|
||||||||||||
|
Definition at line 225 of file bst.c. References bst_node_t, bst_node::child, and bst_node::is_red. Referenced by bst_insert_recursive(), and bst_rotate_double(). 00226 {
00227 bst_node_t *save = root->child[!dir];
00228 root->child[!dir] = save->child[dir];
00229 save->child[dir] = root;
00230 root->is_red = 1;
00231 save->is_red = 0;
00232 return save;
00233 }
|
|
||||||||||||
|
Definition at line 235 of file bst.c. References bst_node_t, bst_rotate_single(), and bst_node::child. Referenced by bst_insert_recursive(). 00236 {
00237 root->child[!dir] = bst_rotate_single(root->child[!dir], !dir);
00238 return bst_rotate_single(root, dir);
00239 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 241 of file bst.c. References apol_bst_t, bst_node_is_red(), bst_node_make(), bst_node_t, bst_rotate_double(), bst_rotate_single(), bst_node::child, apol_bst::cmp, bst_node::elem, and bst_node::is_red. Referenced by apol_bst_insert(), and apol_bst_insert_and_get(). 00243 {
00244 int compval, dir;
00245 if (root == NULL) {
00246 if ((root = bst_node_make(b, *elem)) == NULL) {
00247 *not_uniq = -1;
00248 return NULL;
00249 }
00250 *not_uniq = 0;
00251 } else {
00252 if (b->cmp != NULL) {
00253 compval = b->cmp(root->elem, *elem, data);
00254 } else {
00255 char *p1 = (char *)root->elem;
00256 char *p2 = (char *)(*elem);
00257 if (p1 < p2) {
00258 compval = -1;
00259 } else if (p1 > p2) {
00260 compval = 1;
00261 } else {
00262 compval = 0;
00263 }
00264 }
00265 if (compval == 0) {
00266 /* already exists */
00267 if (fr != NULL) {
00268 fr(*elem);
00269 }
00270 *elem = root->elem;
00271 *not_uniq = 1;
00272 return root;
00273 } else if (compval > 0) {
00274 dir = 0;
00275 } else {
00276 dir = 1;
00277 }
00278 root->child[dir] = bst_insert_recursive(b, root->child[dir], elem, data, fr, not_uniq);
00279 if (*not_uniq != 0) {
00280 return root;
00281 }
00282
00283 /* rebalance tree */
00284 if (bst_node_is_red(root->child[dir])) {
00285 if (bst_node_is_red(root->child[!dir])) {
00286 /* recolor myself and children. note
00287 * that this can't be reached if a
00288 * child is NULL */
00289 root->is_red = 1;
00290 root->child[0]->is_red = 0;
00291 root->child[1]->is_red = 0;
00292 } else {
00293 if (bst_node_is_red(root->child[dir]->child[dir])) {
00294 root = bst_rotate_single(root, !dir);
00295 } else if (bst_node_is_red(root->child[dir]->child[!dir])) {
00296 root = bst_rotate_double(root, !dir);
00297 }
00298 }
00299 }
00300 }
00301 return root;
00302 }
|
|
||||||||||||||||
|
Insert an element to the BST. If the element already exists then do not insert it again.
Definition at line 304 of file bst.c. References apol_bst_t, bst_insert_recursive(), apol_bst::head, and bst_node::is_red. Referenced by apol_avrule_list_to_syn_avrules(), apol_infoflow_graph_create_node(), apol_infoflow_graph_create_required_types(), apol_terule_list_to_syn_terules(), sefs_fclist::getContext(), db_convert::getID(), seaudit_model_hide_message(), table_add_avrule(), and table_add_terule(). 00305 {
00306 int retval = -1;
00307 if (!b || !elem) {
00308 errno = EINVAL;
00309 return -1;
00310 }
00311 b->head = bst_insert_recursive(b, b->head, &elem, data, NULL, &retval);
00312 if (retval >= 0) {
00313 b->head->is_red = 0;
00314 }
00315 return retval;
00316 }
|
|
||||||||||||||||
|
Insert an element into the BST, and then get the element back out. If the element did not already exist, then this function behaves the same as apol_bst_insert(). If however the element did exist, then the passed in element is freed (as per the BST's free function) and then the existing element is returned.
Definition at line 318 of file bst.c. References apol_bst_t, bst_insert_recursive(), apol_bst::fr, apol_bst::head, and bst_node::is_red. Referenced by avc_msg_insert_perms(), avc_msg_insert_tclass(), avrule_add_to_bst(), bool_change_append(), sefs_filesystem::buildDevMap(), sefs_fclist::getContext(), sefs_filesystem::getEntry(), sefs_db::getEntry(), insert_hostname(), insert_manager(), parse_context(), sefs_fcfile::parse_line(), poldiff_build_bsts(), role_allow_get_items(), table_add_avrule(), table_add_terule(), and terule_add_to_bst(). 00319 {
00320 int retval = -1;
00321 if (!b || !elem) {
00322 errno = EINVAL;
00323 return -1;
00324 }
00325 b->head = bst_insert_recursive(b, b->head, elem, data, b->fr, &retval);
00326 if (retval >= 0) {
00327 b->head->is_red = 0;
00328 }
00329 return retval;
00330 }
|
|
||||||||||||||||
|
Definition at line 332 of file bst.c. References bst_node_t, bst_node::child, and bst_node::elem. Referenced by apol_bst_inorder_map(). 00333 {
00334 int retval;
00335 if (node == NULL) {
00336 return 0;
00337 }
00338 if ((retval = bst_inorder_map(node->child[0], fn, data)) < 0) {
00339 return retval;
00340 }
00341 if ((retval = fn(node->elem, data)) < 0) {
00342 return retval;
00343 }
00344 return bst_inorder_map(node->child[1], fn, data);
00345 }
|
|
||||||||||||||||
|
Map a function across all the elements of the BST. Mapping occurs in the sorted order as defined by the original comparison function.
Definition at line 347 of file bst.c. References apol_bst_t, bst_inorder_map(), and apol_bst::head. Referenced by apol_policy_reset_domain_trans_table(), sefs_fclist::associatePolicy(), dom_node_reset(), ep_node_reset(), find_avrules_in_node(), and find_terules_in_node(). 00348 {
00349 if (b == NULL || fn == NULL)
00350 return -1;
00351 return bst_inorder_map(b->head, fn, data);
00352 }
|