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