[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