Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

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