blob: c9950f5fb73279c0f162b73fbff8937538ec9870 [file] [log] [blame]
Jon Medhurstaaf37a32013-06-11 12:10:56 +01001/*
2 * "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $"
3 *
4 * Attribute support code for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2003-2010 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 *
16 * Contents:
17 *
18 * mxmlElementDeleteAttr() - Delete an attribute.
19 * mxmlElementGetAttr() - Get an attribute.
20 * mxmlElementSetAttr() - Set an attribute.
21 * mxmlElementSetAttrf() - Set an attribute with a formatted value.
22 * mxml_set_attr() - Set or add an attribute name/value pair.
23 */
24
25/*
26 * Include necessary headers...
27 */
28
29#include "config.h"
30#include "mxml.h"
31
32
33/*
34 * Local functions...
35 */
36
37static int mxml_set_attr(mxml_node_t *node, const char *name,
38 char *value);
39
40
41/*
42 * 'mxmlElementDeleteAttr()' - Delete an attribute.
43 *
44 * @since Mini-XML 2.4@
45 */
46
47void
48mxmlElementDeleteAttr(mxml_node_t *node,/* I - Element */
49 const char *name)/* I - Attribute name */
50{
51 int i; /* Looping var */
52 mxml_attr_t *attr; /* Cirrent attribute */
53
54
55#ifdef DEBUG
56 fprintf(stderr, "mxmlElementDeleteAttr(node=%p, name=\"%s\")\n",
57 node, name ? name : "(null)");
58#endif /* DEBUG */
59
60 /*
61 * Range check input...
62 */
63
64 if (!node || node->type != MXML_ELEMENT || !name)
65 return;
66
67 /*
68 * Look for the attribute...
69 */
70
71 for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
72 i > 0;
73 i --, attr ++)
74 {
75#ifdef DEBUG
76 printf(" %s=\"%s\"\n", attr->name, attr->value);
77#endif /* DEBUG */
78
79 if (!strcmp(attr->name, name))
80 {
81 /*
82 * Delete this attribute...
83 */
84
85 free(attr->name);
86 free(attr->value);
87
88 i --;
89 if (i > 0)
90 memmove(attr, attr + 1, i * sizeof(mxml_attr_t));
91
92 node->value.element.num_attrs --;
93 return;
94 }
95 }
96}
97
98
99/*
100 * 'mxmlElementGetAttr()' - Get an attribute.
101 *
102 * This function returns NULL if the node is not an element or the
103 * named attribute does not exist.
104 */
105
106const char * /* O - Attribute value or NULL */
107mxmlElementGetAttr(mxml_node_t *node, /* I - Element node */
108 const char *name) /* I - Name of attribute */
109{
110 int i; /* Looping var */
111 mxml_attr_t *attr; /* Cirrent attribute */
112
113
114#ifdef DEBUG
115 fprintf(stderr, "mxmlElementGetAttr(node=%p, name=\"%s\")\n",
116 node, name ? name : "(null)");
117#endif /* DEBUG */
118
119 /*
120 * Range check input...
121 */
122
123 if (!node || node->type != MXML_ELEMENT || !name)
124 return (NULL);
125
126 /*
127 * Look for the attribute...
128 */
129
130 for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
131 i > 0;
132 i --, attr ++)
133 {
134#ifdef DEBUG
135 printf(" %s=\"%s\"\n", attr->name, attr->value);
136#endif /* DEBUG */
137
138 if (!strcmp(attr->name, name))
139 {
140#ifdef DEBUG
141 printf(" Returning \"%s\"!\n", attr->value);
142#endif /* DEBUG */
143 return (attr->value);
144 }
145 }
146
147 /*
148 * Didn't find attribute, so return NULL...
149 */
150
151#ifdef DEBUG
152 puts(" Returning NULL!\n");
153#endif /* DEBUG */
154
155 return (NULL);
156}
157
158
159/*
160 * 'mxmlElementSetAttr()' - Set an attribute.
161 *
162 * If the named attribute already exists, the value of the attribute
163 * is replaced by the new string value. The string value is copied
164 * into the element node. This function does nothing if the node is
165 * not an element.
166 */
167
168void
169mxmlElementSetAttr(mxml_node_t *node, /* I - Element node */
170 const char *name, /* I - Name of attribute */
171 const char *value) /* I - Attribute value */
172{
173 char *valuec; /* Copy of value */
174
175
176#ifdef DEBUG
177 fprintf(stderr, "mxmlElementSetAttr(node=%p, name=\"%s\", value=\"%s\")\n",
178 node, name ? name : "(null)", value ? value : "(null)");
179#endif /* DEBUG */
180
181 /*
182 * Range check input...
183 */
184
185 if (!node || node->type != MXML_ELEMENT || !name)
186 return;
187
188 if (value)
189 valuec = strdup(value);
190 else
191 valuec = NULL;
192
193 if (mxml_set_attr(node, name, valuec))
194 free(valuec);
195}
196
197
198/*
199 * 'mxmlElementSetAttrf()' - Set an attribute with a formatted value.
200 *
201 * If the named attribute already exists, the value of the attribute
202 * is replaced by the new formatted string. The formatted string value is
203 * copied into the element node. This function does nothing if the node
204 * is not an element.
205 *
206 * @since Mini-XML 2.3@
207 */
208
209void
210mxmlElementSetAttrf(mxml_node_t *node, /* I - Element node */
211 const char *name, /* I - Name of attribute */
212 const char *format,/* I - Printf-style attribute value */
213 ...) /* I - Additional arguments as needed */
214{
215 va_list ap; /* Argument pointer */
216 char *value; /* Value */
217
218
219#ifdef DEBUG
220 fprintf(stderr,
221 "mxmlElementSetAttrf(node=%p, name=\"%s\", format=\"%s\", ...)\n",
222 node, name ? name : "(null)", format ? format : "(null)");
223#endif /* DEBUG */
224
225 /*
226 * Range check input...
227 */
228
229 if (!node || node->type != MXML_ELEMENT || !name || !format)
230 return;
231
232 /*
233 * Format the value...
234 */
235
236 va_start(ap, format);
237 value = _mxml_vstrdupf(format, ap);
238 va_end(ap);
239
240 if (!value)
241 mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
242 name, node->value.element.name);
243 else if (mxml_set_attr(node, name, value))
244 free(value);
245}
246
247
248/*
249 * 'mxml_set_attr()' - Set or add an attribute name/value pair.
250 */
251
252static int /* O - 0 on success, -1 on failure */
253mxml_set_attr(mxml_node_t *node, /* I - Element node */
254 const char *name, /* I - Attribute name */
255 char *value) /* I - Attribute value */
256{
257 int i; /* Looping var */
258 mxml_attr_t *attr; /* New attribute */
259
260
261 /*
262 * Look for the attribute...
263 */
264
265 for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
266 i > 0;
267 i --, attr ++)
268 if (!strcmp(attr->name, name))
269 {
270 /*
271 * Free the old value as needed...
272 */
273
274 if (attr->value)
275 free(attr->value);
276
277 attr->value = value;
278
279 return (0);
280 }
281
282 /*
283 * Add a new attribute...
284 */
285
286 if (node->value.element.num_attrs == 0)
287 attr = malloc(sizeof(mxml_attr_t));
288 else
289 attr = realloc(node->value.element.attrs,
290 (node->value.element.num_attrs + 1) * sizeof(mxml_attr_t));
291
292 if (!attr)
293 {
294 mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
295 name, node->value.element.name);
296 return (-1);
297 }
298
299 node->value.element.attrs = attr;
300 attr += node->value.element.num_attrs;
301
302 if ((attr->name = strdup(name)) == NULL)
303 {
304 mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
305 name, node->value.element.name);
306 return (-1);
307 }
308
309 attr->value = value;
310
311 node->value.element.num_attrs ++;
312
313 return (0);
314}
315
316
317/*
318 * End of "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $".
319 */