/tools/gator/daemon/mxml/mxml-search.c

https://gitlab.com/pine64-android/linux-3.10 · C · 280 lines · 124 code · 51 blank · 105 comment · 60 complexity · 2855a5daa8b2d64bbc879b7c0cf074cc MD5 · raw file

  1. /*
  2. * "$Id: mxml-search.c 451 2014-01-04 21:50:06Z msweet $"
  3. *
  4. * Search/navigation functions for Mini-XML, a small XML-like file
  5. * parsing library.
  6. *
  7. * Copyright 2003-2014 by Michael R Sweet.
  8. *
  9. * These coded instructions, statements, and computer programs are the
  10. * property of Michael R Sweet and are protected by Federal copyright
  11. * law. Distribution and use rights are outlined in the file "COPYING"
  12. * which should have been included with this file. If this file is
  13. * missing or damaged, see the license at:
  14. *
  15. * http://www.msweet.org/projects.php/Mini-XML
  16. */
  17. /*
  18. * Include necessary headers...
  19. */
  20. #include "config.h"
  21. #include "mxml.h"
  22. /*
  23. * 'mxmlFindElement()' - Find the named element.
  24. *
  25. * The search is constrained by the name, attribute name, and value; any
  26. * NULL names or values are treated as wildcards, so different kinds of
  27. * searches can be implemented by looking for all elements of a given name
  28. * or all elements with a specific attribute. The descend argument determines
  29. * whether the search descends into child nodes; normally you will use
  30. * MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find
  31. * additional direct descendents of the node. The top node argument
  32. * constrains the search to a particular node's children.
  33. */
  34. mxml_node_t * /* O - Element node or NULL */
  35. mxmlFindElement(mxml_node_t *node, /* I - Current node */
  36. mxml_node_t *top, /* I - Top node */
  37. const char *name, /* I - Element name or NULL for any */
  38. const char *attr, /* I - Attribute name, or NULL for none */
  39. const char *value, /* I - Attribute value, or NULL for any */
  40. int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
  41. {
  42. const char *temp; /* Current attribute value */
  43. /*
  44. * Range check input...
  45. */
  46. if (!node || !top || (!attr && value))
  47. return (NULL);
  48. /*
  49. * Start with the next node...
  50. */
  51. node = mxmlWalkNext(node, top, descend);
  52. /*
  53. * Loop until we find a matching element...
  54. */
  55. while (node != NULL)
  56. {
  57. /*
  58. * See if this node matches...
  59. */
  60. if (node->type == MXML_ELEMENT &&
  61. node->value.element.name &&
  62. (!name || !strcmp(node->value.element.name, name)))
  63. {
  64. /*
  65. * See if we need to check for an attribute...
  66. */
  67. if (!attr)
  68. return (node); /* No attribute search, return it... */
  69. /*
  70. * Check for the attribute...
  71. */
  72. if ((temp = mxmlElementGetAttr(node, attr)) != NULL)
  73. {
  74. /*
  75. * OK, we have the attribute, does it match?
  76. */
  77. if (!value || !strcmp(value, temp))
  78. return (node); /* Yes, return it... */
  79. }
  80. }
  81. /*
  82. * No match, move on to the next node...
  83. */
  84. if (descend == MXML_DESCEND)
  85. node = mxmlWalkNext(node, top, MXML_DESCEND);
  86. else
  87. node = node->next;
  88. }
  89. return (NULL);
  90. }
  91. /*
  92. * 'mxmlFindPath()' - Find a node with the given path.
  93. *
  94. * The "path" is a slash-separated list of element names. The name "*" is
  95. * considered a wildcard for one or more levels of elements. For example,
  96. * "foo/one/two", "bar/two/one", "*\/one", and so forth.
  97. *
  98. * The first child node of the found node is returned if the given node has
  99. * children and the first child is a value node.
  100. *
  101. * @since Mini-XML 2.7@
  102. */
  103. mxml_node_t * /* O - Found node or NULL */
  104. mxmlFindPath(mxml_node_t *top, /* I - Top node */
  105. const char *path) /* I - Path to element */
  106. {
  107. mxml_node_t *node; /* Current node */
  108. char element[256]; /* Current element name */
  109. const char *pathsep; /* Separator in path */
  110. int descend; /* mxmlFindElement option */
  111. /*
  112. * Range check input...
  113. */
  114. if (!top || !path || !*path)
  115. return (NULL);
  116. /*
  117. * Search each element in the path...
  118. */
  119. node = top;
  120. while (*path)
  121. {
  122. /*
  123. * Handle wildcards...
  124. */
  125. if (!strncmp(path, "*/", 2))
  126. {
  127. path += 2;
  128. descend = MXML_DESCEND;
  129. }
  130. else
  131. descend = MXML_DESCEND_FIRST;
  132. /*
  133. * Get the next element in the path...
  134. */
  135. if ((pathsep = strchr(path, '/')) == NULL)
  136. pathsep = path + strlen(path);
  137. if (pathsep == path || (pathsep - path) >= sizeof(element))
  138. return (NULL);
  139. memcpy(element, path, pathsep - path);
  140. element[pathsep - path] = '\0';
  141. if (*pathsep)
  142. path = pathsep + 1;
  143. else
  144. path = pathsep;
  145. /*
  146. * Search for the element...
  147. */
  148. if ((node = mxmlFindElement(node, node, element, NULL, NULL,
  149. descend)) == NULL)
  150. return (NULL);
  151. }
  152. /*
  153. * If we get this far, return the node or its first child...
  154. */
  155. if (node->child && node->child->type != MXML_ELEMENT)
  156. return (node->child);
  157. else
  158. return (node);
  159. }
  160. /*
  161. * 'mxmlWalkNext()' - Walk to the next logical node in the tree.
  162. *
  163. * The descend argument controls whether the first child is considered
  164. * to be the next node. The top node argument constrains the walk to
  165. * the node's children.
  166. */
  167. mxml_node_t * /* O - Next node or NULL */
  168. mxmlWalkNext(mxml_node_t *node, /* I - Current node */
  169. mxml_node_t *top, /* I - Top node */
  170. int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
  171. {
  172. if (!node)
  173. return (NULL);
  174. else if (node->child && descend)
  175. return (node->child);
  176. else if (node == top)
  177. return (NULL);
  178. else if (node->next)
  179. return (node->next);
  180. else if (node->parent && node->parent != top)
  181. {
  182. node = node->parent;
  183. while (!node->next)
  184. if (node->parent == top || !node->parent)
  185. return (NULL);
  186. else
  187. node = node->parent;
  188. return (node->next);
  189. }
  190. else
  191. return (NULL);
  192. }
  193. /*
  194. * 'mxmlWalkPrev()' - Walk to the previous logical node in the tree.
  195. *
  196. * The descend argument controls whether the previous node's last child
  197. * is considered to be the previous node. The top node argument constrains
  198. * the walk to the node's children.
  199. */
  200. mxml_node_t * /* O - Previous node or NULL */
  201. mxmlWalkPrev(mxml_node_t *node, /* I - Current node */
  202. mxml_node_t *top, /* I - Top node */
  203. int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
  204. {
  205. if (!node || node == top)
  206. return (NULL);
  207. else if (node->prev)
  208. {
  209. if (node->prev->last_child && descend)
  210. {
  211. /*
  212. * Find the last child under the previous node...
  213. */
  214. node = node->prev->last_child;
  215. while (node->last_child)
  216. node = node->last_child;
  217. return (node);
  218. }
  219. else
  220. return (node->prev);
  221. }
  222. else if (node->parent != top)
  223. return (node->parent);
  224. else
  225. return (NULL);
  226. }
  227. /*
  228. * End of "$Id: mxml-search.c 451 2014-01-04 21:50:06Z msweet $".
  229. */