[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