Browse Source

From: Joseph Adams <joeyadams3.14159@gmail.com>

The btree patch gives the btree module an intuitive frontend
(btree_insert, btree_remove, btree_lookup) and a built-in ordering
function for strings.  Together, these make it easy to use the btree
module as a dynamic string map.
Rusty Russell 16 years ago
parent
commit
7b877620c6
3 changed files with 81 additions and 9 deletions
  1. 0 8
      ccan/btree/_info
  2. 49 0
      ccan/btree/btree.c
  3. 32 1
      ccan/btree/btree.h

+ 0 - 8
ccan/btree/_info

@@ -12,14 +12,6 @@
  * invalidate all iterators pointing to it (including the one passed to the
  * invalidate all iterators pointing to it (including the one passed to the
  * insertion or removal function).
  * insertion or removal function).
  *
  *
- * btree currently doesn't have convenience functions for the simple tasks of
- * "look up by key", "insert a key", and "remove a key".  To insert or remove,
- * you first have use btree_find* to position an iterator on the
- * insertion/removal point, then call btree_insert_at or btree_remove_at using
- * that iterator.  Since a btree can hold multiple items with the same key,
- * it isn't clear how the convenience functions should work yet.  I'm open to
- * suggestions.
- *
  * A B-tree (not to be confused with a binary tree) is a data structure that
  * A B-tree (not to be confused with a binary tree) is a data structure that
  * performs insertion, removal, and lookup in O(log n) time per operation.
  * performs insertion, removal, and lookup in O(log n) time per operation.
  * Although B-trees are typically used for databases and filesystems, this is
  * Although B-trees are typically used for databases and filesystems, this is

+ 49 - 0
ccan/btree/btree.c

@@ -77,6 +77,7 @@ struct btree *btree_new(btree_search_t search)
 		node->depth = 0;
 		node->depth = 0;
 	btree->root = node;
 	btree->root = node;
 	btree->search = search;
 	btree->search = search;
+	btree->multi = false;
 	return btree;
 	return btree;
 }
 }
 
 
@@ -86,6 +87,43 @@ void btree_delete(struct btree *btree)
 	free(btree);
 	free(btree);
 }
 }
 
 
+bool btree_insert(struct btree *btree, const void *item)
+{
+	btree_iterator iter;
+	
+	if (btree_find_last(btree, item, iter) && !btree->multi)
+		return false;
+	
+	btree_insert_at(iter, item);
+	return true;
+}
+
+bool btree_remove(struct btree *btree, const void *key)
+{
+	btree_iterator iter;
+	bool success = false;
+	bool multi = btree->multi;
+	
+	do {
+		if (btree_find_first(btree, key, iter)) {
+			btree_remove_at(iter);
+			success = true;
+		}
+	} while (multi);
+	
+	return success;
+}
+
+void *btree_lookup(struct btree *btree, const void *key)
+{
+	btree_iterator iter;
+	
+	if (btree_find_first(btree, key, iter))
+		return iter->item;
+	
+	return NULL;
+}
+
 int btree_begin_end_lr(const struct btree *btree, btree_iterator iter, int lr)
 int btree_begin_end_lr(const struct btree *btree, btree_iterator iter, int lr)
 {
 {
 	struct btree_node *node;
 	struct btree_node *node;
@@ -374,6 +412,17 @@ int btree_cmp_iters(const btree_iterator iter_a, const btree_iterator iter_b)
 	return 0;
 	return 0;
 }
 }
 
 
+/********************* Built-in ordering functions *******************/
+
+btree_search_implement
+(
+	btree_strcmp,
+	char*,
+	int c = strcmp(a, b),
+	c == 0,
+	c < 0
+)
+
 
 
 /************************* Private functions *************************/
 /************************* Private functions *************************/
 
 

+ 32 - 1
ccan/btree/btree.h

@@ -33,10 +33,14 @@ Note:  The following should work but are not well-tested yet:
 
 
 btree_walk...
 btree_walk...
 btree_cmp_iters
 btree_cmp_iters
+btree_insert
+btree_remove
+btree_lookup
 */
 */
 
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdint.h>
-#include <stddef.h>
+#include <string.h>
 
 
 /*
 /*
  * Maximum number of items per node.
  * Maximum number of items per node.
@@ -90,6 +94,8 @@ typedef unsigned int btree_search_proto(
 );
 );
 typedef btree_search_proto *btree_search_t;
 typedef btree_search_proto *btree_search_t;
 
 
+btree_search_proto btree_strcmp;
+
 /*
 /*
  * Callback used by btree_delete() and btree_walk...().
  * Callback used by btree_delete() and btree_walk...().
  *
  *
@@ -106,6 +112,7 @@ struct btree {
 	size_t count; /* Total number of items in B-tree */
 	size_t count; /* Total number of items in B-tree */
 	
 	
 	btree_search_t search;
 	btree_search_t search;
+	bool multi;
 	
 	
 	/*
 	/*
 	 * These are set to NULL by default.
 	 * These are set to NULL by default.
@@ -123,6 +130,30 @@ struct btree {
 struct btree *btree_new(btree_search_t search);
 struct btree *btree_new(btree_search_t search);
 void btree_delete(struct btree *btree);
 void btree_delete(struct btree *btree);
 
 
+/* Inserts an item into the btree.  If an item already exists that is equal
+ * to this one (as determined by the search function), behavior depends on the
+ * btree->multi setting.
+ *   If btree->multi is false (default), returns false, and no item
+ *      is inserted (because it would be a duplicate).
+ *   If btree->multi is true, returns true, putting the item after
+ *      its duplicates.
+ */
+bool btree_insert(struct btree *btree, const void *item);
+
+/* Removes an item from the btree.  If an item exists that is equal to the
+ * key (as determined by the search function), it is removed.
+ *
+ * If btree->multi is set, all matching items are removed.
+ *
+ * Returns true if item was found and deleted, false if not found. */
+bool btree_remove(struct btree *btree, const void *key);
+
+/* Finds the requested item.
+ * Returns the item pointer on success, NULL on failure.
+ * Note that NULL is a valid item value.  If you need to put
+ * NULLs in a btree, use btree_find instead. */
+void *btree_lookup(struct btree *btree, const void *key);
+
 
 
 /* lr must be 0 or 1, nothing else. */
 /* lr must be 0 or 1, nothing else. */
 int btree_begin_end_lr(const struct btree *btree, btree_iterator iter, int lr);
 int btree_begin_end_lr(const struct btree *btree, btree_iterator iter, int lr);