Implement index sorting internally to avoid multithreading issues

with qsort().
web
Michael R Sweet 20 years ago
parent e6c90615c6
commit 56d571d240
  1. 10
      doc/reference.html
  2. 209
      mxml-index.c
  3. 4
      mxml.xml

@ -1212,7 +1212,6 @@ union mxml_value_u
<h2><a name='_variables'>Variables</a></h2> <h2><a name='_variables'>Variables</a></h2>
<ul> <ul>
<li><a href='#num_callbacks'><tt>num_callbacks</tt></a></li> <li><a href='#num_callbacks'><tt>num_callbacks</tt></a></li>
<li><a href='#sort_attr_name'><tt>sort_attr_name</tt></a></li>
</ul> </ul>
<!-- NEW PAGE --> <!-- NEW PAGE -->
<h3><a name='num_callbacks'>num_callbacks</a></h3> <h3><a name='num_callbacks'>num_callbacks</a></h3>
@ -1221,14 +1220,5 @@ union mxml_value_u
<pre> <pre>
static int num_callbacks = 1; static int num_callbacks = 1;
</pre> </pre>
<!-- NEW PAGE -->
<h3><a name='sort_attr_name'>sort_attr_name</a></h3>
<hr noshade/>
<h4>Description</h4>
<p>Current attribute to sort on</p>
<h4>Definition</h4>
<pre>
static const char * sort_attr_name;
</pre>
</body> </body>
</html> </html>

@ -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,
const char *value, mxml_node_t *node); mxml_node_t *second);
static int sort_attr(const void *a, const void *b); static int index_find(mxml_index_t *ind, const char *element,
static int sort_element(const void *a, const void *b); const char *value, mxml_node_t *node);
static int sort_element_attr(const void *a, const void *b); static void index_sort(mxml_index_t *ind, int left, int right);
/*
* 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,14 +346,53 @@ 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 */
const char *element, /* I - Element name or NULL */ mxml_node_t *first, /* I - First node */
const char *value, /* I - Attribute value or NULL */ mxml_node_t *second) /* I - Second node */
mxml_node_t *node) /* I - 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 *value, /* I - Attribute value or NULL */
mxml_node_t *node) /* I - Node */
{ {
int diff; /* Difference */ int diff; /* Difference */
@ -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 --;
{
int i; /* Result of comparison */
/*
* Swap nodes if needed...
*/
if ((i = strcmp(((mxml_node_t *)a)->value.element.name, if (templ < tempr)
((mxml_node_t *)b)->value.element.name)) != 0) {
return (i); temp = ind->nodes[templ];
else ind->nodes[templ] = ind->nodes[tempr];
return (strcmp(mxmlElementGetAttr((mxml_node_t *)a, sort_attr_name), ind->nodes[tempr] = temp;
mxmlElementGetAttr((mxml_node_t *)b, sort_attr_name))); }
}
/*
* When we get here, the right (tempr) node is the new position for the
* pivot node...
*/
ind->nodes[left] = ind->nodes[tempr];
ind->nodes[tempr] = pivot;
/*
* Recursively sort the left and right partitions as needed...
*/
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 $".
*/ */

@ -841,8 +841,4 @@ the walk to the node's children.</description>
<variable default="= 1" name="num_callbacks"> <variable default="= 1" name="num_callbacks">
<type>static int</type> <type>static int</type>
</variable> </variable>
<variable name="sort_attr_name">
<type>static const char *</type>
<description>Current attribute to sort on</description>
</variable>
</mxmldoc> </mxmldoc>

Loading…
Cancel
Save