diff --git a/doc/reference.html b/doc/reference.html index c5a9c88..b0ac0de 100644 --- a/doc/reference.html +++ b/doc/reference.html @@ -307,7 +307,7 @@ mxmlFindElement(
Sort attribute...
+Delete an index.
void @@ -326,7 +326,9 @@ mxmlIndexDelete(mxmlIndexEnum()
Description
-Return the next node in the index.
+Return the next node in the index. + +Nodes are returned in the sorted order of the index.
Syntax
mxml_node_t * @@ -345,7 +347,12 @@ mxmlIndexEnum(mxmlIndexFind()
Description
-Find the next matching node.
+Find the next matching node. + +You should call mxmlIndexReset() prior to using this function for +the first time with a particular set of "element" and "value" +strings. Passing NULL for both "element" and "value" is equivalent +to calling mxmlIndexEnum().
Syntax
mxml_node_t * @@ -368,7 +375,13 @@ mxmlIndexFind(mxmlIndexNew()
Description
-Create a new index.
+Create a new index. + +The index will contain all nodes that contain the named element and/or +attribute. If both "element" and "attr" are NULL, then the index will +contain a sorted list of the elements in the node tree. Nodes are +sorted by element name and optionally by attribute value if the "attr" +argument is not NULL.
Syntax
mxml_index_t * @@ -391,7 +404,11 @@ mxmlIndexNew(mxmlIndexReset()
Description
-Return the first node in the index.
+Reset the enumeration/find pointer in the index and +return the first node in the index. + +This function should be called prior to using mxmlIndexEnum() or +mxmlIndexFind() for the first time.
Syntax
mxml_node_t * @@ -1208,7 +1225,7 @@ static int num_callbacks = 1;sort_attr_name
Description
-Delete an index.
+Current attribute to sort on
Definition
static const char * sort_attr_name; diff --git a/mxml-index.c b/mxml-index.c index 27e7668..0438b96 100644 --- a/mxml-index.c +++ b/mxml-index.c @@ -1,5 +1,5 @@ /* - * "$Id: mxml-index.c,v 1.1 2004/05/16 05:25:38 mike Exp $" + * "$Id: mxml-index.c,v 1.2 2004/05/16 13:09:44 mike Exp $" * * Index support code for Mini-XML, a small XML-like file parsing library. * @@ -21,7 +21,8 @@ * mxmlIndexEnum() - Return the next node in the index. * mxmlIndexFind() - Find the next matching node. * mxmlIndexNew() - Create a new index. - * mxmlIndexReset() - Return the first node in the index. + * mxmlIndexReset() - Reset the enumeration/find pointer in the index and + * return the first node in the index. * sort_attr() - Sort by attribute value... * sort_attr() - Sort by element name... * sort_element_attr() - Sort by element name and attribute value... @@ -39,6 +40,8 @@ * Sort functions... */ +static int index_compare(mxml_index_t *ind, const char *element, + const char *value, mxml_node_t *node); static int sort_attr(const void *a, const void *b); static int sort_element(const void *a, const void *b); static int sort_element_attr(const void *a, const void *b); @@ -48,7 +51,7 @@ static int sort_element_attr(const void *a, const void *b); * Sort attribute... */ -static const char *sort_attr_name; +static const char *sort_attr_name; /* Current attribute to sort on */ /* @@ -81,6 +84,8 @@ mxmlIndexDelete(mxml_index_t *ind) /* I - Index to delete */ /* * 'mxmlIndexEnum()' - Return the next node in the index. + * + * Nodes are returned in the sorted order of the index. */ mxml_node_t * /* O - Next node or NULL if there is none */ @@ -106,6 +111,11 @@ mxmlIndexEnum(mxml_index_t *ind) /* I - Index to enumerate */ /* * 'mxmlIndexFind()' - Find the next matching node. + * + * You should call mxmlIndexReset() prior to using this function for + * the first time with a particular set of "element" and "value" + * strings. Passing NULL for both "element" and "value" is equivalent + * to calling mxmlIndexEnum(). */ mxml_node_t * /* O - Node or NULL if none found */ @@ -113,7 +123,10 @@ mxmlIndexFind(mxml_index_t *ind, /* I - Index to search */ const char *element, /* I - Element name to find, if any */ const char *value) /* I - Attribute value, if any */ { - int i, j; /* Looping vars */ + int diff, /* Difference between names */ + current, /* Current entity in search */ + first, /* First entity in search */ + last; /* Last entity in search */ /* @@ -132,58 +145,85 @@ mxmlIndexFind(mxml_index_t *ind, /* I - Index to search */ return (mxmlIndexEnum(ind)); /* - * Find the node... + * If there are no nodes in the index, return NULL... */ - for (i = ind->cur_node; i < ind->num_nodes; i ++) + if (!ind->num_nodes) + return (NULL); + + /* + * If cur_node == 0, then find the first matching node... + */ + + if (ind->cur_node == 0) { /* - * Check the element name... + * Find the first node using a modified binary search algorithm... */ - if (element) + first = 0; + last = ind->num_nodes - 1; + + while (last > first) { - if ((j = strcmp(element, ind->nodes[i]->value.element.name)) > 0) + current = (first + last) / 2; + + if ((diff = index_compare(ind, element, value, ind->nodes[current])) == 0) { /* - * No more elements <= name... + * Found a match, move back to find the first... */ - ind->cur_node = ind->num_nodes; + while (current > 0 && + !index_compare(ind, element, value, ind->nodes[current - 1])) + current --; - return (NULL); + /* + * Return the first match and save the index to the next... + */ + + ind->cur_node = current + 1; + + return (ind->nodes[current]); } - else if (j < 0) - continue; + else if (diff < 0) + last = current; + else + first = current; } /* - * Check the attribute value... + * If we get this far, then we found exactly 0 or 1 matches... */ - if (value) + current = (first + last) / 2; + ind->cur_node = ind->num_nodes; + + if (!index_compare(ind, element, value, ind->nodes[current])) { - if ((j = strcmp(value, mxmlElementGetAttr(ind->nodes[i], ind->attr))) > 0) - { - /* - * No more attributes <= value... - */ + /* + * Found exactly one match... + */ - ind->cur_node = ind->num_nodes; - - return (NULL); - } - else if (j != 0) - continue; + return (ind->nodes[current]); } + else + { + /* + * No matches... + */ + return (NULL); + } + } + else if (ind->cur_node < ind->num_nodes && + !index_compare(ind, element, value, ind->nodes[ind->cur_node])) + { /* - * Got a match, return it... + * Return the next matching node... */ - ind->cur_node = i + 1; - - return (ind->nodes[i]); + return (ind->nodes[ind->cur_node ++]); } /* @@ -198,6 +238,12 @@ mxmlIndexFind(mxml_index_t *ind, /* I - Index to search */ /* * 'mxmlIndexNew()' - Create a new index. + * + * The index will contain all nodes that contain the named element and/or + * attribute. If both "element" and "attr" are NULL, then the index will + * contain a sorted list of the elements in the node tree. Nodes are + * sorted by element name and optionally by attribute value if the "attr" + * argument is not NULL. */ mxml_index_t * /* O - New index */ @@ -306,7 +352,11 @@ mxmlIndexNew(mxml_node_t *node, /* I - XML node tree */ /* - * 'mxmlIndexReset()' - Return the first node in the index. + * 'mxmlIndexReset()' - Reset the enumeration/find pointer in the index and + * return the first node in the index. + * + * This function should be called prior to using mxmlIndexEnum() or + * mxmlIndexFind() for the first time. */ mxml_node_t * /* O - First node or NULL if there is none */ @@ -330,12 +380,53 @@ mxmlIndexReset(mxml_index_t *ind) /* I - Index to reset */ */ if (ind->num_nodes) - return (ind->nodes); + return (ind->nodes[0]); else return (NULL); } +/* + * 'index_compare()' - Compare a node with index values. + */ + +static int /* O - Result of comparison */ +index_compare(mxml_index_t *ind, /* I - Index */ + const char *element, /* I - Element name or NULL */ + const char *value, /* I - Attribute value or NULL */ + mxml_node_t *node) /* I - Node */ +{ + int diff; /* Difference */ + + + /* + * Check the element name... + */ + + if (element) + { + if ((diff = strcmp(element, node->value.element.name)) != 0) + return (diff); + } + + /* + * Check the attribute value... + */ + + if (value) + { + if ((diff = strcmp(value, mxmlElementGetAttr(node, ind->attr))) != 0) + return (diff); + } + + /* + * No difference, return 0... + */ + + return (0); +} + + /* * 'sort_attr()' - Sort by attribute value... */ @@ -383,5 +474,5 @@ sort_element_attr(const void *a, /* I - First node */ /* - * End of "$Id: mxml-index.c,v 1.1 2004/05/16 05:25:38 mike Exp $". + * End of "$Id: mxml-index.c,v 1.2 2004/05/16 13:09:44 mike Exp $". */ diff --git a/mxml.xml b/mxml.xml index 1faaa96..83938de 100644 --- a/mxml.xml +++ b/mxml.xml @@ -156,7 +156,7 @@ constrains the search to a particular node's children.- Sort attribute... +Delete an index. mxml_index_t * Index to delete @@ -167,7 +167,9 @@ constrains the search to a particular node's children.mxml_node_t * Next node or NULL if there is none -Return the next node in the index. +Return the next node in the index. + +Nodes are returned in the sorted order of the index. mxml_index_t * Index to enumerate @@ -178,7 +180,12 @@ constrains the search to a particular node's children.mxml_node_t * Node or NULL if none found -Find the next matching node. +Find the next matching node. + +You should call mxmlIndexReset() prior to using this function for +the first time with a particular set of "element" and "value" +strings. Passing NULL for both "element" and "value" is equivalent +to calling mxmlIndexEnum(). mxml_index_t * Index to search @@ -197,7 +204,13 @@ constrains the search to a particular node's children.mxml_index_t * New index -Create a new index. +Create a new index. + +The index will contain all nodes that contain the named element and/or +attribute. If both "element" and "attr" are NULL, then the index will +contain a sorted list of the elements in the node tree. Nodes are +sorted by element name and optionally by attribute value if the "attr" +argument is not NULL. mxml_node_t * XML node tree @@ -216,7 +229,11 @@ constrains the search to a particular node's children.mxml_node_t * First node or NULL if there is none -Return the first node in the index. +Reset the enumeration/find pointer in the index and +return the first node in the index. + +This function should be called prior to using mxmlIndexEnum() or +mxmlIndexFind() for the first time. mxml_index_t * Index to reset @@ -826,6 +843,6 @@ the walk to the node's children.static const char * -Delete an index. +Current attribute to sort on