Mercurial > pidgin
comparison src/protocols/jabber/xmlnode.c @ 2086:424a40f12a6c
[gaim-migrate @ 2096]
moving protocols from plugins/ to src/protocols. making it so that you can select which protocols are compiled statically.
committer: Tailor Script <tailor@pidgin.im>
| author | Eric Warmenhoven <eric@warmenhoven.org> |
|---|---|
| date | Tue, 31 Jul 2001 01:00:39 +0000 |
| parents | |
| children | 4e7cefc55971 |
comparison
equal
deleted
inserted
replaced
| 2085:7ebb4322f89b | 2086:424a40f12a6c |
|---|---|
| 1 /* | |
| 2 * This program is free software; you can redistribute it and/or modify | |
| 3 * it under the terms of the GNU General Public License as published by | |
| 4 * the Free Software Foundation; either version 2 of the License, or | |
| 5 * (at your option) any later version. | |
| 6 * | |
| 7 * This program is distributed in the hope that it will be useful, | |
| 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 10 * GNU General Public License for more details. | |
| 11 * | |
| 12 * You should have received a copy of the GNU General Public License | |
| 13 * along with this program; if not, write to the Free Software | |
| 14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| 15 * | |
| 16 * Jabber | |
| 17 * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ | |
| 18 */ | |
| 19 | |
| 20 #include "libxode.h" | |
| 21 | |
| 22 /* Internal routines */ | |
| 23 xmlnode _xmlnode_new(pool p, const char* name, unsigned int type) | |
| 24 { | |
| 25 xmlnode result = NULL; | |
| 26 if (type > NTYPE_LAST) | |
| 27 return NULL; | |
| 28 | |
| 29 if (type != NTYPE_CDATA && name == NULL) | |
| 30 return NULL; | |
| 31 | |
| 32 if (p == NULL) | |
| 33 { | |
| 34 p = pool_heap(1*1024); | |
| 35 } | |
| 36 | |
| 37 /* Allocate & zero memory */ | |
| 38 result = (xmlnode)pmalloc(p, sizeof(_xmlnode)); | |
| 39 memset(result, '\0', sizeof(_xmlnode)); | |
| 40 | |
| 41 /* Initialize fields */ | |
| 42 if (type != NTYPE_CDATA) | |
| 43 result->name = pstrdup(p,name); | |
| 44 result->type = type; | |
| 45 result->p = p; | |
| 46 return result; | |
| 47 } | |
| 48 | |
| 49 static xmlnode _xmlnode_append_sibling(xmlnode lastsibling, const char* name, unsigned int type) | |
| 50 { | |
| 51 xmlnode result; | |
| 52 | |
| 53 result = _xmlnode_new(xmlnode_pool(lastsibling), name, type); | |
| 54 if (result != NULL) | |
| 55 { | |
| 56 /* Setup sibling pointers */ | |
| 57 result->prev = lastsibling; | |
| 58 lastsibling->next = result; | |
| 59 } | |
| 60 return result; | |
| 61 } | |
| 62 | |
| 63 static xmlnode _xmlnode_insert(xmlnode parent, const char* name, unsigned int type) | |
| 64 { | |
| 65 xmlnode result; | |
| 66 | |
| 67 if(parent == NULL || name == NULL) return NULL; | |
| 68 | |
| 69 /* If parent->firstchild is NULL, simply create a new node for the first child */ | |
| 70 if (parent->firstchild == NULL) | |
| 71 { | |
| 72 result = _xmlnode_new(parent->p, name, type); | |
| 73 parent->firstchild = result; | |
| 74 } | |
| 75 /* Otherwise, append this to the lastchild */ | |
| 76 else | |
| 77 { | |
| 78 result= _xmlnode_append_sibling(parent->lastchild, name, type); | |
| 79 } | |
| 80 result->parent = parent; | |
| 81 parent->lastchild = result; | |
| 82 return result; | |
| 83 | |
| 84 } | |
| 85 | |
| 86 static xmlnode _xmlnode_search(xmlnode firstsibling, const char* name, unsigned int type) | |
| 87 { | |
| 88 xmlnode current; | |
| 89 | |
| 90 /* Walk the sibling list, looking for a NTYPE_TAG xmlnode with | |
| 91 the specified name */ | |
| 92 current = firstsibling; | |
| 93 while (current != NULL) | |
| 94 { | |
| 95 if ((current->type == type) && (j_strcmp(current->name, name) == 0)) | |
| 96 return current; | |
| 97 else | |
| 98 current = current->next; | |
| 99 } | |
| 100 return NULL; | |
| 101 } | |
| 102 | |
| 103 static char* _xmlnode_merge(pool p, char* dest, unsigned int destsize, const char* src, unsigned int srcsize) | |
| 104 { | |
| 105 char* result; | |
| 106 result = (char*)pmalloc(p, destsize + srcsize + 1); | |
| 107 memcpy(result, dest, destsize); | |
| 108 memcpy(result+destsize, src, srcsize); | |
| 109 result[destsize + srcsize] = '\0'; | |
| 110 | |
| 111 /* WARNING: major ugly hack: since we're throwing the old data away, let's jump in the pool and subtract it from the size, this is for xmlstream's big-node checking */ | |
| 112 p->size -= destsize; | |
| 113 | |
| 114 return result; | |
| 115 } | |
| 116 | |
| 117 static void _xmlnode_hide_sibling(xmlnode child) | |
| 118 { | |
| 119 if(child == NULL) | |
| 120 return; | |
| 121 | |
| 122 if(child->prev != NULL) | |
| 123 child->prev->next = child->next; | |
| 124 if(child->next != NULL) | |
| 125 child->next->prev = child->prev; | |
| 126 } | |
| 127 | |
| 128 void _xmlnode_tag2str(spool s, xmlnode node, int flag) | |
| 129 { | |
| 130 xmlnode tmp; | |
| 131 | |
| 132 if(flag==0 || flag==1) | |
| 133 { | |
| 134 spooler(s,"<",xmlnode_get_name(node),s); | |
| 135 tmp = xmlnode_get_firstattrib(node); | |
| 136 while(tmp) { | |
| 137 spooler(s," ",xmlnode_get_name(tmp),"='",strescape(xmlnode_pool(node),xmlnode_get_data(tmp)),"'",s); | |
| 138 tmp = xmlnode_get_nextsibling(tmp); | |
| 139 } | |
| 140 if(flag==0) | |
| 141 spool_add(s,"/>"); | |
| 142 else | |
| 143 spool_add(s,">"); | |
| 144 } | |
| 145 else | |
| 146 { | |
| 147 spooler(s,"</",xmlnode_get_name(node),">",s); | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 spool _xmlnode2spool(xmlnode node) | |
| 152 { | |
| 153 spool s; | |
| 154 int level=0,dir=0; | |
| 155 xmlnode tmp; | |
| 156 | |
| 157 if(!node || xmlnode_get_type(node)!=NTYPE_TAG) | |
| 158 return NULL; | |
| 159 | |
| 160 s = spool_new(xmlnode_pool(node)); | |
| 161 if(!s) return(NULL); | |
| 162 | |
| 163 while(1) | |
| 164 { | |
| 165 if(dir==0) | |
| 166 { | |
| 167 if(xmlnode_get_type(node) == NTYPE_TAG) | |
| 168 { | |
| 169 if(xmlnode_has_children(node)) | |
| 170 { | |
| 171 _xmlnode_tag2str(s,node,1); | |
| 172 node = xmlnode_get_firstchild(node); | |
| 173 level++; | |
| 174 continue; | |
| 175 } | |
| 176 else | |
| 177 { | |
| 178 _xmlnode_tag2str(s,node,0); | |
| 179 } | |
| 180 } | |
| 181 else | |
| 182 { | |
| 183 spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node))); | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 tmp = xmlnode_get_nextsibling(node); | |
| 188 if(!tmp) | |
| 189 { | |
| 190 node = xmlnode_get_parent(node); | |
| 191 level--; | |
| 192 if(level>=0) _xmlnode_tag2str(s,node,2); | |
| 193 if(level<1) break; | |
| 194 dir = 1; | |
| 195 } | |
| 196 else | |
| 197 { | |
| 198 node = tmp; | |
| 199 dir = 0; | |
| 200 } | |
| 201 } | |
| 202 | |
| 203 return s; | |
| 204 } | |
| 205 | |
| 206 | |
| 207 /* External routines */ | |
| 208 | |
| 209 | |
| 210 /* | |
| 211 * xmlnode_new_tag -- create a tag node | |
| 212 * Automatically creates a memory pool for the node. | |
| 213 * | |
| 214 * parameters | |
| 215 * name -- name of the tag | |
| 216 * | |
| 217 * returns | |
| 218 * a pointer to the tag node | |
| 219 * or NULL if it was unsuccessfull | |
| 220 */ | |
| 221 xmlnode xmlnode_new_tag(const char* name) | |
| 222 { | |
| 223 return _xmlnode_new(NULL, name, NTYPE_TAG); | |
| 224 } | |
| 225 | |
| 226 | |
| 227 /* | |
| 228 * xmlnode_new_tag_pool -- create a tag node within given pool | |
| 229 * | |
| 230 * parameters | |
| 231 * p -- previously created memory pool | |
| 232 * name -- name of the tag | |
| 233 * | |
| 234 * returns | |
| 235 * a pointer to the tag node | |
| 236 * or NULL if it was unsuccessfull | |
| 237 */ | |
| 238 xmlnode xmlnode_new_tag_pool(pool p, const char* name) | |
| 239 { | |
| 240 return _xmlnode_new(p, name, NTYPE_TAG); | |
| 241 } | |
| 242 | |
| 243 | |
| 244 /* | |
| 245 * xmlnode_insert_tag -- append a child tag to a tag | |
| 246 * | |
| 247 * parameters | |
| 248 * parent -- pointer to the parent tag | |
| 249 * name -- name of the child tag | |
| 250 * | |
| 251 * returns | |
| 252 * a pointer to the child tag node | |
| 253 * or NULL if it was unsuccessfull | |
| 254 */ | |
| 255 xmlnode xmlnode_insert_tag(xmlnode parent, const char* name) | |
| 256 { | |
| 257 return _xmlnode_insert(parent, name, NTYPE_TAG); | |
| 258 } | |
| 259 | |
| 260 | |
| 261 /* | |
| 262 * xmlnode_insert_cdata -- append character data to a tag | |
| 263 * If last child of the parent is CDATA, merges CDATA nodes. Otherwise | |
| 264 * creates a CDATA node, and appends it to the parent's child list. | |
| 265 * | |
| 266 * parameters | |
| 267 * parent -- parent tag | |
| 268 * CDATA -- character data | |
| 269 * size -- size of CDATA | |
| 270 * or -1 for null-terminated CDATA strings | |
| 271 * | |
| 272 * returns | |
| 273 * a pointer to the child CDATA node | |
| 274 * or NULL if it was unsuccessfull | |
| 275 */ | |
| 276 xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size) | |
| 277 { | |
| 278 xmlnode result; | |
| 279 | |
| 280 if(CDATA == NULL || parent == NULL) | |
| 281 return NULL; | |
| 282 | |
| 283 if(size == -1) | |
| 284 size = strlen(CDATA); | |
| 285 | |
| 286 if ((parent->lastchild != NULL) && (parent->lastchild->type == NTYPE_CDATA)) | |
| 287 { | |
| 288 result = parent->lastchild; | |
| 289 result->data = _xmlnode_merge(result->p, result->data, result->data_sz, CDATA, size); | |
| 290 result->data_sz = result->data_sz + size; | |
| 291 } | |
| 292 else | |
| 293 { | |
| 294 result = _xmlnode_insert(parent, "", NTYPE_CDATA); | |
| 295 if (result != NULL) | |
| 296 { | |
| 297 result->data = (char*)pmalloc(result->p, size + 1); | |
| 298 memcpy(result->data, CDATA, size); | |
| 299 result->data[size] = '\0'; | |
| 300 result->data_sz = size; | |
| 301 } | |
| 302 } | |
| 303 | |
| 304 return result; | |
| 305 } | |
| 306 | |
| 307 | |
| 308 /* | |
| 309 * xmlnode_get_tag -- find given tag in an xmlnode tree | |
| 310 * | |
| 311 * parameters | |
| 312 * parent -- pointer to the parent tag | |
| 313 * name -- "name" for the child tag of that name | |
| 314 * "name/name" for a sub child (recurses) | |
| 315 * "?attrib" to match the first tag with that attrib defined | |
| 316 * "?attrib=value" to match the first tag with that attrib and value | |
| 317 * or any combination: "name/name/?attrib", etc | |
| 318 * | |
| 319 * results | |
| 320 * a pointer to the tag matching search criteria | |
| 321 * or NULL if search was unsuccessfull | |
| 322 */ | |
| 323 xmlnode xmlnode_get_tag(xmlnode parent, const char* name) | |
| 324 { | |
| 325 char *str, *slash, *qmark, *equals; | |
| 326 xmlnode step, ret; | |
| 327 | |
| 328 if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL; | |
| 329 | |
| 330 if(strstr(name, "/") == NULL && strstr(name,"?") == NULL) | |
| 331 return _xmlnode_search(parent->firstchild, name, NTYPE_TAG); | |
| 332 | |
| 333 /* jer's note: why can't I modify the name directly, why do I have to strdup it? damn c grrr! */ | |
| 334 str = strdup(name); | |
| 335 slash = strstr(str, "/"); | |
| 336 qmark = strstr(str, "?"); | |
| 337 equals = strstr(str, "="); | |
| 338 | |
| 339 if(qmark != NULL && (slash == NULL || qmark < slash)) | |
| 340 { /* of type ?attrib */ | |
| 341 | |
| 342 *qmark = '\0'; | |
| 343 qmark++; | |
| 344 if(equals != NULL) | |
| 345 { | |
| 346 *equals = '\0'; | |
| 347 equals++; | |
| 348 } | |
| 349 | |
| 350 for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) | |
| 351 { | |
| 352 if(xmlnode_get_type(step) != NTYPE_TAG) | |
| 353 continue; | |
| 354 | |
| 355 if(*str != '\0') | |
| 356 if(j_strcmp(xmlnode_get_name(step),str) != 0) | |
| 357 continue; | |
| 358 | |
| 359 if(xmlnode_get_attrib(step,qmark) == NULL) | |
| 360 continue; | |
| 361 | |
| 362 if(equals != NULL && j_strcmp(xmlnode_get_attrib(step,qmark),equals) != 0) | |
| 363 continue; | |
| 364 | |
| 365 break; | |
| 366 } | |
| 367 | |
| 368 free(str); | |
| 369 return step; | |
| 370 } | |
| 371 | |
| 372 | |
| 373 *slash = '\0'; | |
| 374 ++slash; | |
| 375 | |
| 376 for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) | |
| 377 { | |
| 378 if(xmlnode_get_type(step) != NTYPE_TAG) continue; | |
| 379 | |
| 380 if(j_strcmp(xmlnode_get_name(step),str) != 0) | |
| 381 continue; | |
| 382 | |
| 383 ret = xmlnode_get_tag(step, slash); | |
| 384 if(ret != NULL) | |
| 385 { | |
| 386 free(str); | |
| 387 return ret; | |
| 388 } | |
| 389 } | |
| 390 | |
| 391 free(str); | |
| 392 return NULL; | |
| 393 } | |
| 394 | |
| 395 | |
| 396 /* return the cdata from any tag */ | |
| 397 char *xmlnode_get_tag_data(xmlnode parent, const char *name) | |
| 398 { | |
| 399 xmlnode tag; | |
| 400 | |
| 401 tag = xmlnode_get_tag(parent, name); | |
| 402 if(tag == NULL) return NULL; | |
| 403 | |
| 404 return xmlnode_get_data(tag); | |
| 405 } | |
| 406 | |
| 407 | |
| 408 void xmlnode_put_attrib(xmlnode owner, const char* name, const char* value) | |
| 409 { | |
| 410 xmlnode attrib; | |
| 411 | |
| 412 if(owner == NULL || name == NULL || value == NULL) return; | |
| 413 | |
| 414 /* If there are no existing attributs, allocate a new one to start | |
| 415 the list */ | |
| 416 if (owner->firstattrib == NULL) | |
| 417 { | |
| 418 attrib = _xmlnode_new(owner->p, name, NTYPE_ATTRIB); | |
| 419 owner->firstattrib = attrib; | |
| 420 owner->lastattrib = attrib; | |
| 421 } | |
| 422 else | |
| 423 { | |
| 424 attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); | |
| 425 if(attrib == NULL) | |
| 426 { | |
| 427 attrib = _xmlnode_append_sibling(owner->lastattrib, name, NTYPE_ATTRIB); | |
| 428 owner->lastattrib = attrib; | |
| 429 } | |
| 430 } | |
| 431 /* Update the value of the attribute */ | |
| 432 attrib->data_sz = strlen(value); | |
| 433 attrib->data = pstrdup(owner->p, value); | |
| 434 | |
| 435 } | |
| 436 | |
| 437 char* xmlnode_get_attrib(xmlnode owner, const char* name) | |
| 438 { | |
| 439 xmlnode attrib; | |
| 440 | |
| 441 if (owner != NULL && owner->firstattrib != NULL) | |
| 442 { | |
| 443 attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); | |
| 444 if (attrib != NULL) | |
| 445 return (char*)attrib->data; | |
| 446 } | |
| 447 return NULL; | |
| 448 } | |
| 449 | |
| 450 void xmlnode_put_vattrib(xmlnode owner, const char* name, void *value) | |
| 451 { | |
| 452 xmlnode attrib; | |
| 453 | |
| 454 if (owner != NULL) | |
| 455 { | |
| 456 attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); | |
| 457 if (attrib == NULL) | |
| 458 { | |
| 459 xmlnode_put_attrib(owner, name, ""); | |
| 460 attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); | |
| 461 } | |
| 462 if (attrib != NULL) | |
| 463 attrib->firstchild = (xmlnode)value; | |
| 464 } | |
| 465 } | |
| 466 | |
| 467 void* xmlnode_get_vattrib(xmlnode owner, const char* name) | |
| 468 { | |
| 469 xmlnode attrib; | |
| 470 | |
| 471 if (owner != NULL && owner->firstattrib != NULL) | |
| 472 { | |
| 473 attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); | |
| 474 if (attrib != NULL) | |
| 475 return (void*)attrib->firstchild; | |
| 476 } | |
| 477 return NULL; | |
| 478 } | |
| 479 | |
| 480 xmlnode xmlnode_get_firstattrib(xmlnode parent) | |
| 481 { | |
| 482 if (parent != NULL) | |
| 483 return parent->firstattrib; | |
| 484 return NULL; | |
| 485 } | |
| 486 | |
| 487 xmlnode xmlnode_get_firstchild(xmlnode parent) | |
| 488 { | |
| 489 if (parent != NULL) | |
| 490 return parent->firstchild; | |
| 491 return NULL; | |
| 492 } | |
| 493 | |
| 494 xmlnode xmlnode_get_lastchild(xmlnode parent) | |
| 495 { | |
| 496 if (parent != NULL) | |
| 497 return parent->lastchild; | |
| 498 return NULL; | |
| 499 } | |
| 500 | |
| 501 xmlnode xmlnode_get_nextsibling(xmlnode sibling) | |
| 502 { | |
| 503 if (sibling != NULL) | |
| 504 return sibling->next; | |
| 505 return NULL; | |
| 506 } | |
| 507 | |
| 508 xmlnode xmlnode_get_prevsibling(xmlnode sibling) | |
| 509 { | |
| 510 if (sibling != NULL) | |
| 511 return sibling->prev; | |
| 512 return NULL; | |
| 513 } | |
| 514 | |
| 515 xmlnode xmlnode_get_parent(xmlnode node) | |
| 516 { | |
| 517 if (node != NULL) | |
| 518 return node->parent; | |
| 519 return NULL; | |
| 520 } | |
| 521 | |
| 522 char* xmlnode_get_name(xmlnode node) | |
| 523 { | |
| 524 if (node != NULL) | |
| 525 return node->name; | |
| 526 return NULL; | |
| 527 } | |
| 528 | |
| 529 char* xmlnode_get_data(xmlnode node) | |
| 530 { | |
| 531 xmlnode cur; | |
| 532 | |
| 533 if(node == NULL) return NULL; | |
| 534 | |
| 535 if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA */ | |
| 536 { | |
| 537 for(cur = xmlnode_get_firstchild(node); cur != NULL; cur = xmlnode_get_nextsibling(cur)) | |
| 538 if(xmlnode_get_type(cur) == NTYPE_CDATA) | |
| 539 return cur->data; | |
| 540 }else{ | |
| 541 return node->data; | |
| 542 } | |
| 543 return NULL; | |
| 544 } | |
| 545 | |
| 546 int xmlnode_get_datasz(xmlnode node) | |
| 547 { | |
| 548 if (node != NULL) | |
| 549 return node->data_sz; | |
| 550 return (int)NULL; | |
| 551 } | |
| 552 | |
| 553 int xmlnode_get_type(xmlnode node) | |
| 554 { | |
| 555 if (node != NULL) | |
| 556 return node->type; | |
| 557 return (int)NULL; | |
| 558 } | |
| 559 | |
| 560 int xmlnode_has_children(xmlnode node) | |
| 561 { | |
| 562 if ((node != NULL) && (node->firstchild != NULL)) | |
| 563 return 1; | |
| 564 return 0; | |
| 565 } | |
| 566 | |
| 567 int xmlnode_has_attribs(xmlnode node) | |
| 568 { | |
| 569 if ((node != NULL) && (node->firstattrib != NULL)) | |
| 570 return 1; | |
| 571 return 0; | |
| 572 } | |
| 573 | |
| 574 pool xmlnode_pool(xmlnode node) | |
| 575 { | |
| 576 if (node != NULL) | |
| 577 return node->p; | |
| 578 return (pool)NULL; | |
| 579 } | |
| 580 | |
| 581 void xmlnode_hide(xmlnode child) | |
| 582 { | |
| 583 xmlnode parent; | |
| 584 | |
| 585 if(child == NULL || child->parent == NULL) | |
| 586 return; | |
| 587 | |
| 588 parent = child->parent; | |
| 589 | |
| 590 /* first fix up at the child level */ | |
| 591 _xmlnode_hide_sibling(child); | |
| 592 | |
| 593 /* next fix up at the parent level */ | |
| 594 if(parent->firstchild == child) | |
| 595 parent->firstchild = child->next; | |
| 596 if(parent->lastchild == child) | |
| 597 parent->lastchild = child->prev; | |
| 598 } | |
| 599 | |
| 600 void xmlnode_hide_attrib(xmlnode parent, const char *name) | |
| 601 { | |
| 602 xmlnode attrib; | |
| 603 | |
| 604 if(parent == NULL || parent->firstattrib == NULL || name == NULL) | |
| 605 return; | |
| 606 | |
| 607 attrib = _xmlnode_search(parent->firstattrib, name, NTYPE_ATTRIB); | |
| 608 if(attrib == NULL) | |
| 609 return; | |
| 610 | |
| 611 /* first fix up at the child level */ | |
| 612 _xmlnode_hide_sibling(attrib); | |
| 613 | |
| 614 /* next fix up at the parent level */ | |
| 615 if(parent->firstattrib == attrib) | |
| 616 parent->firstattrib = attrib->next; | |
| 617 if(parent->lastattrib == attrib) | |
| 618 parent->lastattrib = attrib->prev; | |
| 619 } | |
| 620 | |
| 621 | |
| 622 | |
| 623 /* | |
| 624 * xmlnode2str -- convert given xmlnode tree into a string | |
| 625 * | |
| 626 * parameters | |
| 627 * node -- pointer to the xmlnode structure | |
| 628 * | |
| 629 * results | |
| 630 * a pointer to the created string | |
| 631 * or NULL if it was unsuccessfull | |
| 632 */ | |
| 633 char *xmlnode2str(xmlnode node) | |
| 634 { | |
| 635 return spool_print(_xmlnode2spool(node)); | |
| 636 } | |
| 637 | |
| 638 /* | |
| 639 * xmlnode2tstr -- convert given xmlnode tree into a newline terminated string | |
| 640 * | |
| 641 * parameters | |
| 642 * node -- pointer to the xmlnode structure | |
| 643 * | |
| 644 * results | |
| 645 * a pointer to the created string | |
| 646 * or NULL if it was unsuccessfull | |
| 647 */ | |
| 648 char* xmlnode2tstr(xmlnode node) | |
| 649 { | |
| 650 spool s = _xmlnode2spool(node); | |
| 651 if (s != NULL) | |
| 652 spool_add(s, "\n"); | |
| 653 return spool_print(s); | |
| 654 } | |
| 655 | |
| 656 | |
| 657 /* loop through both a and b comparing everything, attribs, cdata, children, etc */ | |
| 658 int xmlnode_cmp(xmlnode a, xmlnode b) | |
| 659 { | |
| 660 int ret = 0; | |
| 661 | |
| 662 while(1) | |
| 663 { | |
| 664 if(a == NULL && b == NULL) | |
| 665 return 0; | |
| 666 | |
| 667 if(a == NULL || b == NULL) | |
| 668 return -1; | |
| 669 | |
| 670 if(xmlnode_get_type(a) != xmlnode_get_type(b)) | |
| 671 return -1; | |
| 672 | |
| 673 switch(xmlnode_get_type(a)) | |
| 674 { | |
| 675 case NTYPE_ATTRIB: | |
| 676 ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b)); | |
| 677 if(ret != 0) | |
| 678 return -1; | |
| 679 ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b)); | |
| 680 if(ret != 0) | |
| 681 return -1; | |
| 682 break; | |
| 683 case NTYPE_TAG: | |
| 684 ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b)); | |
| 685 if(ret != 0) | |
| 686 return -1; | |
| 687 ret = xmlnode_cmp(xmlnode_get_firstattrib(a), xmlnode_get_firstattrib(b)); | |
| 688 if(ret != 0) | |
| 689 return -1; | |
| 690 ret = xmlnode_cmp(xmlnode_get_firstchild(a), xmlnode_get_firstchild(b)); | |
| 691 if(ret != 0) | |
| 692 return -1; | |
| 693 break; | |
| 694 case NTYPE_CDATA: | |
| 695 ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b)); | |
| 696 if(ret != 0) | |
| 697 return -1; | |
| 698 } | |
| 699 a = xmlnode_get_nextsibling(a); | |
| 700 b = xmlnode_get_nextsibling(b); | |
| 701 } | |
| 702 } | |
| 703 | |
| 704 | |
| 705 xmlnode xmlnode_insert_tag_node(xmlnode parent, xmlnode node) | |
| 706 { | |
| 707 xmlnode child; | |
| 708 | |
| 709 child = xmlnode_insert_tag(parent, xmlnode_get_name(node)); | |
| 710 if (xmlnode_has_attribs(node)) | |
| 711 xmlnode_insert_node(child, xmlnode_get_firstattrib(node)); | |
| 712 if (xmlnode_has_children(node)) | |
| 713 xmlnode_insert_node(child, xmlnode_get_firstchild(node)); | |
| 714 | |
| 715 return child; | |
| 716 } | |
| 717 | |
| 718 /* places copy of node and node's siblings in parent */ | |
| 719 void xmlnode_insert_node(xmlnode parent, xmlnode node) | |
| 720 { | |
| 721 if(node == NULL || parent == NULL) | |
| 722 return; | |
| 723 | |
| 724 while(node != NULL) | |
| 725 { | |
| 726 switch(xmlnode_get_type(node)) | |
| 727 { | |
| 728 case NTYPE_ATTRIB: | |
| 729 xmlnode_put_attrib(parent, xmlnode_get_name(node), xmlnode_get_data(node)); | |
| 730 break; | |
| 731 case NTYPE_TAG: | |
| 732 xmlnode_insert_tag_node(parent, node); | |
| 733 break; | |
| 734 case NTYPE_CDATA: | |
| 735 xmlnode_insert_cdata(parent, xmlnode_get_data(node), xmlnode_get_datasz(node)); | |
| 736 } | |
| 737 node = xmlnode_get_nextsibling(node); | |
| 738 } | |
| 739 } | |
| 740 | |
| 741 | |
| 742 /* produce full duplicate of x with a new pool, x must be a tag! */ | |
| 743 xmlnode xmlnode_dup(xmlnode x) | |
| 744 { | |
| 745 xmlnode x2; | |
| 746 | |
| 747 if(x == NULL) | |
| 748 return NULL; | |
| 749 | |
| 750 x2 = xmlnode_new_tag(xmlnode_get_name(x)); | |
| 751 | |
| 752 if (xmlnode_has_attribs(x)) | |
| 753 xmlnode_insert_node(x2, xmlnode_get_firstattrib(x)); | |
| 754 if (xmlnode_has_children(x)) | |
| 755 xmlnode_insert_node(x2, xmlnode_get_firstchild(x)); | |
| 756 | |
| 757 return x2; | |
| 758 } | |
| 759 | |
| 760 xmlnode xmlnode_dup_pool(pool p, xmlnode x) | |
| 761 { | |
| 762 xmlnode x2; | |
| 763 | |
| 764 if(x == NULL) | |
| 765 return NULL; | |
| 766 | |
| 767 x2 = xmlnode_new_tag_pool(p, xmlnode_get_name(x)); | |
| 768 | |
| 769 if (xmlnode_has_attribs(x)) | |
| 770 xmlnode_insert_node(x2, xmlnode_get_firstattrib(x)); | |
| 771 if (xmlnode_has_children(x)) | |
| 772 xmlnode_insert_node(x2, xmlnode_get_firstchild(x)); | |
| 773 | |
| 774 return x2; | |
| 775 } | |
| 776 | |
| 777 xmlnode xmlnode_wrap(xmlnode x,const char *wrapper) | |
| 778 { | |
| 779 xmlnode wrap; | |
| 780 if(x==NULL||wrapper==NULL) return NULL; | |
| 781 wrap=xmlnode_new_tag_pool(xmlnode_pool(x),wrapper); | |
| 782 if(wrap==NULL) return NULL; | |
| 783 wrap->firstchild=x; | |
| 784 wrap->lastchild=x; | |
| 785 x->parent=wrap; | |
| 786 return wrap; | |
| 787 } | |
| 788 | |
| 789 void xmlnode_free(xmlnode node) | |
| 790 { | |
| 791 if(node == NULL) | |
| 792 return; | |
| 793 | |
| 794 pool_free(node->p); | |
| 795 } |
