Merge branch 'linux-3.10.y' of git://git.kernel.org/pub/scm/linux/kernel/git/stable...
[firefly-linux-kernel-4.4.55.git] / tools / gator / daemon / mxml / mxml-search.c
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 /*
19  * Include necessary headers...
20  */
21
22 #include "config.h"
23 #include "mxml.h"
24
25
26 /*
27  * 'mxmlFindElement()' - Find the named element.
28  *
29  * The search is constrained by the name, attribute name, and value; any
30  * NULL names or values are treated as wildcards, so different kinds of
31  * searches can be implemented by looking for all elements of a given name
32  * or all elements with a specific attribute. The descend argument determines
33  * whether the search descends into child nodes; normally you will use
34  * MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find
35  * additional direct descendents of the node. The top node argument
36  * constrains the search to a particular node's children.
37  */
38
39 mxml_node_t *                           /* O - Element node or NULL */
40 mxmlFindElement(mxml_node_t *node,      /* I - Current node */
41                 mxml_node_t *top,       /* I - Top node */
42                 const char  *name,      /* I - Element name or NULL for any */
43                 const char  *attr,      /* I - Attribute name, or NULL for none */
44                 const char  *value,     /* I - Attribute value, or NULL for any */
45                 int         descend)    /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
46 {
47   const char    *temp;                  /* Current attribute value */
48
49
50  /*
51   * Range check input...
52   */
53
54   if (!node || !top || (!attr && value))
55     return (NULL);
56
57  /*
58   * Start with the next node...
59   */
60
61   node = mxmlWalkNext(node, top, descend);
62
63  /*
64   * Loop until we find a matching element...
65   */
66
67   while (node != NULL)
68   {
69    /*
70     * See if this node matches...
71     */
72
73     if (node->type == MXML_ELEMENT &&
74         node->value.element.name &&
75         (!name || !strcmp(node->value.element.name, name)))
76     {
77      /*
78       * See if we need to check for an attribute...
79       */
80
81       if (!attr)
82         return (node);                  /* No attribute search, return it... */
83
84      /*
85       * Check for the attribute...
86       */
87
88       if ((temp = mxmlElementGetAttr(node, attr)) != NULL)
89       {
90        /*
91         * OK, we have the attribute, does it match?
92         */
93
94         if (!value || !strcmp(value, temp))
95           return (node);                /* Yes, return it... */
96       }
97     }
98
99    /*
100     * No match, move on to the next node...
101     */
102
103     if (descend == MXML_DESCEND)
104       node = mxmlWalkNext(node, top, MXML_DESCEND);
105     else
106       node = node->next;
107   }
108
109   return (NULL);
110 }
111
112
113 /*
114  * 'mxmlFindPath()' - Find a node with the given path.
115  *
116  * The "path" is a slash-separated list of element names. The name "*" is
117  * considered a wildcard for one or more levels of elements.  For example,
118  * "foo/one/two", "bar/two/one", "*\/one", and so forth.
119  *
120  * The first child node of the found node is returned if the given node has
121  * children and the first child is a value node.
122  *
123  * @since Mini-XML 2.7@
124  */
125
126 mxml_node_t *                           /* O - Found node or NULL */
127 mxmlFindPath(mxml_node_t *top,          /* I - Top node */
128              const char  *path)         /* I - Path to element */
129 {
130   mxml_node_t   *node;                  /* Current node */
131   char          element[256];           /* Current element name */
132   const char    *pathsep;               /* Separator in path */
133   int           descend;                /* mxmlFindElement option */
134
135
136  /*
137   * Range check input...
138   */
139
140   if (!top || !path || !*path)
141     return (NULL);
142
143  /*
144   * Search each element in the path...
145   */
146
147   node = top;
148   while (*path)
149   {
150    /*
151     * Handle wildcards...
152     */
153
154     if (!strncmp(path, "*/", 2))
155     {
156       path += 2;
157       descend = MXML_DESCEND;
158     }
159     else
160       descend = MXML_DESCEND_FIRST;
161
162    /*
163     * Get the next element in the path...
164     */
165
166     if ((pathsep = strchr(path, '/')) == NULL)
167       pathsep = path + strlen(path);
168
169     if (pathsep == path || (pathsep - path) >= sizeof(element))
170       return (NULL);
171
172     memcpy(element, path, pathsep - path);
173     element[pathsep - path] = '\0';
174
175     if (*pathsep)
176       path = pathsep + 1;
177     else
178       path = pathsep;
179
180    /*
181     * Search for the element...
182     */
183
184     if ((node = mxmlFindElement(node, node, element, NULL, NULL,
185                                 descend)) == NULL)
186       return (NULL);
187   }
188
189  /*
190   * If we get this far, return the node or its first child...
191   */
192
193   if (node->child && node->child->type != MXML_ELEMENT)
194     return (node->child);
195   else
196     return (node);
197 }
198
199
200 /*
201  * 'mxmlWalkNext()' - Walk to the next logical node in the tree.
202  *
203  * The descend argument controls whether the first child is considered
204  * to be the next node. The top node argument constrains the walk to
205  * the node's children.
206  */
207
208 mxml_node_t *                           /* O - Next node or NULL */
209 mxmlWalkNext(mxml_node_t *node,         /* I - Current node */
210              mxml_node_t *top,          /* I - Top node */
211              int         descend)       /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
212 {
213   if (!node)
214     return (NULL);
215   else if (node->child && descend)
216     return (node->child);
217   else if (node == top)
218     return (NULL);
219   else if (node->next)
220     return (node->next);
221   else if (node->parent && node->parent != top)
222   {
223     node = node->parent;
224
225     while (!node->next)
226       if (node->parent == top || !node->parent)
227         return (NULL);
228       else
229         node = node->parent;
230
231     return (node->next);
232   }
233   else
234     return (NULL);
235 }
236
237
238 /*
239  * 'mxmlWalkPrev()' - Walk to the previous logical node in the tree.
240  *
241  * The descend argument controls whether the previous node's last child
242  * is considered to be the previous node. The top node argument constrains
243  * the walk to the node's children.
244  */
245
246 mxml_node_t *                           /* O - Previous node or NULL */
247 mxmlWalkPrev(mxml_node_t *node,         /* I - Current node */
248              mxml_node_t *top,          /* I - Top node */
249              int         descend)       /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
250 {
251   if (!node || node == top)
252     return (NULL);
253   else if (node->prev)
254   {
255     if (node->prev->last_child && descend)
256     {
257      /*
258       * Find the last child under the previous node...
259       */
260
261       node = node->prev->last_child;
262
263       while (node->last_child)
264         node = node->last_child;
265
266       return (node);
267     }
268     else
269       return (node->prev);
270   }
271   else if (node->parent != top)
272     return (node->parent);
273   else
274     return (NULL);
275 }
276
277
278 /*
279  * End of "$Id: mxml-search.c 451 2014-01-04 21:50:06Z msweet $".
280  */