don't blow up if a jitterbuffer is not in use
[asterisk/asterisk.git] / mxml / mxml-search.c
1 /*
2  * "$Id$"
3  *
4  * Search/navigation functions for Mini-XML, a small XML-like file
5  * parsing library.
6  *
7  * Copyright 2003-2005 by Michael Sweet.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * Contents:
20  *
21  *   mxmlFindElement() - Find the named element.
22  *   mxmlWalkNext()    - Walk to the next logical node in the tree.
23  *   mxmlWalkPrev()    - Walk to the previous logical node in the tree.
24  */
25
26 /*
27  * Include necessary headers...
28  */
29
30 #include "config.h"
31 #include "mxml.h"
32
33
34 /*
35  * 'mxmlFindElement()' - Find the named element.
36  *
37  * The search is constrained by the name, attribute name, and value; any
38  * NULL names or values are treated as wildcards, so different kinds of
39  * searches can be implemented by looking for all elements of a given name
40  * or all elements with a specific attribute. The descend argument determines
41  * whether the search descends into child nodes; normally you will use
42  * MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find
43  * additional direct descendents of the node. The top node argument
44  * constrains the search to a particular node's children.
45  */
46
47 mxml_node_t *                           /* O - Element node or NULL */
48 mxmlFindElement(mxml_node_t *node,      /* I - Current node */
49                 mxml_node_t *top,       /* I - Top node */
50                 const char  *name,      /* I - Element name or NULL for any */
51                 const char  *attr,      /* I - Attribute name, or NULL for none */
52                 const char  *value,     /* I - Attribute value, or NULL for any */
53                 int         descend)    /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
54 {
55   const char    *temp;                  /* Current attribute value */
56
57
58  /*
59   * Range check input...
60   */
61
62   if (!node || !top || (!attr && value))
63     return (NULL);
64
65  /*
66   * Start with the next node...
67   */
68
69   node = mxmlWalkNext(node, top, descend);
70
71  /*
72   * Loop until we find a matching element...
73   */
74
75   while (node != NULL)
76   {
77    /*
78     * See if this node matches...
79     */
80
81     if (node->type == MXML_ELEMENT &&
82         node->value.element.name &&
83         (!name || !strcmp(node->value.element.name, name)))
84     {
85      /*
86       * See if we need to check for an attribute...
87       */
88
89       if (!attr)
90         return (node);                  /* No attribute search, return it... */
91
92      /*
93       * Check for the attribute...
94       */
95
96       if ((temp = mxmlElementGetAttr(node, attr)) != NULL)
97       {
98        /*
99         * OK, we have the attribute, does it match?
100         */
101
102         if (!value || !strcmp(value, temp))
103           return (node);                /* Yes, return it... */
104       }
105     }
106
107    /*
108     * No match, move on to the next node...
109     */
110
111     if (descend == MXML_DESCEND)
112       node = mxmlWalkNext(node, top, MXML_DESCEND);
113     else
114       node = node->next;
115   }
116
117   return (NULL);
118 }
119
120
121 /*
122  * 'mxmlWalkNext()' - Walk to the next logical node in the tree.
123  *
124  * The descend argument controls whether the first child is considered
125  * to be the next node. The top node argument constrains the walk to
126  * the node's children.
127  */
128
129 mxml_node_t *                           /* O - Next node or NULL */
130 mxmlWalkNext(mxml_node_t *node,         /* I - Current node */
131              mxml_node_t *top,          /* I - Top node */
132              int         descend)       /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
133 {
134   if (!node)
135     return (NULL);
136   else if (node->child && descend)
137     return (node->child);
138   else if (node->next)
139     return (node->next);
140   else if (node->parent && node->parent != top)
141   {
142     node = node->parent;
143
144     while (!node->next)
145       if (node->parent == top || !node->parent)
146         return (NULL);
147       else
148         node = node->parent;
149
150     return (node->next);
151   }
152   else
153     return (NULL);
154 }
155
156
157 /*
158  * 'mxmlWalkPrev()' - Walk to the previous logical node in the tree.
159  *
160  * The descend argument controls whether the previous node's last child
161  * is considered to be the previous node. The top node argument constrains
162  * the walk to the node's children.
163  */
164
165 mxml_node_t *                           /* O - Previous node or NULL */
166 mxmlWalkPrev(mxml_node_t *node,         /* I - Current node */
167              mxml_node_t *top,          /* I - Top node */
168              int         descend)       /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
169 {
170   if (!node)
171     return (NULL);
172   else if (node->prev)
173   {
174     if (node->prev->last_child && descend)
175     {
176      /*
177       * Find the last child under the previous node...
178       */
179
180       node = node->prev->last_child;
181
182       while (node->last_child)
183         node = node->last_child;
184
185       return (node);
186     }
187     else
188       return (node->prev);
189   }
190   else if (node->parent != top)
191     return (node->parent);
192   else
193     return (NULL);
194 }
195
196
197 /*
198  * End of "$Id$".
199  */