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