[asterisk-commits] bbryant: branch group/data_api_gsoc2009 r205354 - /team/group/data_api_gsoc20...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jul 8 14:31:46 CDT 2009


Author: bbryant
Date: Wed Jul  8 14:31:42 2009
New Revision: 205354

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=205354
Log:
Add in code for the filter functionality in the data API.

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=205354&r1=205353&r2=205354
==============================================================================
--- team/group/data_api_gsoc2009/main/data.c (original)
+++ team/group/data_api_gsoc2009/main/data.c Wed Jul  8 14:31:42 2009
@@ -33,6 +33,7 @@
 #include "asterisk/data.h"
 #include "asterisk/astobj2.h"
 #include "asterisk/xml.h"
+#include "asterisk/linkedlists.h"
 
 #define NUM_DATA_NODE_BUCKETS	60
 #define NUM_DATA_RESULT_BUCKETS 60
@@ -72,10 +73,16 @@
 	char name[0];
 };
 
-struct data_filter {
+struct data_filter_node;
+
+AST_LIST_HEAD(data_filter_list, data_filter_node);
+
+struct data_filter_node {
 	/*! \brief The list of filter or search requirements
 	           ( container of type struct ast_data ) */
-	struct ao2_container *children;
+	struct data_filter_list children;
+	AST_LIST_ENTRY(data_filter_node) next;
+	char name[0];
 };
 
 /*! \brief Type of comparisons allow in the search string. */
@@ -1072,6 +1079,96 @@
 
 /*!
  * \internal
+ * \brief Destroy a list of data filter nodes.
+ * \param[in] Data filter list to be destroyed.
+ */
+static void data_filter_list_destroy(struct data_filter_list *flist)
+{
+	struct data_filter_node *node;
+
+	AST_LIST_TRAVERSE(flist, node, next) {
+		if (node->children.first) {
+			data_filter_list_destroy(&(node->children));
+		}
+
+		free(node);
+	}
+}
+
+/*!
+ * \internal
+ * \brief Add a node to a filter list from a path
+ * \param[in] Filter list to add the path onto.
+ * \param[in] The path to add into the filter list.
+ */
+static struct data_filter_list *data_filter_add_node(struct data_filter_list *flist, char *path)
+{
+	int found;
+	struct data_filter_list **list_head = &flist;
+	struct data_filter_node *node;
+	char *token;
+
+	for (token = strtok(path, "/"); token; token = strtok(NULL, "/")) {
+		if (!flist) {
+			flist = ast_calloc(1, sizeof(*flist));
+		} else {
+			found = 0;
+
+			AST_LIST_TRAVERSE(flist, node, next) {
+				if (!strcasecmp(node->name, token)) {
+					found = 1;
+					break;
+				}
+			}
+
+			if (found) {
+				continue;
+			}
+		}
+
+		node = ast_calloc(1, sizeof(*node));
+		*(node->name) = '/';
+		strcpy(node->name + 1, token);
+		AST_LIST_INSERT_TAIL(flist, node, next);
+		flist = &(node->children);
+	}
+
+	return *list_head;
+}
+
+/*!
+ * \internal
+ * \brief Generate a filter list based on a filter string provided by the API user.
+ * \param[in] A filter string to create a filter from.
+ */
+static struct data_filter_list *data_filter_generate(const char *constfilter)
+{
+	struct data_filter_list *filter = NULL;
+	char *strfilter = ast_strdupa(constfilter), *token;
+	
+	for (token = strtok(strfilter, ","); token; token = strtok(NULL, ",")) {
+		filter = data_filter_add_node(filter, token);
+	}
+
+	return filter;
+}
+
+/*!
+ * \internal
+ * \brief XXX-document this
+ */
+#define data_filter_get_last_leaf(constpath) ({								\
+	char *path = ast_strdupa(constpath), *leaf = NULL, *token;				\
+																			\
+	for (token = strtok(path, "/"); token; token = strtok(NULL, ",")) {		\
+		leaf = token;														\
+	}																		\
+																			\
+	(leaf);																	\
+})
+
+/*!
+ * \internal
  * \brief Generate all the tree from a specified provider.
  * \param[in] query The query executed.
  * \param[in] root_provider The provider specified in the path of the query.
@@ -1082,18 +1179,25 @@
 static struct ast_data *__data_result_generate_node(const struct ast_data_query *query,
 	const struct data_provider *root_provider,
 	const char *parent_node_name,
-	struct data_filter *filter,
+	struct data_filter_list *flist,
 	const struct ast_data_search *search)
 {
+	int found;
+	char *pathtmp;
 	struct ast_data *generated, *node;
 	struct ao2_iterator i;
 	struct data_provider *provider;
+	struct data_filter_node *fnode, *fnode2;
 	struct ast_data_search *search_child = NULL;
 
 	node = data_result_create(parent_node_name);
 	if (!node) {
 		ast_log(LOG_ERROR, "Unable to allocate '%s' node\n", parent_node_name);
 		return NULL;
+	}
+
+	if (!flist) {
+		flist = data_filter_generate(query->filter);
 	}
 
 	if (root_provider->module) {
@@ -1104,7 +1208,24 @@
 	if (root_provider->handler && root_provider->handler->get) {
 		generated = root_provider->handler->get(search);
 		if (generated) {
-			data_result_add_child(node, generated);
+			pathtmp = data_filter_get_last_leaf(parent_node_name);
+
+			AST_LIST_TRAVERSE(flist, fnode, next) {
+				if (!strcasecmp(fnode->name, pathtmp)) {
+					AST_LIST_TRAVERSE(&(fnode->children), fnode2, next) {
+						if (!strcasecmp(fnode->name, generated->name)) {
+							data_result_add_child(node, generated);
+							found = 1;
+							break;
+						}
+					}
+
+					if (found) {
+						break;
+					}
+				}
+			}
+
 			ao2_ref(generated, -1);
 		}
 
@@ -1122,14 +1243,36 @@
 		if (search) {
 			search_child = data_search_find(search->children, provider->name);
 		}
-		generated = __data_result_generate_node(query, provider, provider->name, filter, search_child);
+		generated = __data_result_generate_node(query, provider, provider->name, flist, search_child);
 		ao2_ref(search_child, -1);
 
 		if (generated) {
-			data_result_add_child(node, generated);
+			pathtmp = data_filter_get_last_leaf(parent_node_name);
+
+			AST_LIST_TRAVERSE(flist, fnode, next) {
+				if (!strcasecmp(fnode->name, provider->name)) {
+					AST_LIST_TRAVERSE(&(fnode->children), fnode2, next) {
+						if (!strcasecmp(fnode2->name, generated->name)) {
+							data_result_add_child(node, generated);
+							found = 1;
+							break;
+						}
+					}
+
+					if (found) {
+						break;
+					}
+				}
+			}
+
 			ao2_ref(generated, -1);
 		}
 		ao2_ref(provider, -1);
+	}
+
+	/* Clean up the filter if we had one */
+	if (flist) {
+		data_filter_list_destroy(flist);
 	}
 
 	return node;




More information about the asterisk-commits mailing list