|
|
@ -1,5 +1,5 @@ |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* "$Id: mxml-index.c,v 1.2 2004/05/16 13:09:44 mike Exp $" |
|
|
|
* "$Id: mxml-index.c,v 1.3 2004/05/16 13:45:56 mike Exp $" |
|
|
|
* |
|
|
|
* |
|
|
|
* Index support code for Mini-XML, a small XML-like file parsing library. |
|
|
|
* Index support code for Mini-XML, a small XML-like file parsing library. |
|
|
|
* |
|
|
|
* |
|
|
@ -23,9 +23,9 @@ |
|
|
|
* mxmlIndexNew() - Create a new index. |
|
|
|
* mxmlIndexNew() - Create a new index. |
|
|
|
* mxmlIndexReset() - Reset the enumeration/find pointer in the index and |
|
|
|
* mxmlIndexReset() - Reset the enumeration/find pointer in the index and |
|
|
|
* return the first node in the index. |
|
|
|
* return the first node in the index. |
|
|
|
* sort_attr() - Sort by attribute value... |
|
|
|
* index_compare() - Compare two nodes. |
|
|
|
* sort_attr() - Sort by element name... |
|
|
|
* index_find() - Compare a node with index values. |
|
|
|
* sort_element_attr() - Sort by element name and attribute value... |
|
|
|
* index_sort() - Sort the nodes in the index... |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -40,18 +40,11 @@ |
|
|
|
* Sort functions... |
|
|
|
* Sort functions... |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
static int index_compare(mxml_index_t *ind, const char *element, |
|
|
|
static int index_compare(mxml_index_t *ind, mxml_node_t *first, |
|
|
|
|
|
|
|
mxml_node_t *second); |
|
|
|
|
|
|
|
static int index_find(mxml_index_t *ind, const char *element, |
|
|
|
const char *value, mxml_node_t *node); |
|
|
|
const char *value, mxml_node_t *node); |
|
|
|
static int sort_attr(const void *a, const void *b); |
|
|
|
static void index_sort(mxml_index_t *ind, int left, int right); |
|
|
|
static int sort_element(const void *a, const void *b); |
|
|
|
|
|
|
|
static int sort_element_attr(const void *a, const void *b); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Sort attribute... |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char *sort_attr_name; /* Current attribute to sort on */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -168,14 +161,14 @@ mxmlIndexFind(mxml_index_t *ind, /* I - Index to search */ |
|
|
|
{ |
|
|
|
{ |
|
|
|
current = (first + last) / 2; |
|
|
|
current = (first + last) / 2; |
|
|
|
|
|
|
|
|
|
|
|
if ((diff = index_compare(ind, element, value, ind->nodes[current])) == 0) |
|
|
|
if ((diff = index_find(ind, element, value, ind->nodes[current])) == 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Found a match, move back to find the first... |
|
|
|
* Found a match, move back to find the first... |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
while (current > 0 && |
|
|
|
while (current > 0 && |
|
|
|
!index_compare(ind, element, value, ind->nodes[current - 1])) |
|
|
|
!index_find(ind, element, value, ind->nodes[current - 1])) |
|
|
|
current --; |
|
|
|
current --; |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -199,7 +192,7 @@ mxmlIndexFind(mxml_index_t *ind, /* I - Index to search */ |
|
|
|
current = (first + last) / 2; |
|
|
|
current = (first + last) / 2; |
|
|
|
ind->cur_node = ind->num_nodes; |
|
|
|
ind->cur_node = ind->num_nodes; |
|
|
|
|
|
|
|
|
|
|
|
if (!index_compare(ind, element, value, ind->nodes[current])) |
|
|
|
if (!index_find(ind, element, value, ind->nodes[current])) |
|
|
|
{ |
|
|
|
{ |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Found exactly one match... |
|
|
|
* Found exactly one match... |
|
|
@ -217,7 +210,7 @@ mxmlIndexFind(mxml_index_t *ind, /* I - Index to search */ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else if (ind->cur_node < ind->num_nodes && |
|
|
|
else if (ind->cur_node < ind->num_nodes && |
|
|
|
!index_compare(ind, element, value, ind->nodes[ind->cur_node])) |
|
|
|
!index_find(ind, element, value, ind->nodes[ind->cur_node])) |
|
|
|
{ |
|
|
|
{ |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Return the next matching node... |
|
|
|
* Return the next matching node... |
|
|
@ -306,42 +299,8 @@ mxmlIndexNew(mxml_node_t *node, /* I - XML node tree */ |
|
|
|
* Sort nodes based upon the search criteria... |
|
|
|
* Sort nodes based upon the search criteria... |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
if (ind->num_nodes > 0) |
|
|
|
if (ind->num_nodes > 1) |
|
|
|
{ |
|
|
|
index_sort(ind, 0, ind->num_nodes - 1); |
|
|
|
if (!element && attr) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Sort based upon the element name and attribute value... |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sort_attr_name = attr; |
|
|
|
|
|
|
|
ind->attr = strdup(attr); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
qsort(ind->nodes, ind->num_nodes, sizeof(mxml_node_t *), |
|
|
|
|
|
|
|
sort_element_attr); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (!element && !attr) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Sort based upon the element name... |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
qsort(ind->nodes, ind->num_nodes, sizeof(mxml_node_t *), |
|
|
|
|
|
|
|
sort_element); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (attr) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Sort based upon the attribute value... |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sort_attr_name = attr; |
|
|
|
|
|
|
|
ind->attr = strdup(attr); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
qsort(ind->nodes, ind->num_nodes, sizeof(mxml_node_t *), |
|
|
|
|
|
|
|
sort_attr); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Return the new index... |
|
|
|
* Return the new index... |
|
|
@ -387,11 +346,50 @@ mxmlIndexReset(mxml_index_t *ind) /* I - Index to reset */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* 'index_compare()' - Compare a node with index values. |
|
|
|
* 'index_compare()' - Compare two nodes. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
static int /* O - Result of comparison */ |
|
|
|
static int /* O - Result of comparison */ |
|
|
|
index_compare(mxml_index_t *ind, /* I - Index */ |
|
|
|
index_compare(mxml_index_t *ind, /* I - Index */ |
|
|
|
|
|
|
|
mxml_node_t *first, /* I - First node */ |
|
|
|
|
|
|
|
mxml_node_t *second) /* I - Second node */ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int diff; /* Difference */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Check the element name... |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((diff = strcmp(first->value.element.name, |
|
|
|
|
|
|
|
second->value.element.name)) != 0) |
|
|
|
|
|
|
|
return (diff); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Check the attribute value... |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ind->attr) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if ((diff = strcmp(mxmlElementGetAttr(first, ind->attr), |
|
|
|
|
|
|
|
mxmlElementGetAttr(second, ind->attr))) != 0) |
|
|
|
|
|
|
|
return (diff); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* No difference, return 0... |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* 'index_find()' - Compare a node with index values. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int /* O - Result of comparison */ |
|
|
|
|
|
|
|
index_find(mxml_index_t *ind, /* I - Index */ |
|
|
|
const char *element, /* I - Element name or NULL */ |
|
|
|
const char *element, /* I - Element name or NULL */ |
|
|
|
const char *value, /* I - Attribute value or NULL */ |
|
|
|
const char *value, /* I - Attribute value or NULL */ |
|
|
|
mxml_node_t *node) /* I - Node */ |
|
|
|
mxml_node_t *node) /* I - Node */ |
|
|
@ -428,51 +426,78 @@ index_compare(mxml_index_t *ind, /* I - Index */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* 'sort_attr()' - Sort by attribute value... |
|
|
|
* 'index_sort()' - Sort the nodes in the index... |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* This function implements the classic quicksort algorithm... |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
static int /* O - Result of comparison */ |
|
|
|
static void |
|
|
|
sort_attr(const void *a, /* I - First node */ |
|
|
|
index_sort(mxml_index_t *ind, /* I - Index to sort */ |
|
|
|
const void *b) /* I - Second node */ |
|
|
|
int left, /* I - Left node in partition */ |
|
|
|
|
|
|
|
int right) /* I - Right node in partition */ |
|
|
|
{ |
|
|
|
{ |
|
|
|
return (strcmp(mxmlElementGetAttr((mxml_node_t *)a, sort_attr_name), |
|
|
|
mxml_node_t *pivot, /* Pivot node */ |
|
|
|
mxmlElementGetAttr((mxml_node_t *)b, sort_attr_name))); |
|
|
|
*temp; /* Swap node */ |
|
|
|
} |
|
|
|
int templ, /* Temporary left node */ |
|
|
|
|
|
|
|
tempr; /* Temporary right node */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* 'sort_element()' - Sort by element name... |
|
|
|
* Sort the pivot in the current partition... |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
static int /* O - Result of comparison */ |
|
|
|
pivot = ind->nodes[left]; |
|
|
|
sort_element(const void *a, /* I - First node */ |
|
|
|
|
|
|
|
const void *b) /* I - Second node */ |
|
|
|
for (templ = left, tempr = right; templ < tempr;) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return (strcmp(((mxml_node_t *)a)->value.element.name, |
|
|
|
/*
|
|
|
|
((mxml_node_t *)b)->value.element.name)); |
|
|
|
* Move left while left node <= pivot node... |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while ((templ < right) && |
|
|
|
|
|
|
|
index_compare(ind, ind->nodes[templ], pivot) <= 0) |
|
|
|
|
|
|
|
templ ++; |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* 'sort_element_attr()' - Sort by element name and attribute value... |
|
|
|
* Move right while right node > pivot node... |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
static int /* O - Result of comparison */ |
|
|
|
while ((tempr > left) && |
|
|
|
sort_element_attr(const void *a, /* I - First node */ |
|
|
|
index_compare(ind, ind->nodes[tempr], pivot) > 0) |
|
|
|
const void *b) /* I - Second node */ |
|
|
|
tempr --; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Swap nodes if needed... |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (templ < tempr) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int i; /* Result of comparison */ |
|
|
|
temp = ind->nodes[templ]; |
|
|
|
|
|
|
|
ind->nodes[templ] = ind->nodes[tempr]; |
|
|
|
|
|
|
|
ind->nodes[tempr] = temp; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* When we get here, the right (tempr) node is the new position for the |
|
|
|
|
|
|
|
* pivot node... |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
if ((i = strcmp(((mxml_node_t *)a)->value.element.name, |
|
|
|
ind->nodes[left] = ind->nodes[tempr]; |
|
|
|
((mxml_node_t *)b)->value.element.name)) != 0) |
|
|
|
ind->nodes[tempr] = pivot; |
|
|
|
return (i); |
|
|
|
|
|
|
|
else |
|
|
|
/*
|
|
|
|
return (strcmp(mxmlElementGetAttr((mxml_node_t *)a, sort_attr_name), |
|
|
|
* Recursively sort the left and right partitions as needed... |
|
|
|
mxmlElementGetAttr((mxml_node_t *)b, sort_attr_name))); |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (left < (tempr - 1)) |
|
|
|
|
|
|
|
index_sort(ind, left, tempr - 1); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (right > (tempr + 1)) |
|
|
|
|
|
|
|
index_sort(ind, tempr + 1, right); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* End of "$Id: mxml-index.c,v 1.2 2004/05/16 13:09:44 mike Exp $". |
|
|
|
* End of "$Id: mxml-index.c,v 1.3 2004/05/16 13:45:56 mike Exp $". |
|
|
|
*/ |
|
|
|
*/ |
|
|
|