root / logic / trunk / src / mxml / mxml-node.c @ 69
History | View | Annotate | Download (17.9 KB)
1 | 49 | Janez1 | /*
|
---|---|---|---|
2 | * "$Id: mxml-node.c 363 2008-10-26 18:28:05Z mike $"
|
||
3 | *
|
||
4 | * Node support code for Mini-XML, a small XML-like file parsing library.
|
||
5 | *
|
||
6 | * Copyright 2003-2007 by Michael Sweet.
|
||
7 | *
|
||
8 | * This program is free software; you can redistribute it and/or
|
||
9 | * modify it under the terms of the GNU Library General Public
|
||
10 | * License as published by the Free Software Foundation; either
|
||
11 | * version 2, or (at your option) any later version.
|
||
12 | *
|
||
13 | * This program is distributed in the hope that it will be useful,
|
||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
16 | * GNU General Public License for more details.
|
||
17 | *
|
||
18 | * Contents:
|
||
19 | *
|
||
20 | * mxmlAdd() - Add a node to a tree.
|
||
21 | * mxmlDelete() - Delete a node and all of its children.
|
||
22 | * mxmlNewCDATA() - Create a new CDATA node.
|
||
23 | * mxmlNewCustom() - Create a new custom data node.
|
||
24 | * mxmlNewElement() - Create a new element node.
|
||
25 | * mxmlNewInteger() - Create a new integer node.
|
||
26 | * mxmlNewOpaque() - Create a new opaque string.
|
||
27 | * mxmlNewReal() - Create a new real number node.
|
||
28 | * mxmlNewText() - Create a new text fragment node.
|
||
29 | * mxmlNewTextf() - Create a new formatted text fragment node.
|
||
30 | * mxmlNewXML() - Create a new XML document tree.
|
||
31 | * mxmlRelease() - Release a node.
|
||
32 | * mxmlRemove() - Remove a node from its parent.
|
||
33 | * mxmlRetain() - Retain a node.
|
||
34 | * mxml_new() - Create a new node.
|
||
35 | */
|
||
36 | |||
37 | /*
|
||
38 | * Include necessary headers...
|
||
39 | */
|
||
40 | |||
41 | #include "config.h" |
||
42 | #include "mxml.h" |
||
43 | |||
44 | |||
45 | /*
|
||
46 | * Local functions...
|
||
47 | */
|
||
48 | |||
49 | static mxml_node_t *mxml_new(mxml_node_t *parent, mxml_type_t type);
|
||
50 | |||
51 | |||
52 | /*
|
||
53 | * 'mxmlAdd()' - Add a node to a tree.
|
||
54 | *
|
||
55 | * Adds the specified node to the parent. If the child argument is not
|
||
56 | * NULL, puts the new node before or after the specified child depending
|
||
57 | * on the value of the where argument. If the child argument is NULL,
|
||
58 | * puts the new node at the beginning of the child list (MXML_ADD_BEFORE)
|
||
59 | * or at the end of the child list (MXML_ADD_AFTER). The constant
|
||
60 | * MXML_ADD_TO_PARENT can be used to specify a NULL child pointer.
|
||
61 | */
|
||
62 | |||
63 | void
|
||
64 | mxmlAdd(mxml_node_t *parent, /* I - Parent node */
|
||
65 | int where, /* I - Where to add, MXML_ADD_BEFORE or MXML_ADD_AFTER */ |
||
66 | mxml_node_t *child, /* I - Child node for where or MXML_ADD_TO_PARENT */
|
||
67 | mxml_node_t *node) /* I - Node to add */
|
||
68 | { |
||
69 | #ifdef DEBUG
|
||
70 | fprintf(stderr, "mxmlAdd(parent=%p, where=%d, child=%p, node=%p)\n", parent,
|
||
71 | where, child, node); |
||
72 | #endif /* DEBUG */ |
||
73 | |||
74 | /*
|
||
75 | * Range check input...
|
||
76 | */
|
||
77 | |||
78 | if (!parent || !node)
|
||
79 | return;
|
||
80 | |||
81 | #if DEBUG > 1 |
||
82 | fprintf(stderr, " BEFORE: node->parent=%p\n", node->parent);
|
||
83 | if (parent)
|
||
84 | { |
||
85 | fprintf(stderr, " BEFORE: parent->child=%p\n", parent->child);
|
||
86 | fprintf(stderr, " BEFORE: parent->last_child=%p\n", parent->last_child);
|
||
87 | fprintf(stderr, " BEFORE: parent->prev=%p\n", parent->prev);
|
||
88 | fprintf(stderr, " BEFORE: parent->next=%p\n", parent->next);
|
||
89 | } |
||
90 | #endif /* DEBUG > 1 */ |
||
91 | |||
92 | /*
|
||
93 | * Remove the node from any existing parent...
|
||
94 | */
|
||
95 | |||
96 | if (node->parent)
|
||
97 | mxmlRemove(node); |
||
98 | |||
99 | /*
|
||
100 | * Reset pointers...
|
||
101 | */
|
||
102 | |||
103 | node->parent = parent; |
||
104 | |||
105 | switch (where)
|
||
106 | { |
||
107 | case MXML_ADD_BEFORE :
|
||
108 | if (!child || child == parent->child || child->parent != parent)
|
||
109 | { |
||
110 | /*
|
||
111 | * Insert as first node under parent...
|
||
112 | */
|
||
113 | |||
114 | node->next = parent->child; |
||
115 | |||
116 | if (parent->child)
|
||
117 | parent->child->prev = node; |
||
118 | else
|
||
119 | parent->last_child = node; |
||
120 | |||
121 | parent->child = node; |
||
122 | } |
||
123 | else
|
||
124 | { |
||
125 | /*
|
||
126 | * Insert node before this child...
|
||
127 | */
|
||
128 | |||
129 | node->next = child; |
||
130 | node->prev = child->prev; |
||
131 | |||
132 | if (child->prev)
|
||
133 | child->prev->next = node; |
||
134 | else
|
||
135 | parent->child = node; |
||
136 | |||
137 | child->prev = node; |
||
138 | } |
||
139 | break;
|
||
140 | |||
141 | case MXML_ADD_AFTER :
|
||
142 | if (!child || child == parent->last_child || child->parent != parent)
|
||
143 | { |
||
144 | /*
|
||
145 | * Insert as last node under parent...
|
||
146 | */
|
||
147 | |||
148 | node->parent = parent; |
||
149 | node->prev = parent->last_child; |
||
150 | |||
151 | if (parent->last_child)
|
||
152 | parent->last_child->next = node; |
||
153 | else
|
||
154 | parent->child = node; |
||
155 | |||
156 | parent->last_child = node; |
||
157 | } |
||
158 | else
|
||
159 | { |
||
160 | /*
|
||
161 | * Insert node after this child...
|
||
162 | */
|
||
163 | |||
164 | node->prev = child; |
||
165 | node->next = child->next; |
||
166 | |||
167 | if (child->next)
|
||
168 | child->next->prev = node; |
||
169 | else
|
||
170 | parent->last_child = node; |
||
171 | |||
172 | child->next = node; |
||
173 | } |
||
174 | break;
|
||
175 | } |
||
176 | |||
177 | #if DEBUG > 1 |
||
178 | fprintf(stderr, " AFTER: node->parent=%p\n", node->parent);
|
||
179 | if (parent)
|
||
180 | { |
||
181 | fprintf(stderr, " AFTER: parent->child=%p\n", parent->child);
|
||
182 | fprintf(stderr, " AFTER: parent->last_child=%p\n", parent->last_child);
|
||
183 | fprintf(stderr, " AFTER: parent->prev=%p\n", parent->prev);
|
||
184 | fprintf(stderr, " AFTER: parent->next=%p\n", parent->next);
|
||
185 | } |
||
186 | #endif /* DEBUG > 1 */ |
||
187 | } |
||
188 | |||
189 | |||
190 | /*
|
||
191 | * 'mxmlDelete()' - Delete a node and all of its children.
|
||
192 | *
|
||
193 | * If the specified node has a parent, this function first removes the
|
||
194 | * node from its parent using the mxmlRemove() function.
|
||
195 | */
|
||
196 | |||
197 | void
|
||
198 | mxmlDelete(mxml_node_t *node) /* I - Node to delete */
|
||
199 | { |
||
200 | int i; /* Looping var */ |
||
201 | |||
202 | |||
203 | #ifdef DEBUG
|
||
204 | fprintf(stderr, "mxmlDelete(node=%p)\n", node);
|
||
205 | #endif /* DEBUG */ |
||
206 | |||
207 | /*
|
||
208 | * Range check input...
|
||
209 | */
|
||
210 | |||
211 | if (!node)
|
||
212 | return;
|
||
213 | |||
214 | /*
|
||
215 | * Remove the node from its parent, if any...
|
||
216 | */
|
||
217 | |||
218 | mxmlRemove(node); |
||
219 | |||
220 | /*
|
||
221 | * Delete children...
|
||
222 | */
|
||
223 | |||
224 | while (node->child)
|
||
225 | mxmlDelete(node->child); |
||
226 | |||
227 | /*
|
||
228 | * Now delete any node data...
|
||
229 | */
|
||
230 | |||
231 | switch (node->type)
|
||
232 | { |
||
233 | case MXML_ELEMENT :
|
||
234 | if (node->value.element.name)
|
||
235 | free(node->value.element.name); |
||
236 | |||
237 | if (node->value.element.num_attrs)
|
||
238 | { |
||
239 | for (i = 0; i < node->value.element.num_attrs; i ++) |
||
240 | { |
||
241 | if (node->value.element.attrs[i].name)
|
||
242 | free(node->value.element.attrs[i].name); |
||
243 | if (node->value.element.attrs[i].value)
|
||
244 | free(node->value.element.attrs[i].value); |
||
245 | } |
||
246 | |||
247 | free(node->value.element.attrs); |
||
248 | } |
||
249 | break;
|
||
250 | case MXML_INTEGER :
|
||
251 | /* Nothing to do */
|
||
252 | break;
|
||
253 | case MXML_OPAQUE :
|
||
254 | if (node->value.opaque)
|
||
255 | free(node->value.opaque); |
||
256 | break;
|
||
257 | case MXML_REAL :
|
||
258 | /* Nothing to do */
|
||
259 | break;
|
||
260 | case MXML_TEXT :
|
||
261 | if (node->value.text.string)
|
||
262 | free(node->value.text.string); |
||
263 | break;
|
||
264 | case MXML_CUSTOM :
|
||
265 | if (node->value.custom.data &&
|
||
266 | node->value.custom.destroy) |
||
267 | (*(node->value.custom.destroy))(node->value.custom.data); |
||
268 | break;
|
||
269 | default :
|
||
270 | break;
|
||
271 | } |
||
272 | |||
273 | /*
|
||
274 | * Free this node...
|
||
275 | */
|
||
276 | |||
277 | free(node); |
||
278 | } |
||
279 | |||
280 | |||
281 | /*
|
||
282 | * 'mxmlNewCDATA()' - Create a new CDATA node.
|
||
283 | *
|
||
284 | * The new CDATA node is added to the end of the specified parent's child
|
||
285 | * list. The constant MXML_NO_PARENT can be used to specify that the new
|
||
286 | * CDATA node has no parent. The data string must be nul-terminated and
|
||
287 | * is copied into the new node. CDATA nodes use the MXML_ELEMENT type.
|
||
288 | *
|
||
289 | * @since Mini-XML 2.3@
|
||
290 | */
|
||
291 | |||
292 | mxml_node_t * /* O - New node */
|
||
293 | mxmlNewCDATA(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
|
||
294 | const char *data) /* I - Data string */ |
||
295 | { |
||
296 | mxml_node_t *node; /* New node */
|
||
297 | |||
298 | |||
299 | #ifdef DEBUG
|
||
300 | fprintf(stderr, "mxmlNewCDATA(parent=%p, data=\"%s\")\n",
|
||
301 | parent, data ? data : "(null)");
|
||
302 | #endif /* DEBUG */ |
||
303 | |||
304 | /*
|
||
305 | * Range check input...
|
||
306 | */
|
||
307 | |||
308 | if (!data)
|
||
309 | return (NULL); |
||
310 | |||
311 | /*
|
||
312 | * Create the node and set the name value...
|
||
313 | */
|
||
314 | |||
315 | if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL) |
||
316 | node->value.element.name = _mxml_strdupf("![CDATA[%s]]", data);
|
||
317 | |||
318 | return (node);
|
||
319 | } |
||
320 | |||
321 | |||
322 | /*
|
||
323 | * 'mxmlNewCustom()' - Create a new custom data node.
|
||
324 | *
|
||
325 | * The new custom node is added to the end of the specified parent's child
|
||
326 | * list. The constant MXML_NO_PARENT can be used to specify that the new
|
||
327 | * element node has no parent. NULL can be passed when the data in the
|
||
328 | * node is not dynamically allocated or is separately managed.
|
||
329 | *
|
||
330 | * @since Mini-XML 2.1@
|
||
331 | */
|
||
332 | |||
333 | mxml_node_t * /* O - New node */
|
||
334 | mxmlNewCustom( |
||
335 | mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
|
||
336 | void *data, /* I - Pointer to data */ |
||
337 | mxml_custom_destroy_cb_t destroy) /* I - Function to destroy data */
|
||
338 | { |
||
339 | mxml_node_t *node; /* New node */
|
||
340 | |||
341 | |||
342 | #ifdef DEBUG
|
||
343 | fprintf(stderr, "mxmlNewCustom(parent=%p, data=%p, destroy=%p)\n", parent,
|
||
344 | data, destroy); |
||
345 | #endif /* DEBUG */ |
||
346 | |||
347 | /*
|
||
348 | * Create the node and set the value...
|
||
349 | */
|
||
350 | |||
351 | if ((node = mxml_new(parent, MXML_CUSTOM)) != NULL) |
||
352 | { |
||
353 | node->value.custom.data = data; |
||
354 | node->value.custom.destroy = destroy; |
||
355 | } |
||
356 | |||
357 | return (node);
|
||
358 | } |
||
359 | |||
360 | |||
361 | /*
|
||
362 | * 'mxmlNewElement()' - Create a new element node.
|
||
363 | *
|
||
364 | * The new element node is added to the end of the specified parent's child
|
||
365 | * list. The constant MXML_NO_PARENT can be used to specify that the new
|
||
366 | * element node has no parent.
|
||
367 | */
|
||
368 | |||
369 | mxml_node_t * /* O - New node */
|
||
370 | mxmlNewElement(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
|
||
371 | const char *name) /* I - Name of element */ |
||
372 | { |
||
373 | mxml_node_t *node; /* New node */
|
||
374 | |||
375 | |||
376 | #ifdef DEBUG
|
||
377 | fprintf(stderr, "mxmlNewElement(parent=%p, name=\"%s\")\n", parent,
|
||
378 | name ? name : "(null)");
|
||
379 | #endif /* DEBUG */ |
||
380 | |||
381 | /*
|
||
382 | * Range check input...
|
||
383 | */
|
||
384 | |||
385 | if (!name)
|
||
386 | return (NULL); |
||
387 | |||
388 | /*
|
||
389 | * Create the node and set the element name...
|
||
390 | */
|
||
391 | |||
392 | if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL) |
||
393 | node->value.element.name = strdup(name); |
||
394 | |||
395 | return (node);
|
||
396 | } |
||
397 | |||
398 | |||
399 | /*
|
||
400 | * 'mxmlNewInteger()' - Create a new integer node.
|
||
401 | *
|
||
402 | * The new integer node is added to the end of the specified parent's child
|
||
403 | * list. The constant MXML_NO_PARENT can be used to specify that the new
|
||
404 | * integer node has no parent.
|
||
405 | */
|
||
406 | |||
407 | mxml_node_t * /* O - New node */
|
||
408 | mxmlNewInteger(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
|
||
409 | int integer) /* I - Integer value */ |
||
410 | { |
||
411 | mxml_node_t *node; /* New node */
|
||
412 | |||
413 | |||
414 | #ifdef DEBUG
|
||
415 | fprintf(stderr, "mxmlNewInteger(parent=%p, integer=%d)\n", parent, integer);
|
||
416 | #endif /* DEBUG */ |
||
417 | |||
418 | /*
|
||
419 | * Create the node and set the element name...
|
||
420 | */
|
||
421 | |||
422 | if ((node = mxml_new(parent, MXML_INTEGER)) != NULL) |
||
423 | node->value.integer = integer; |
||
424 | |||
425 | return (node);
|
||
426 | } |
||
427 | |||
428 | |||
429 | /*
|
||
430 | * 'mxmlNewOpaque()' - Create a new opaque string.
|
||
431 | *
|
||
432 | * The new opaque node is added to the end of the specified parent's child
|
||
433 | * list. The constant MXML_NO_PARENT can be used to specify that the new
|
||
434 | * opaque node has no parent. The opaque string must be nul-terminated and
|
||
435 | * is copied into the new node.
|
||
436 | */
|
||
437 | |||
438 | mxml_node_t * /* O - New node */
|
||
439 | mxmlNewOpaque(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
|
||
440 | const char *opaque) /* I - Opaque string */ |
||
441 | { |
||
442 | mxml_node_t *node; /* New node */
|
||
443 | |||
444 | |||
445 | #ifdef DEBUG
|
||
446 | fprintf(stderr, "mxmlNewOpaque(parent=%p, opaque=\"%s\")\n", parent,
|
||
447 | opaque ? opaque : "(null)");
|
||
448 | #endif /* DEBUG */ |
||
449 | |||
450 | /*
|
||
451 | * Range check input...
|
||
452 | */
|
||
453 | |||
454 | if (!opaque)
|
||
455 | return (NULL); |
||
456 | |||
457 | /*
|
||
458 | * Create the node and set the element name...
|
||
459 | */
|
||
460 | |||
461 | if ((node = mxml_new(parent, MXML_OPAQUE)) != NULL) |
||
462 | node->value.opaque = strdup(opaque); |
||
463 | |||
464 | return (node);
|
||
465 | } |
||
466 | |||
467 | |||
468 | /*
|
||
469 | * 'mxmlNewReal()' - Create a new real number node.
|
||
470 | *
|
||
471 | * The new real number node is added to the end of the specified parent's
|
||
472 | * child list. The constant MXML_NO_PARENT can be used to specify that
|
||
473 | * the new real number node has no parent.
|
||
474 | */
|
||
475 | |||
476 | mxml_node_t * /* O - New node */
|
||
477 | mxmlNewReal(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
|
||
478 | double real) /* I - Real number value */ |
||
479 | { |
||
480 | mxml_node_t *node; /* New node */
|
||
481 | |||
482 | |||
483 | #ifdef DEBUG
|
||
484 | fprintf(stderr, "mxmlNewReal(parent=%p, real=%g)\n", parent, real);
|
||
485 | #endif /* DEBUG */ |
||
486 | |||
487 | /*
|
||
488 | * Create the node and set the element name...
|
||
489 | */
|
||
490 | |||
491 | if ((node = mxml_new(parent, MXML_REAL)) != NULL) |
||
492 | node->value.real = real; |
||
493 | |||
494 | return (node);
|
||
495 | } |
||
496 | |||
497 | |||
498 | /*
|
||
499 | * 'mxmlNewText()' - Create a new text fragment node.
|
||
500 | *
|
||
501 | * The new text node is added to the end of the specified parent's child
|
||
502 | * list. The constant MXML_NO_PARENT can be used to specify that the new
|
||
503 | * text node has no parent. The whitespace parameter is used to specify
|
||
504 | * whether leading whitespace is present before the node. The text
|
||
505 | * string must be nul-terminated and is copied into the new node.
|
||
506 | */
|
||
507 | |||
508 | mxml_node_t * /* O - New node */
|
||
509 | mxmlNewText(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
|
||
510 | int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */ |
||
511 | const char *string) /* I - String */ |
||
512 | { |
||
513 | mxml_node_t *node; /* New node */
|
||
514 | |||
515 | |||
516 | #ifdef DEBUG
|
||
517 | fprintf(stderr, "mxmlNewText(parent=%p, whitespace=%d, string=\"%s\")\n",
|
||
518 | parent, whitespace, string ? string : "(null)");
|
||
519 | #endif /* DEBUG */ |
||
520 | |||
521 | /*
|
||
522 | * Range check input...
|
||
523 | */
|
||
524 | |||
525 | if (!string)
|
||
526 | return (NULL); |
||
527 | |||
528 | /*
|
||
529 | * Create the node and set the text value...
|
||
530 | */
|
||
531 | |||
532 | if ((node = mxml_new(parent, MXML_TEXT)) != NULL) |
||
533 | { |
||
534 | node->value.text.whitespace = whitespace; |
||
535 | node->value.text.string = strdup(string); |
||
536 | } |
||
537 | |||
538 | return (node);
|
||
539 | } |
||
540 | |||
541 | |||
542 | /*
|
||
543 | * 'mxmlNewTextf()' - Create a new formatted text fragment node.
|
||
544 | *
|
||
545 | * The new text node is added to the end of the specified parent's child
|
||
546 | * list. The constant MXML_NO_PARENT can be used to specify that the new
|
||
547 | * text node has no parent. The whitespace parameter is used to specify
|
||
548 | * whether leading whitespace is present before the node. The format
|
||
549 | * string must be nul-terminated and is formatted into the new node.
|
||
550 | */
|
||
551 | |||
552 | mxml_node_t * /* O - New node */
|
||
553 | mxmlNewTextf(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
|
||
554 | int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */ |
||
555 | const char *format, /* I - Printf-style frmat string */ |
||
556 | ...) /* I - Additional args as needed */
|
||
557 | { |
||
558 | mxml_node_t *node; /* New node */
|
||
559 | va_list ap; /* Pointer to arguments */
|
||
560 | |||
561 | |||
562 | #ifdef DEBUG
|
||
563 | fprintf(stderr, "mxmlNewTextf(parent=%p, whitespace=%d, format=\"%s\", ...)\n",
|
||
564 | parent, whitespace, format ? format : "(null)");
|
||
565 | #endif /* DEBUG */ |
||
566 | |||
567 | /*
|
||
568 | * Range check input...
|
||
569 | */
|
||
570 | |||
571 | if (!format)
|
||
572 | return (NULL); |
||
573 | |||
574 | /*
|
||
575 | * Create the node and set the text value...
|
||
576 | */
|
||
577 | |||
578 | if ((node = mxml_new(parent, MXML_TEXT)) != NULL) |
||
579 | { |
||
580 | va_start(ap, format); |
||
581 | |||
582 | node->value.text.whitespace = whitespace; |
||
583 | node->value.text.string = _mxml_vstrdupf(format, ap); |
||
584 | |||
585 | va_end(ap); |
||
586 | } |
||
587 | |||
588 | return (node);
|
||
589 | } |
||
590 | |||
591 | |||
592 | /*
|
||
593 | * 'mxmlRemove()' - Remove a node from its parent.
|
||
594 | *
|
||
595 | * Does not free memory used by the node - use mxmlDelete() for that.
|
||
596 | * This function does nothing if the node has no parent.
|
||
597 | */
|
||
598 | |||
599 | void
|
||
600 | mxmlRemove(mxml_node_t *node) /* I - Node to remove */
|
||
601 | { |
||
602 | #ifdef DEBUG
|
||
603 | fprintf(stderr, "mxmlRemove(node=%p)\n", node);
|
||
604 | #endif /* DEBUG */ |
||
605 | |||
606 | /*
|
||
607 | * Range check input...
|
||
608 | */
|
||
609 | |||
610 | if (!node || !node->parent)
|
||
611 | return;
|
||
612 | |||
613 | /*
|
||
614 | * Remove from parent...
|
||
615 | */
|
||
616 | |||
617 | #if DEBUG > 1 |
||
618 | fprintf(stderr, " BEFORE: node->parent=%p\n", node->parent);
|
||
619 | if (node->parent)
|
||
620 | { |
||
621 | fprintf(stderr, " BEFORE: node->parent->child=%p\n", node->parent->child);
|
||
622 | fprintf(stderr, " BEFORE: node->parent->last_child=%p\n", node->parent->last_child);
|
||
623 | } |
||
624 | fprintf(stderr, " BEFORE: node->child=%p\n", node->child);
|
||
625 | fprintf(stderr, " BEFORE: node->last_child=%p\n", node->last_child);
|
||
626 | fprintf(stderr, " BEFORE: node->prev=%p\n", node->prev);
|
||
627 | fprintf(stderr, " BEFORE: node->next=%p\n", node->next);
|
||
628 | #endif /* DEBUG > 1 */ |
||
629 | |||
630 | if (node->prev)
|
||
631 | node->prev->next = node->next; |
||
632 | else
|
||
633 | node->parent->child = node->next; |
||
634 | |||
635 | if (node->next)
|
||
636 | node->next->prev = node->prev; |
||
637 | else
|
||
638 | node->parent->last_child = node->prev; |
||
639 | |||
640 | node->parent = NULL;
|
||
641 | node->prev = NULL;
|
||
642 | node->next = NULL;
|
||
643 | |||
644 | #if DEBUG > 1 |
||
645 | fprintf(stderr, " AFTER: node->parent=%p\n", node->parent);
|
||
646 | if (node->parent)
|
||
647 | { |
||
648 | fprintf(stderr, " AFTER: node->parent->child=%p\n", node->parent->child);
|
||
649 | fprintf(stderr, " AFTER: node->parent->last_child=%p\n", node->parent->last_child);
|
||
650 | } |
||
651 | fprintf(stderr, " AFTER: node->child=%p\n", node->child);
|
||
652 | fprintf(stderr, " AFTER: node->last_child=%p\n", node->last_child);
|
||
653 | fprintf(stderr, " AFTER: node->prev=%p\n", node->prev);
|
||
654 | fprintf(stderr, " AFTER: node->next=%p\n", node->next);
|
||
655 | #endif /* DEBUG > 1 */ |
||
656 | } |
||
657 | |||
658 | |||
659 | /*
|
||
660 | * 'mxmlNewXML()' - Create a new XML document tree.
|
||
661 | *
|
||
662 | * The "version" argument specifies the version number to put in the
|
||
663 | * ?xml element node. If NULL, version 1.0 is assumed.
|
||
664 | *
|
||
665 | * @since Mini-XML 2.3@
|
||
666 | */
|
||
667 | |||
668 | mxml_node_t * /* O - New ?xml node */
|
||
669 | mxmlNewXML(const char *version) /* I - Version number to use */ |
||
670 | { |
||
671 | char element[1024]; /* Element text */ |
||
672 | |||
673 | |||
674 | snprintf(element, sizeof(element), "?xml version=\"%s\" encoding=\"utf-8\"?", |
||
675 | version ? version : "1.0");
|
||
676 | |||
677 | return (mxmlNewElement(NULL, element)); |
||
678 | } |
||
679 | |||
680 | |||
681 | /*
|
||
682 | * 'mxmlRelease()' - Release a node.
|
||
683 | *
|
||
684 | * When the reference count reaches zero, the node (and any children)
|
||
685 | * is deleted via mxmlDelete().
|
||
686 | *
|
||
687 | * @since Mini-XML 2.3@
|
||
688 | */
|
||
689 | |||
690 | int /* O - New reference count */ |
||
691 | mxmlRelease(mxml_node_t *node) /* I - Node */
|
||
692 | { |
||
693 | if (node)
|
||
694 | { |
||
695 | if ((-- node->ref_count) <= 0) |
||
696 | { |
||
697 | mxmlDelete(node); |
||
698 | return (0); |
||
699 | } |
||
700 | else
|
||
701 | return (node->ref_count);
|
||
702 | } |
||
703 | else
|
||
704 | return (-1); |
||
705 | } |
||
706 | |||
707 | |||
708 | /*
|
||
709 | * 'mxmlRetain()' - Retain a node.
|
||
710 | *
|
||
711 | * @since Mini-XML 2.3@
|
||
712 | */
|
||
713 | |||
714 | int /* O - New reference count */ |
||
715 | mxmlRetain(mxml_node_t *node) /* I - Node */
|
||
716 | { |
||
717 | if (node)
|
||
718 | return (++ node->ref_count);
|
||
719 | else
|
||
720 | return (-1); |
||
721 | } |
||
722 | |||
723 | |||
724 | /*
|
||
725 | * 'mxml_new()' - Create a new node.
|
||
726 | */
|
||
727 | |||
728 | static mxml_node_t * /* O - New node */ |
||
729 | mxml_new(mxml_node_t *parent, /* I - Parent node */
|
||
730 | mxml_type_t type) /* I - Node type */
|
||
731 | { |
||
732 | mxml_node_t *node; /* New node */
|
||
733 | |||
734 | |||
735 | #if DEBUG > 1 |
||
736 | fprintf(stderr, "mxml_new(parent=%p, type=%d)\n", parent, type);
|
||
737 | #endif /* DEBUG > 1 */ |
||
738 | |||
739 | /*
|
||
740 | * Allocate memory for the node...
|
||
741 | */
|
||
742 | |||
743 | if ((node = calloc(1, sizeof(mxml_node_t))) == NULL) |
||
744 | { |
||
745 | #if DEBUG > 1 |
||
746 | fputs(" returning NULL\n", stderr);
|
||
747 | #endif /* DEBUG > 1 */ |
||
748 | |||
749 | return (NULL); |
||
750 | } |
||
751 | |||
752 | #if DEBUG > 1 |
||
753 | fprintf(stderr, " returning %p\n", node);
|
||
754 | #endif /* DEBUG > 1 */ |
||
755 | |||
756 | /*
|
||
757 | * Set the node type...
|
||
758 | */
|
||
759 | |||
760 | node->type = type; |
||
761 | node->ref_count = 1;
|
||
762 | |||
763 | /*
|
||
764 | * Add to the parent if present...
|
||
765 | */
|
||
766 | |||
767 | if (parent)
|
||
768 | mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node); |
||
769 | |||
770 | /*
|
||
771 | * Return the new node...
|
||
772 | */
|
||
773 | |||
774 | return (node);
|
||
775 | } |
||
776 | |||
777 | |||
778 | /*
|
||
779 | * End of "$Id: mxml-node.c 363 2008-10-26 18:28:05Z mike $".
|
||
780 | */ |