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