[asterisk-commits] eliel: branch group/data_api_gsoc2009 r205040 - /team/group/data_api_gsoc2009...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jul 7 07:06:47 CDT 2009


Author: eliel
Date: Tue Jul  7 07:06:43 2009
New Revision: 205040

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=205040
Log:
Create the search tree.


Modified:
    team/group/data_api_gsoc2009/main/data.c

Modified: team/group/data_api_gsoc2009/main/data.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/data_api_gsoc2009/main/data.c?view=diff&rev=205040&r1=205039&r2=205040
==============================================================================
--- team/group/data_api_gsoc2009/main/data.c (original)
+++ team/group/data_api_gsoc2009/main/data.c Tue Jul  7 07:06:43 2009
@@ -36,6 +36,7 @@
 
 #define NUM_DATA_NODE_BUCKETS	60
 #define NUM_DATA_RESULT_BUCKETS 60
+#define NUM_DATA_SEARCH_BUCKETS 60
 
 /*! \brief The last compatible version. */
 static const uint32_t latest_handler_compatible_version = 0;
@@ -91,7 +92,7 @@
 /*! \brief The list of nodes with their search requirement. */
 struct ast_data_search {
 	/*! \brief The value of the comparison. */
-	void *value;
+	char *value;
 
 	/*! \brief The type of comparison. */
 	enum data_search_comparison cmp_type;
@@ -178,7 +179,6 @@
 	struct ast_data *node1 = obj, *node2 = arg;
 	return strcasecmp(node1->name, node2->name) ? 0 : CMP_MATCH;
 }
-
 
 /*!
  * \internal
@@ -571,37 +571,191 @@
  * \internal
  * \brief Get the type of comparison.
  */
-#if 0
-static enum data_search_comparison data_search_comparison_type(const char *comparison_string)
-{
-	if (!strcmp(comparison_string, "=")) {
+static enum data_search_comparison data_search_comparison_type(const char *comparison)
+{
+	if (!strcmp(comparison, "=")) {
 		return DATA_CMP_EQ;
-	} else if (!strcmp(comparison_string, "!=")) {
+	} else if (!strcmp(comparison, "!=")) {
 		return DATA_CMP_NEQ;
-	} else if (!strcmp(comparison_string, "<")) {
+	} else if (!strcmp(comparison, "<")) {
 		return DATA_CMP_LT;
-	} else if (!strcmp(comparison_string, ">")) {
+	} else if (!strcmp(comparison, ">")) {
 		return DATA_CMP_GT;
-	} else if (!strcmp(comparison_string, "<=")) {
+	} else if (!strcmp(comparison, "<=")) {
 		return DATA_CMP_LE;
-	} else if (!strcmp(comparison_string, ">=")) {
+	} else if (!strcmp(comparison, ">=")) {
 		return DATA_CMP_GE;
 	}
 
 	return DATA_CMP_UNKNOWN;
 }
-#endif
+
+/*!
+ * \internal
+ * \brief Common string hash function for data nodes
+ */
+static int data_search_hash(const void *obj, const int flags)
+{
+	const struct ast_data_search *node = obj;
+	return ast_str_hash(node->name);
+}
+
+/*!
+ * \internal
+ * \brief Common string comparison function
+ */
+static int data_search_cmp(void *obj, void *arg, int flags)
+{
+	struct ast_data_search *node1 = obj, *node2 = arg;
+	return strcasecmp(node1->name, node2->name) ? 0 : CMP_MATCH;
+}
+
+/*!
+ * \internal
+ * \brief Destroy the ao2 search node.
+ */
+static void data_search_destructor(void *obj)
+{
+	struct ast_data_search *node = obj;
+
+	if (node->value) {
+		ast_free(node->value);
+	}
+
+	ao2_ref(node->children, -1);
+}
+
+/*!
+ * \internal
+ * \brief Allocate a search node.
+ * \retval NULL on error.
+ * \retval non-NULL The allocated search node structure.
+ */
+static struct ast_data_search *data_search_alloc(const char *name)
+{
+	struct ast_data_search *res;
+	size_t name_len = strlen(name) + 1;
+
+	res = ao2_alloc(sizeof(*res) + name_len, data_search_destructor);
+	if (!res) {
+		return NULL;
+	}
+
+	res->children = ao2_container_alloc(NUM_DATA_SEARCH_BUCKETS, data_search_hash,
+		data_search_cmp);
+
+	if (!res) {
+		ao2_ref(res, -1);
+		return NULL;
+	}
+
+	strcpy(res->name, name);
+
+	return res;
+}
+
+/*!
+ * \internal
+ * \brief Find a child node, based on his name.
+ * \param[in] parent Where to find the node.
+ * \param[in] name The node name to find.
+ * \retval NULL if a node wasn't found.
+ * \retval The node found.
+ * \note Remember to decrement the ref count of the returned node after using it.
+ */
+static struct ast_data_search *data_search_find(struct ao2_container *parent,
+	const char *name)
+{
+	struct ast_data_search *find_node, *found;
+
+	find_node = data_search_alloc(name);
+	if (!find_node) {
+		return NULL;
+	}
+
+	found = ao2_find(parent, find_node, OBJ_POINTER);
+
+	/* free the created node used for searching. */
+	ao2_ref(find_node, -1);
+
+	return found;
+}
+
+/*!
+ * \internal
+ * \brief Add a child node named 'name' to the 'parent' node.
+ * \param[in] parent Where to add the child node.
+ * \param[in] name The name of the child node.
+ * \retval NULL on error.
+ * \retval A newly allocated child in parent.
+ */
+static struct ast_data_search *data_search_add_child(struct ao2_container *parent,
+	const char *name)
+{
+	struct ast_data_search *child;
+
+	child = data_search_alloc(name);
+	if (!child) {
+		return NULL;
+	}
+
+	ao2_link(parent, child);
+
+	return child;
+}
+
+/*!
+ * \internal
+ * \brief Create the middle nodes for the specified path (asterisk/testnode1/childnode)
+ * \param[in] parent Where to add the middle nodes structure.
+ * \param[in] path The path of nodes to add.
+ * \retval NULL on error.
+ * \retval The created node.
+ */
+static struct ast_data_search *data_search_create(struct ao2_container *parent,
+	const char *path)
+{
+	char *rpath, *node_name;
+	struct ast_data_search *child, *ret = NULL;
+
+	rpath = ast_strdupa(path);
+
+	node_name = next_node_name(&rpath);
+	if (!node_name) {
+		/* no more nodes to create. */
+		return NULL;
+	}
+
+	child = data_search_find(parent, node_name);
+
+	if (!child) {
+		/* nodes without handler are non-terminal nodes. */
+		child = data_search_add_child(parent, node_name);
+	}
+
+	if (rpath) {
+		ret = data_search_create(child->children, rpath);
+		if (ret) {
+			ao2_ref(child, -1);
+		}
+	}
+
+	return ret ? ret : child;
+}
 
 /*!
  * \internal
  * \brief Allocate a tree with the search string parsed.
- * \TODO complete documentation.
+ * \param[in] search_string The search string.
+ * \retval NULL on error.
+ * \retval non-NULL A dynamically allocated search tree.
  */
 static struct ast_data_search *data_search_parse(const char *search_string)
 {
 	struct ast_str *name, *value, *comparison;
 	char *elements, *search_string_dup;
 	int i;
+	struct ast_data_search *root, *child;
 
 	if (!search_string) {
 		ast_log(LOG_ERROR, "You must pass a valid search string.\n");
@@ -615,6 +769,12 @@
 	search_string_dup = ast_strdupa(search_string);
 
 	elements = strtok(search_string_dup, ",");
+
+	/* Create the root node (just used as a container) */
+	root = data_search_alloc("/");
+	if (!root) {
+		return NULL;
+	}
 
 	while (elements) {
 		/* Parse the name */
@@ -629,7 +789,7 @@
 			/* if this is the end of the string, then this is
 			 * an error! */
 			ast_log(LOG_ERROR, "Invalid search string!\n");
-			break;
+			continue;
 		}
 
 		/* parse the comparison string. */
@@ -644,26 +804,27 @@
 			ast_str_append(&value, 0, "%c", elements[i]);
 		}
 
-		ast_log(LOG_ERROR, "NAME = %s\n", ast_str_buffer(name));
-		ast_log(LOG_ERROR, "VALUE = %s\n", ast_str_buffer(value));
-		ast_log(LOG_ERROR, "CMP = %s\n", ast_str_buffer(comparison));
-
 		/* add this node to the tree. */
+		child = data_search_create(root->children, ast_str_buffer(name));
+		if (child) {
+			child->cmp_type = data_search_comparison_type(ast_str_buffer(comparison));
+			child->value = ast_strdup(ast_str_buffer(value));
+		}
 
 		elements = strtok(NULL, ",");
 	}
 
-	return NULL;
-}
-
-/*!
- * \internal
- * \brief
- * \TODO complete documentation.
+	return root;
+}
+
+/*!
+ * \internal
+ * \brief Release the allocated memory for the search tree.
+ * \param[in] search The search tree root node.
  */
 static void data_search_release(struct ast_data_search *search)
 {
-
+	ao2_ref(search, -1);
 }
 
 /*!




More information about the asterisk-commits mailing list