00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "config.h"
00042 #include "mxml.h"
00043
00044
00045
00046
00047
00048
00049 static mxml_node_t *mxml_new(mxml_node_t *parent, mxml_type_t type);
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 void
00064 mxmlAdd(mxml_node_t *parent,
00065 int where,
00066 mxml_node_t *child,
00067 mxml_node_t *node)
00068 {
00069 #ifdef DEBUG
00070 fprintf(stderr, "mxmlAdd(parent=%p, where=%d, child=%p, node=%p)\n", parent,
00071 where, child, node);
00072 #endif
00073
00074
00075
00076
00077
00078 if (!parent || !node)
00079 return;
00080
00081 #if DEBUG > 1
00082 fprintf(stderr, " BEFORE: node->parent=%p\n", node->parent);
00083 if (parent)
00084 {
00085 fprintf(stderr, " BEFORE: parent->child=%p\n", parent->child);
00086 fprintf(stderr, " BEFORE: parent->last_child=%p\n", parent->last_child);
00087 fprintf(stderr, " BEFORE: parent->prev=%p\n", parent->prev);
00088 fprintf(stderr, " BEFORE: parent->next=%p\n", parent->next);
00089 }
00090 #endif
00091
00092
00093
00094
00095
00096 if (node->parent)
00097 mxmlRemove(node);
00098
00099
00100
00101
00102
00103 node->parent = parent;
00104
00105 switch (where)
00106 {
00107 case MXML_ADD_BEFORE :
00108 if (!child || child == parent->child || child->parent != parent)
00109 {
00110
00111
00112
00113
00114 node->next = parent->child;
00115
00116 if (parent->child)
00117 parent->child->prev = node;
00118 else
00119 parent->last_child = node;
00120
00121 parent->child = node;
00122 }
00123 else
00124 {
00125
00126
00127
00128
00129 node->next = child;
00130 node->prev = child->prev;
00131
00132 if (child->prev)
00133 child->prev->next = node;
00134 else
00135 parent->child = node;
00136
00137 child->prev = node;
00138 }
00139 break;
00140
00141 case MXML_ADD_AFTER :
00142 if (!child || child == parent->last_child || child->parent != parent)
00143 {
00144
00145
00146
00147
00148 node->parent = parent;
00149 node->prev = parent->last_child;
00150
00151 if (parent->last_child)
00152 parent->last_child->next = node;
00153 else
00154 parent->child = node;
00155
00156 parent->last_child = node;
00157 }
00158 else
00159 {
00160
00161
00162
00163
00164 node->prev = child;
00165 node->next = child->next;
00166
00167 if (child->next)
00168 child->next->prev = node;
00169 else
00170 parent->last_child = node;
00171
00172 child->next = node;
00173 }
00174 break;
00175 }
00176
00177 #if DEBUG > 1
00178 fprintf(stderr, " AFTER: node->parent=%p\n", node->parent);
00179 if (parent)
00180 {
00181 fprintf(stderr, " AFTER: parent->child=%p\n", parent->child);
00182 fprintf(stderr, " AFTER: parent->last_child=%p\n", parent->last_child);
00183 fprintf(stderr, " AFTER: parent->prev=%p\n", parent->prev);
00184 fprintf(stderr, " AFTER: parent->next=%p\n", parent->next);
00185 }
00186 #endif
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 void
00198 mxmlDelete(mxml_node_t *node)
00199 {
00200 int i;
00201
00202
00203 #ifdef DEBUG
00204 fprintf(stderr, "mxmlDelete(node=%p)\n", node);
00205 #endif
00206
00207
00208
00209
00210
00211 if (!node)
00212 return;
00213
00214
00215
00216
00217
00218 mxmlRemove(node);
00219
00220
00221
00222
00223
00224 while (node->child)
00225 mxmlDelete(node->child);
00226
00227
00228
00229
00230
00231 switch (node->type)
00232 {
00233 case MXML_ELEMENT :
00234 if (node->value.element.name)
00235 free(node->value.element.name);
00236
00237 if (node->value.element.num_attrs)
00238 {
00239 for (i = 0; i < node->value.element.num_attrs; i ++)
00240 {
00241 if (node->value.element.attrs[i].name)
00242 free(node->value.element.attrs[i].name);
00243 if (node->value.element.attrs[i].value)
00244 free(node->value.element.attrs[i].value);
00245 }
00246
00247 free(node->value.element.attrs);
00248 }
00249 break;
00250 case MXML_INTEGER :
00251
00252 break;
00253 case MXML_OPAQUE :
00254 if (node->value.opaque)
00255 free(node->value.opaque);
00256 break;
00257 case MXML_REAL :
00258
00259 break;
00260 case MXML_TEXT :
00261 if (node->value.text.string)
00262 free(node->value.text.string);
00263 break;
00264 case MXML_CUSTOM :
00265 if (node->value.custom.data &&
00266 node->value.custom.destroy)
00267 (*(node->value.custom.destroy))(node->value.custom.data);
00268 break;
00269 default :
00270 break;
00271 }
00272
00273
00274
00275
00276
00277 free(node);
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 mxml_node_t *
00293 mxmlNewCDATA(mxml_node_t *parent,
00294 const char *data)
00295 {
00296 mxml_node_t *node;
00297
00298
00299 #ifdef DEBUG
00300 fprintf(stderr, "mxmlNewCDATA(parent=%p, data=\"%s\")\n",
00301 parent, data ? data : "(null)");
00302 #endif
00303
00304
00305
00306
00307
00308 if (!data)
00309 return (NULL);
00310
00311
00312
00313
00314
00315 if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL)
00316 node->value.element.name = _mxml_strdupf("![CDATA[%s]]", data);
00317
00318 return (node);
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 mxml_node_t *
00334 mxmlNewCustom(
00335 mxml_node_t *parent,
00336 void *data,
00337 mxml_custom_destroy_cb_t destroy)
00338 {
00339 mxml_node_t *node;
00340
00341
00342 #ifdef DEBUG
00343 fprintf(stderr, "mxmlNewCustom(parent=%p, data=%p, destroy=%p)\n", parent,
00344 data, destroy);
00345 #endif
00346
00347
00348
00349
00350
00351 if ((node = mxml_new(parent, MXML_CUSTOM)) != NULL)
00352 {
00353 node->value.custom.data = data;
00354 node->value.custom.destroy = destroy;
00355 }
00356
00357 return (node);
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 mxml_node_t *
00370 mxmlNewElement(mxml_node_t *parent,
00371 const char *name)
00372 {
00373 mxml_node_t *node;
00374
00375
00376 #ifdef DEBUG
00377 fprintf(stderr, "mxmlNewElement(parent=%p, name=\"%s\")\n", parent,
00378 name ? name : "(null)");
00379 #endif
00380
00381
00382
00383
00384
00385 if (!name)
00386 return (NULL);
00387
00388
00389
00390
00391
00392 if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL)
00393 node->value.element.name = strdup(name);
00394
00395 return (node);
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 mxml_node_t *
00408 mxmlNewInteger(mxml_node_t *parent,
00409 int integer)
00410 {
00411 mxml_node_t *node;
00412
00413
00414 #ifdef DEBUG
00415 fprintf(stderr, "mxmlNewInteger(parent=%p, integer=%d)\n", parent, integer);
00416 #endif
00417
00418
00419
00420
00421
00422 if ((node = mxml_new(parent, MXML_INTEGER)) != NULL)
00423 node->value.integer = integer;
00424
00425 return (node);
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 mxml_node_t *
00439 mxmlNewOpaque(mxml_node_t *parent,
00440 const char *opaque)
00441 {
00442 mxml_node_t *node;
00443
00444
00445 #ifdef DEBUG
00446 fprintf(stderr, "mxmlNewOpaque(parent=%p, opaque=\"%s\")\n", parent,
00447 opaque ? opaque : "(null)");
00448 #endif
00449
00450
00451
00452
00453
00454 if (!opaque)
00455 return (NULL);
00456
00457
00458
00459
00460
00461 if ((node = mxml_new(parent, MXML_OPAQUE)) != NULL)
00462 node->value.opaque = strdup(opaque);
00463
00464 return (node);
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 mxml_node_t *
00477 mxmlNewReal(mxml_node_t *parent,
00478 double real)
00479 {
00480 mxml_node_t *node;
00481
00482
00483 #ifdef DEBUG
00484 fprintf(stderr, "mxmlNewReal(parent=%p, real=%g)\n", parent, real);
00485 #endif
00486
00487
00488
00489
00490
00491 if ((node = mxml_new(parent, MXML_REAL)) != NULL)
00492 node->value.real = real;
00493
00494 return (node);
00495 }
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 mxml_node_t *
00509 mxmlNewText(mxml_node_t *parent,
00510 int whitespace,
00511 const char *string)
00512 {
00513 mxml_node_t *node;
00514
00515
00516 #ifdef DEBUG
00517 fprintf(stderr, "mxmlNewText(parent=%p, whitespace=%d, string=\"%s\")\n",
00518 parent, whitespace, string ? string : "(null)");
00519 #endif
00520
00521
00522
00523
00524
00525 if (!string)
00526 return (NULL);
00527
00528
00529
00530
00531
00532 if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
00533 {
00534 node->value.text.whitespace = whitespace;
00535 node->value.text.string = strdup(string);
00536 }
00537
00538 return (node);
00539 }
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 mxml_node_t *
00553 mxmlNewTextf(mxml_node_t *parent,
00554 int whitespace,
00555 const char *format,
00556 ...)
00557 {
00558 mxml_node_t *node;
00559 va_list ap;
00560
00561
00562 #ifdef DEBUG
00563 fprintf(stderr, "mxmlNewTextf(parent=%p, whitespace=%d, format=\"%s\", ...)\n",
00564 parent, whitespace, format ? format : "(null)");
00565 #endif
00566
00567
00568
00569
00570
00571 if (!format)
00572 return (NULL);
00573
00574
00575
00576
00577
00578 if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
00579 {
00580 va_start(ap, format);
00581
00582 node->value.text.whitespace = whitespace;
00583 node->value.text.string = _mxml_vstrdupf(format, ap);
00584
00585 va_end(ap);
00586 }
00587
00588 return (node);
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 void
00600 mxmlRemove(mxml_node_t *node)
00601 {
00602 #ifdef DEBUG
00603 fprintf(stderr, "mxmlRemove(node=%p)\n", node);
00604 #endif
00605
00606
00607
00608
00609
00610 if (!node || !node->parent)
00611 return;
00612
00613
00614
00615
00616
00617 #if DEBUG > 1
00618 fprintf(stderr, " BEFORE: node->parent=%p\n", node->parent);
00619 if (node->parent)
00620 {
00621 fprintf(stderr, " BEFORE: node->parent->child=%p\n", node->parent->child);
00622 fprintf(stderr, " BEFORE: node->parent->last_child=%p\n", node->parent->last_child);
00623 }
00624 fprintf(stderr, " BEFORE: node->child=%p\n", node->child);
00625 fprintf(stderr, " BEFORE: node->last_child=%p\n", node->last_child);
00626 fprintf(stderr, " BEFORE: node->prev=%p\n", node->prev);
00627 fprintf(stderr, " BEFORE: node->next=%p\n", node->next);
00628 #endif
00629
00630 if (node->prev)
00631 node->prev->next = node->next;
00632 else
00633 node->parent->child = node->next;
00634
00635 if (node->next)
00636 node->next->prev = node->prev;
00637 else
00638 node->parent->last_child = node->prev;
00639
00640 node->parent = NULL;
00641 node->prev = NULL;
00642 node->next = NULL;
00643
00644 #if DEBUG > 1
00645 fprintf(stderr, " AFTER: node->parent=%p\n", node->parent);
00646 if (node->parent)
00647 {
00648 fprintf(stderr, " AFTER: node->parent->child=%p\n", node->parent->child);
00649 fprintf(stderr, " AFTER: node->parent->last_child=%p\n", node->parent->last_child);
00650 }
00651 fprintf(stderr, " AFTER: node->child=%p\n", node->child);
00652 fprintf(stderr, " AFTER: node->last_child=%p\n", node->last_child);
00653 fprintf(stderr, " AFTER: node->prev=%p\n", node->prev);
00654 fprintf(stderr, " AFTER: node->next=%p\n", node->next);
00655 #endif
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 mxml_node_t *
00669 mxmlNewXML(const char *version)
00670 {
00671 char element[1024];
00672
00673
00674 snprintf(element, sizeof(element), "?xml version=\"%s\"?",
00675 version ? version : "1.0");
00676
00677 return (mxmlNewElement(NULL, element));
00678 }
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 int
00691 mxmlRelease(mxml_node_t *node)
00692 {
00693 if (node)
00694 {
00695 if ((-- node->ref_count) <= 0)
00696 {
00697 mxmlDelete(node);
00698 return (0);
00699 }
00700 else
00701 return (node->ref_count);
00702 }
00703 else
00704 return (-1);
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714 int
00715 mxmlRetain(mxml_node_t *node)
00716 {
00717 if (node)
00718 return (++ node->ref_count);
00719 else
00720 return (-1);
00721 }
00722
00723
00724
00725
00726
00727
00728 static mxml_node_t *
00729 mxml_new(mxml_node_t *parent,
00730 mxml_type_t type)
00731 {
00732 mxml_node_t *node;
00733
00734
00735 #if DEBUG > 1
00736 fprintf(stderr, "mxml_new(parent=%p, type=%d)\n", parent, type);
00737 #endif
00738
00739
00740
00741
00742
00743 if ((node = calloc(1, sizeof(mxml_node_t))) == NULL)
00744 {
00745 #if DEBUG > 1
00746 fputs(" returning NULL\n", stderr);
00747 #endif
00748
00749 return (NULL);
00750 }
00751
00752 #if DEBUG > 1
00753 fprintf(stderr, " returning %p\n", node);
00754 #endif
00755
00756
00757
00758
00759
00760 node->type = type;
00761 node->ref_count = 1;
00762
00763
00764
00765
00766
00767 if (parent)
00768 mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
00769
00770
00771
00772
00773
00774 return (node);
00775 }