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 | static int _xode_strcmp(const char *a, const char *b) |
---|
23 | { |
---|
24 | if(a == NULL || b == NULL) return -1; |
---|
25 | |
---|
26 | return strcmp(a,b); |
---|
27 | } |
---|
28 | |
---|
29 | /* Internal routines */ |
---|
30 | static xode _xode_new(xode_pool p, const char* name, unsigned int type) |
---|
31 | { |
---|
32 | xode result = NULL; |
---|
33 | if (type > XODE_TYPE_LAST) |
---|
34 | return NULL; |
---|
35 | |
---|
36 | if (type != XODE_TYPE_CDATA && name == NULL) |
---|
37 | return NULL; |
---|
38 | |
---|
39 | if (p == NULL) |
---|
40 | { |
---|
41 | p = xode_pool_heap(1*1024); |
---|
42 | } |
---|
43 | |
---|
44 | /* Allocate & zero memory */ |
---|
45 | result = (xode)xode_pool_malloc(p, sizeof(_xode)); |
---|
46 | memset(result, '\0', sizeof(_xode)); |
---|
47 | |
---|
48 | /* Initialize fields */ |
---|
49 | if (type != XODE_TYPE_CDATA) |
---|
50 | result->name = xode_pool_strdup(p,name); |
---|
51 | result->type = type; |
---|
52 | result->p = p; |
---|
53 | return result; |
---|
54 | } |
---|
55 | |
---|
56 | static xode _xode_appendsibling(xode lastsibling, const char* name, unsigned int type) |
---|
57 | { |
---|
58 | xode result; |
---|
59 | |
---|
60 | result = _xode_new(xode_get_pool(lastsibling), name, type); |
---|
61 | if (result != NULL) |
---|
62 | { |
---|
63 | /* Setup sibling pointers */ |
---|
64 | result->prev = lastsibling; |
---|
65 | lastsibling->next = result; |
---|
66 | } |
---|
67 | return result; |
---|
68 | } |
---|
69 | |
---|
70 | static xode _xode_insert(xode parent, const char* name, unsigned int type) |
---|
71 | { |
---|
72 | xode result; |
---|
73 | |
---|
74 | if(parent == NULL || name == NULL) return NULL; |
---|
75 | |
---|
76 | /* If parent->firstchild is NULL, simply create a new node for the first child */ |
---|
77 | if (parent->firstchild == NULL) |
---|
78 | { |
---|
79 | result = _xode_new(parent->p, name, type); |
---|
80 | parent->firstchild = result; |
---|
81 | } |
---|
82 | /* Otherwise, append this to the lastchild */ |
---|
83 | else |
---|
84 | { |
---|
85 | result= _xode_appendsibling(parent->lastchild, name, type); |
---|
86 | } |
---|
87 | result->parent = parent; |
---|
88 | parent->lastchild = result; |
---|
89 | return result; |
---|
90 | |
---|
91 | } |
---|
92 | |
---|
93 | static xode _xode_search(xode firstsibling, const char* name, unsigned int type) |
---|
94 | { |
---|
95 | xode current; |
---|
96 | |
---|
97 | /* Walk the sibling list, looking for a XODE_TYPE_TAG xode with |
---|
98 | the specified name */ |
---|
99 | current = firstsibling; |
---|
100 | while (current != NULL) |
---|
101 | { |
---|
102 | if (name != NULL && (current->type == type) && (_xode_strcmp(current->name, name) == 0)) |
---|
103 | return current; |
---|
104 | else |
---|
105 | current = current->next; |
---|
106 | } |
---|
107 | return NULL; |
---|
108 | } |
---|
109 | |
---|
110 | static char* _xode_merge(xode_pool p, char* dest, unsigned int destsize, const char* src, unsigned int srcsize) |
---|
111 | { |
---|
112 | char* result; |
---|
113 | result = (char*)xode_pool_malloc(p, destsize + srcsize + 1); |
---|
114 | memcpy(result, dest, destsize); |
---|
115 | memcpy(result+destsize, src, srcsize); |
---|
116 | result[destsize + srcsize] = '\0'; |
---|
117 | |
---|
118 | /* WARNING: major ugly hack: since we're throwing the old data away, let's jump in the xode_pool and subtract it from the size, this is for xmlstream's big-node checking */ |
---|
119 | p->size -= destsize; |
---|
120 | |
---|
121 | return result; |
---|
122 | } |
---|
123 | |
---|
124 | static void _xode_hidesibling(xode child) |
---|
125 | { |
---|
126 | if(child == NULL) |
---|
127 | return; |
---|
128 | |
---|
129 | if(child->prev != NULL) |
---|
130 | child->prev->next = child->next; |
---|
131 | if(child->next != NULL) |
---|
132 | child->next->prev = child->prev; |
---|
133 | } |
---|
134 | |
---|
135 | static void _xode_tag2str(xode_spool s, xode node, int flag) |
---|
136 | { |
---|
137 | xode tmp; |
---|
138 | |
---|
139 | if(flag==0 || flag==1) |
---|
140 | { |
---|
141 | xode_spooler(s,"<",xode_get_name(node),s); |
---|
142 | tmp = xode_get_firstattrib(node); |
---|
143 | while(tmp) { |
---|
144 | xode_spooler(s," ",xode_get_name(tmp),"='",xode_strescape(xode_get_pool(node),xode_get_data(tmp)),"'",s); |
---|
145 | tmp = xode_get_nextsibling(tmp); |
---|
146 | } |
---|
147 | if(flag==0) |
---|
148 | xode_spool_add(s,"/>"); |
---|
149 | else |
---|
150 | xode_spool_add(s,">"); |
---|
151 | } |
---|
152 | else |
---|
153 | { |
---|
154 | xode_spooler(s,"</",xode_get_name(node),">",s); |
---|
155 | } |
---|
156 | } |
---|
157 | |
---|
158 | static xode_spool _xode_tospool(xode node) |
---|
159 | { |
---|
160 | xode_spool s; |
---|
161 | int level=0,dir=0; |
---|
162 | xode tmp; |
---|
163 | |
---|
164 | if(!node || xode_get_type(node) != XODE_TYPE_TAG) |
---|
165 | return NULL; |
---|
166 | |
---|
167 | s = xode_spool_newfrompool(xode_get_pool(node)); |
---|
168 | if(!s) return(NULL); |
---|
169 | |
---|
170 | while(1) |
---|
171 | { |
---|
172 | if(dir==0) |
---|
173 | { |
---|
174 | if(xode_get_type(node) == XODE_TYPE_TAG) |
---|
175 | { |
---|
176 | if(xode_has_children(node)) |
---|
177 | { |
---|
178 | _xode_tag2str(s,node,1); |
---|
179 | node = xode_get_firstchild(node); |
---|
180 | level++; |
---|
181 | continue; |
---|
182 | } |
---|
183 | else |
---|
184 | { |
---|
185 | _xode_tag2str(s,node,0); |
---|
186 | } |
---|
187 | } |
---|
188 | else |
---|
189 | { |
---|
190 | xode_spool_add(s,xode_strescape(xode_get_pool(node),xode_get_data(node))); |
---|
191 | } |
---|
192 | } |
---|
193 | |
---|
194 | tmp = xode_get_nextsibling(node); |
---|
195 | if(!tmp) |
---|
196 | { |
---|
197 | node = xode_get_parent(node); |
---|
198 | level--; |
---|
199 | if(level>=0) _xode_tag2str(s,node,2); |
---|
200 | if(level<1) break; |
---|
201 | dir = 1; |
---|
202 | } |
---|
203 | else |
---|
204 | { |
---|
205 | node = tmp; |
---|
206 | dir = 0; |
---|
207 | } |
---|
208 | } |
---|
209 | |
---|
210 | return s; |
---|
211 | } |
---|
212 | |
---|
213 | |
---|
214 | /* External routines */ |
---|
215 | |
---|
216 | |
---|
217 | /* |
---|
218 | * xode_new_tag -- create a tag node |
---|
219 | * Automatically creates a memory xode_pool for the node. |
---|
220 | * |
---|
221 | * parameters |
---|
222 | * name -- name of the tag |
---|
223 | * |
---|
224 | * returns |
---|
225 | * a pointer to the tag node |
---|
226 | * or NULL if it was unsuccessfull |
---|
227 | */ |
---|
228 | xode xode_new(const char* name) |
---|
229 | { |
---|
230 | return _xode_new(NULL, name, XODE_TYPE_TAG); |
---|
231 | } |
---|
232 | |
---|
233 | |
---|
234 | /* |
---|
235 | * xode_new_tag_pool -- create a tag node within given pool |
---|
236 | * |
---|
237 | * parameters |
---|
238 | * p -- previously created memory pool |
---|
239 | * name -- name of the tag |
---|
240 | * |
---|
241 | * returns |
---|
242 | * a pointer to the tag node |
---|
243 | * or NULL if it was unsuccessfull |
---|
244 | */ |
---|
245 | xode xode_new_frompool(xode_pool p, const char* name) |
---|
246 | { |
---|
247 | return _xode_new(p, name, XODE_TYPE_TAG); |
---|
248 | } |
---|
249 | |
---|
250 | |
---|
251 | /* |
---|
252 | * xode_insert_tag -- append a child tag to a tag |
---|
253 | * |
---|
254 | * parameters |
---|
255 | * parent -- pointer to the parent tag |
---|
256 | * name -- name of the child tag |
---|
257 | * |
---|
258 | * returns |
---|
259 | * a pointer to the child tag node |
---|
260 | * or NULL if it was unsuccessfull |
---|
261 | */ |
---|
262 | xode xode_insert_tag(xode parent, const char* name) |
---|
263 | { |
---|
264 | return _xode_insert(parent, name, XODE_TYPE_TAG); |
---|
265 | } |
---|
266 | |
---|
267 | |
---|
268 | /* |
---|
269 | * xode_insert_cdata -- append character data to a tag |
---|
270 | * If last child of the parent is CDATA, merges CDATA nodes. Otherwise |
---|
271 | * creates a CDATA node, and appends it to the parent's child list. |
---|
272 | * |
---|
273 | * parameters |
---|
274 | * parent -- parent tag |
---|
275 | * CDATA -- character data |
---|
276 | * size -- size of CDATA |
---|
277 | * or -1 for null-terminated CDATA strings |
---|
278 | * |
---|
279 | * returns |
---|
280 | * a pointer to the child CDATA node |
---|
281 | * or NULL if it was unsuccessfull |
---|
282 | */ |
---|
283 | xode xode_insert_cdata(xode parent, const char* CDATA, unsigned int size) |
---|
284 | { |
---|
285 | xode result; |
---|
286 | |
---|
287 | if(CDATA == NULL || parent == NULL) |
---|
288 | return NULL; |
---|
289 | |
---|
290 | if(size == -1) |
---|
291 | size = strlen(CDATA); |
---|
292 | |
---|
293 | if ((parent->lastchild != NULL) && (parent->lastchild->type == XODE_TYPE_CDATA)) |
---|
294 | { |
---|
295 | result = parent->lastchild; |
---|
296 | result->data = _xode_merge(result->p, result->data, result->data_sz, CDATA, size); |
---|
297 | result->data_sz = result->data_sz + size; |
---|
298 | } |
---|
299 | else |
---|
300 | { |
---|
301 | result = _xode_insert(parent, "", XODE_TYPE_CDATA); |
---|
302 | if (result != NULL) |
---|
303 | { |
---|
304 | result->data = (char*)xode_pool_malloc(result->p, size + 1); |
---|
305 | memcpy(result->data, CDATA, size); |
---|
306 | result->data[size] = '\0'; |
---|
307 | result->data_sz = size; |
---|
308 | } |
---|
309 | } |
---|
310 | |
---|
311 | return result; |
---|
312 | } |
---|
313 | |
---|
314 | |
---|
315 | /* |
---|
316 | * xode_gettag -- find given tag in an xode tree |
---|
317 | * |
---|
318 | * parameters |
---|
319 | * parent -- pointer to the parent tag |
---|
320 | * name -- "name" for the child tag of that name |
---|
321 | * "name/name" for a sub child (recurses) |
---|
322 | * "?attrib" to match the first tag with that attrib defined |
---|
323 | * "?attrib=value" to match the first tag with that attrib and value |
---|
324 | * or any combination: "name/name/?attrib", etc |
---|
325 | * |
---|
326 | * results |
---|
327 | * a pointer to the tag matching search criteria |
---|
328 | * or NULL if search was unsuccessfull |
---|
329 | */ |
---|
330 | xode xode_get_tag(xode parent, const char* name) |
---|
331 | { |
---|
332 | char *str, *slash, *qmark, *equals; |
---|
333 | xode step, ret; |
---|
334 | |
---|
335 | if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL; |
---|
336 | |
---|
337 | if(strstr(name, "/") == NULL && strstr(name,"?") == NULL) |
---|
338 | return _xode_search(parent->firstchild, name, XODE_TYPE_TAG); |
---|
339 | |
---|
340 | /* jer's note: why can't I modify the name directly, why do I have to strdup it? damn c grrr! */ |
---|
341 | str = strdup(name); |
---|
342 | slash = strstr(str, "/"); |
---|
343 | qmark = strstr(str, "?"); |
---|
344 | equals = strstr(str, "="); |
---|
345 | |
---|
346 | if(qmark != NULL && (slash == NULL || qmark < slash)) |
---|
347 | { /* of type ?attrib */ |
---|
348 | |
---|
349 | *qmark = '\0'; |
---|
350 | qmark++; |
---|
351 | if(equals != NULL) |
---|
352 | { |
---|
353 | *equals = '\0'; |
---|
354 | equals++; |
---|
355 | } |
---|
356 | |
---|
357 | for(step = parent->firstchild; step != NULL; step = xode_get_nextsibling(step)) |
---|
358 | { |
---|
359 | if(xode_get_type(step) != XODE_TYPE_TAG) |
---|
360 | continue; |
---|
361 | |
---|
362 | if(*str != '\0') |
---|
363 | if(_xode_strcmp(xode_get_name(step),str) != 0) |
---|
364 | continue; |
---|
365 | |
---|
366 | if(xode_get_attrib(step,qmark) == NULL) |
---|
367 | continue; |
---|
368 | |
---|
369 | if(equals != NULL && _xode_strcmp(xode_get_attrib(step,qmark),equals) != 0) |
---|
370 | continue; |
---|
371 | |
---|
372 | break; |
---|
373 | } |
---|
374 | |
---|
375 | free(str); |
---|
376 | return step; |
---|
377 | } |
---|
378 | |
---|
379 | |
---|
380 | *slash = '\0'; |
---|
381 | ++slash; |
---|
382 | |
---|
383 | for(step = parent->firstchild; step != NULL; step = xode_get_nextsibling(step)) |
---|
384 | { |
---|
385 | if(xode_get_type(step) != XODE_TYPE_TAG) continue; |
---|
386 | |
---|
387 | if(_xode_strcmp(xode_get_name(step),str) != 0) |
---|
388 | continue; |
---|
389 | |
---|
390 | ret = xode_get_tag(step, slash); |
---|
391 | if(ret != NULL) |
---|
392 | { |
---|
393 | free(str); |
---|
394 | return ret; |
---|
395 | } |
---|
396 | } |
---|
397 | |
---|
398 | free(str); |
---|
399 | return NULL; |
---|
400 | } |
---|
401 | |
---|
402 | |
---|
403 | /* return the cdata from any tag */ |
---|
404 | char *xode_get_tagdata(xode parent, const char *name) |
---|
405 | { |
---|
406 | xode tag; |
---|
407 | |
---|
408 | tag = xode_get_tag(parent, name); |
---|
409 | if(tag == NULL) return NULL; |
---|
410 | |
---|
411 | return xode_get_data(tag); |
---|
412 | } |
---|
413 | |
---|
414 | |
---|
415 | void xode_put_attrib(xode owner, const char* name, const char* value) |
---|
416 | { |
---|
417 | xode attrib; |
---|
418 | |
---|
419 | if(owner == NULL || name == NULL || value == NULL) return; |
---|
420 | |
---|
421 | /* If there are no existing attributs, allocate a new one to start |
---|
422 | the list */ |
---|
423 | if (owner->firstattrib == NULL) |
---|
424 | { |
---|
425 | attrib = _xode_new(owner->p, name, XODE_TYPE_ATTRIB); |
---|
426 | owner->firstattrib = attrib; |
---|
427 | owner->lastattrib = attrib; |
---|
428 | } |
---|
429 | else |
---|
430 | { |
---|
431 | attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB); |
---|
432 | if(attrib == NULL) |
---|
433 | { |
---|
434 | attrib = _xode_appendsibling(owner->lastattrib, name, XODE_TYPE_ATTRIB); |
---|
435 | owner->lastattrib = attrib; |
---|
436 | } |
---|
437 | } |
---|
438 | /* Update the value of the attribute */ |
---|
439 | attrib->data_sz = strlen(value); |
---|
440 | attrib->data = xode_pool_strdup(owner->p, value); |
---|
441 | |
---|
442 | } |
---|
443 | |
---|
444 | char* xode_get_attrib(xode owner, const char* name) |
---|
445 | { |
---|
446 | xode attrib; |
---|
447 | |
---|
448 | if (owner != NULL && owner->firstattrib != NULL) |
---|
449 | { |
---|
450 | attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB); |
---|
451 | if (attrib != NULL) |
---|
452 | return (char*)attrib->data; |
---|
453 | } |
---|
454 | return NULL; |
---|
455 | } |
---|
456 | |
---|
457 | void xode_put_vattrib(xode owner, const char* name, void *value) |
---|
458 | { |
---|
459 | xode attrib; |
---|
460 | |
---|
461 | if (owner != NULL) |
---|
462 | { |
---|
463 | attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB); |
---|
464 | if (attrib == NULL) |
---|
465 | { |
---|
466 | xode_put_attrib(owner, name, ""); |
---|
467 | attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB); |
---|
468 | } |
---|
469 | if (attrib != NULL) |
---|
470 | attrib->firstchild = (xode)value; |
---|
471 | } |
---|
472 | } |
---|
473 | |
---|
474 | void* xode_get_vattrib(xode owner, const char* name) |
---|
475 | { |
---|
476 | xode attrib; |
---|
477 | |
---|
478 | if (owner != NULL && owner->firstattrib != NULL) |
---|
479 | { |
---|
480 | attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB); |
---|
481 | if (attrib != NULL) |
---|
482 | return (void*)attrib->firstchild; |
---|
483 | } |
---|
484 | return NULL; |
---|
485 | } |
---|
486 | |
---|
487 | xode xode_get_firstattrib(xode parent) |
---|
488 | { |
---|
489 | if (parent != NULL) |
---|
490 | return parent->firstattrib; |
---|
491 | return NULL; |
---|
492 | } |
---|
493 | |
---|
494 | xode xode_get_firstchild(xode parent) |
---|
495 | { |
---|
496 | if (parent != NULL) |
---|
497 | return parent->firstchild; |
---|
498 | return NULL; |
---|
499 | } |
---|
500 | |
---|
501 | xode xode_get_lastchild(xode parent) |
---|
502 | { |
---|
503 | if (parent != NULL) |
---|
504 | return parent->lastchild; |
---|
505 | return NULL; |
---|
506 | } |
---|
507 | |
---|
508 | xode xode_get_nextsibling(xode sibling) |
---|
509 | { |
---|
510 | if (sibling != NULL) |
---|
511 | return sibling->next; |
---|
512 | return NULL; |
---|
513 | } |
---|
514 | |
---|
515 | xode xode_get_prevsibling(xode sibling) |
---|
516 | { |
---|
517 | if (sibling != NULL) |
---|
518 | return sibling->prev; |
---|
519 | return NULL; |
---|
520 | } |
---|
521 | |
---|
522 | xode xode_get_parent(xode node) |
---|
523 | { |
---|
524 | if (node != NULL) |
---|
525 | return node->parent; |
---|
526 | return NULL; |
---|
527 | } |
---|
528 | |
---|
529 | char* xode_get_name(xode node) |
---|
530 | { |
---|
531 | if (node != NULL) |
---|
532 | return node->name; |
---|
533 | return NULL; |
---|
534 | } |
---|
535 | |
---|
536 | char* xode_get_data(xode node) |
---|
537 | { |
---|
538 | xode cur; |
---|
539 | |
---|
540 | if(node == NULL) return NULL; |
---|
541 | |
---|
542 | if(xode_get_type(node) == XODE_TYPE_TAG) /* loop till we find a CDATA */ |
---|
543 | { |
---|
544 | for(cur = xode_get_firstchild(node); cur != NULL; cur = xode_get_nextsibling(cur)) |
---|
545 | if(xode_get_type(cur) == XODE_TYPE_CDATA) |
---|
546 | return cur->data; |
---|
547 | }else{ |
---|
548 | return node->data; |
---|
549 | } |
---|
550 | return NULL; |
---|
551 | } |
---|
552 | |
---|
553 | int xode_get_datasz(xode node) |
---|
554 | { |
---|
555 | |
---|
556 | if( node == NULL ) |
---|
557 | { |
---|
558 | return (int)NULL; |
---|
559 | } |
---|
560 | else if(xode_get_type(node) == XODE_TYPE_TAG) /* loop till we find a CDATA */ |
---|
561 | { |
---|
562 | xode cur; |
---|
563 | for(cur = xode_get_firstchild(node); cur != NULL; cur = xode_get_nextsibling(cur)) |
---|
564 | if(xode_get_type(cur) == XODE_TYPE_CDATA) |
---|
565 | return cur->data_sz; |
---|
566 | }else{ |
---|
567 | return node->data_sz; |
---|
568 | } |
---|
569 | return (int)NULL; |
---|
570 | } |
---|
571 | |
---|
572 | int xode_get_type(xode node) |
---|
573 | { |
---|
574 | if (node != NULL) |
---|
575 | { |
---|
576 | return node->type; |
---|
577 | } |
---|
578 | return (int)NULL; |
---|
579 | } |
---|
580 | |
---|
581 | int xode_has_children(xode node) |
---|
582 | { |
---|
583 | if ((node != NULL) && (node->firstchild != NULL)) |
---|
584 | return 1; |
---|
585 | return 0; |
---|
586 | } |
---|
587 | |
---|
588 | int xode_has_attribs(xode node) |
---|
589 | { |
---|
590 | if ((node != NULL) && (node->firstattrib != NULL)) |
---|
591 | return 1; |
---|
592 | return 0; |
---|
593 | } |
---|
594 | |
---|
595 | xode_pool xode_get_pool(xode node) |
---|
596 | { |
---|
597 | if (node != NULL) |
---|
598 | return node->p; |
---|
599 | return (xode_pool)NULL; |
---|
600 | } |
---|
601 | |
---|
602 | void xode_hide(xode child) |
---|
603 | { |
---|
604 | xode parent; |
---|
605 | |
---|
606 | if(child == NULL || child->parent == NULL) |
---|
607 | return; |
---|
608 | |
---|
609 | parent = child->parent; |
---|
610 | |
---|
611 | /* first fix up at the child level */ |
---|
612 | _xode_hidesibling(child); |
---|
613 | |
---|
614 | /* next fix up at the parent level */ |
---|
615 | if(parent->firstchild == child) |
---|
616 | parent->firstchild = child->next; |
---|
617 | if(parent->lastchild == child) |
---|
618 | parent->lastchild = child->prev; |
---|
619 | } |
---|
620 | |
---|
621 | void xode_hide_attrib(xode parent, const char *name) |
---|
622 | { |
---|
623 | xode attrib; |
---|
624 | |
---|
625 | if(parent == NULL || parent->firstattrib == NULL || name == NULL) |
---|
626 | return; |
---|
627 | |
---|
628 | attrib = _xode_search(parent->firstattrib, name, XODE_TYPE_ATTRIB); |
---|
629 | if(attrib == NULL) |
---|
630 | return; |
---|
631 | |
---|
632 | /* first fix up at the child level */ |
---|
633 | _xode_hidesibling(attrib); |
---|
634 | |
---|
635 | /* next fix up at the parent level */ |
---|
636 | if(parent->firstattrib == attrib) |
---|
637 | parent->firstattrib = attrib->next; |
---|
638 | if(parent->lastattrib == attrib) |
---|
639 | parent->lastattrib = attrib->prev; |
---|
640 | } |
---|
641 | |
---|
642 | |
---|
643 | |
---|
644 | /* |
---|
645 | * xode2str -- convert given xode tree into a string |
---|
646 | * |
---|
647 | * parameters |
---|
648 | * node -- pointer to the xode structure |
---|
649 | * |
---|
650 | * results |
---|
651 | * a pointer to the created string |
---|
652 | * or NULL if it was unsuccessfull |
---|
653 | */ |
---|
654 | char *xode_to_str(xode node) |
---|
655 | { |
---|
656 | return xode_spool_tostr(_xode_tospool(node)); |
---|
657 | } |
---|
658 | |
---|
659 | |
---|
660 | /* loop through both a and b comparing everything, attribs, cdata, children, etc */ |
---|
661 | int xode_cmp(xode a, xode b) |
---|
662 | { |
---|
663 | int ret = 0; |
---|
664 | |
---|
665 | while(1) |
---|
666 | { |
---|
667 | if(a == NULL && b == NULL) |
---|
668 | return 0; |
---|
669 | |
---|
670 | if(a == NULL || b == NULL) |
---|
671 | return -1; |
---|
672 | |
---|
673 | if(xode_get_type(a) != xode_get_type(b)) |
---|
674 | return -1; |
---|
675 | |
---|
676 | switch(xode_get_type(a)) |
---|
677 | { |
---|
678 | case XODE_TYPE_ATTRIB: |
---|
679 | ret = _xode_strcmp(xode_get_name(a), xode_get_name(b)); |
---|
680 | if(ret != 0) |
---|
681 | return -1; |
---|
682 | ret = _xode_strcmp(xode_get_data(a), xode_get_data(b)); |
---|
683 | if(ret != 0) |
---|
684 | return -1; |
---|
685 | break; |
---|
686 | case XODE_TYPE_TAG: |
---|
687 | ret = _xode_strcmp(xode_get_name(a), xode_get_name(b)); |
---|
688 | if(ret != 0) |
---|
689 | return -1; |
---|
690 | ret = xode_cmp(xode_get_firstattrib(a), xode_get_firstattrib(b)); |
---|
691 | if(ret != 0) |
---|
692 | return -1; |
---|
693 | ret = xode_cmp(xode_get_firstchild(a), xode_get_firstchild(b)); |
---|
694 | if(ret != 0) |
---|
695 | return -1; |
---|
696 | break; |
---|
697 | case XODE_TYPE_CDATA: |
---|
698 | ret = _xode_strcmp(xode_get_data(a), xode_get_data(b)); |
---|
699 | if(ret != 0) |
---|
700 | return -1; |
---|
701 | } |
---|
702 | a = xode_get_nextsibling(a); |
---|
703 | b = xode_get_nextsibling(b); |
---|
704 | } |
---|
705 | } |
---|
706 | |
---|
707 | |
---|
708 | xode xode_insert_tagnode(xode parent, xode node) |
---|
709 | { |
---|
710 | xode child; |
---|
711 | |
---|
712 | child = xode_insert_tag(parent, xode_get_name(node)); |
---|
713 | if (xode_has_attribs(node)) |
---|
714 | xode_insert_node(child, xode_get_firstattrib(node)); |
---|
715 | if (xode_has_children(node)) |
---|
716 | xode_insert_node(child, xode_get_firstchild(node)); |
---|
717 | |
---|
718 | return child; |
---|
719 | } |
---|
720 | |
---|
721 | /* places copy of node and node's siblings in parent */ |
---|
722 | void xode_insert_node(xode parent, xode node) |
---|
723 | { |
---|
724 | if(node == NULL || parent == NULL) |
---|
725 | return; |
---|
726 | |
---|
727 | while(node != NULL) |
---|
728 | { |
---|
729 | switch(xode_get_type(node)) |
---|
730 | { |
---|
731 | case XODE_TYPE_ATTRIB: |
---|
732 | xode_put_attrib(parent, xode_get_name(node), xode_get_data(node)); |
---|
733 | break; |
---|
734 | case XODE_TYPE_TAG: |
---|
735 | xode_insert_tagnode(parent, node); |
---|
736 | break; |
---|
737 | case XODE_TYPE_CDATA: |
---|
738 | xode_insert_cdata(parent, xode_get_data(node), xode_get_datasz(node)); |
---|
739 | } |
---|
740 | node = xode_get_nextsibling(node); |
---|
741 | } |
---|
742 | } |
---|
743 | |
---|
744 | |
---|
745 | /* produce full duplicate of x with a new xode_pool, x must be a tag! */ |
---|
746 | xode xode_dup(xode x) |
---|
747 | { |
---|
748 | xode x2; |
---|
749 | |
---|
750 | if(x == NULL) |
---|
751 | return NULL; |
---|
752 | |
---|
753 | x2 = xode_new(xode_get_name(x)); |
---|
754 | |
---|
755 | if (xode_has_attribs(x)) |
---|
756 | xode_insert_node(x2, xode_get_firstattrib(x)); |
---|
757 | if (xode_has_children(x)) |
---|
758 | xode_insert_node(x2, xode_get_firstchild(x)); |
---|
759 | |
---|
760 | return x2; |
---|
761 | } |
---|
762 | |
---|
763 | xode xode_dup_frompool(xode_pool p, xode x) |
---|
764 | { |
---|
765 | xode x2; |
---|
766 | |
---|
767 | if(x == NULL) |
---|
768 | return NULL; |
---|
769 | |
---|
770 | x2 = xode_new_frompool(p, xode_get_name(x)); |
---|
771 | |
---|
772 | if (xode_has_attribs(x)) |
---|
773 | xode_insert_node(x2, xode_get_firstattrib(x)); |
---|
774 | if (xode_has_children(x)) |
---|
775 | xode_insert_node(x2, xode_get_firstchild(x)); |
---|
776 | |
---|
777 | return x2; |
---|
778 | } |
---|
779 | |
---|
780 | xode xode_wrap(xode x,const char *wrapper) |
---|
781 | { |
---|
782 | xode wrap; |
---|
783 | if(x==NULL||wrapper==NULL) return NULL; |
---|
784 | wrap=xode_new_frompool(xode_get_pool(x),wrapper); |
---|
785 | if(wrap==NULL) return NULL; |
---|
786 | wrap->firstchild=x; |
---|
787 | wrap->lastchild=x; |
---|
788 | x->parent=wrap; |
---|
789 | return wrap; |
---|
790 | } |
---|
791 | |
---|
792 | void xode_free(xode node) |
---|
793 | { |
---|
794 | if(node == NULL) |
---|
795 | return; |
---|
796 | |
---|
797 | xode_pool_free(node->p); |
---|
798 | } |
---|
799 | |
---|
800 | |
---|
801 | void |
---|
802 | _xode_to_prettystr( xode_spool s, xode x, int deep ) |
---|
803 | { |
---|
804 | int i; |
---|
805 | xode y; |
---|
806 | |
---|
807 | if(xode_get_type(x) != XODE_TYPE_TAG) return; |
---|
808 | |
---|
809 | for(i=0; i<deep; i++) xode_spool_add(s, "\t"); |
---|
810 | |
---|
811 | xode_spooler( s , "<" , xode_get_name(x) , s ); |
---|
812 | |
---|
813 | y = xode_get_firstattrib(x); |
---|
814 | while( y ) |
---|
815 | { |
---|
816 | xode_spooler( s , " " , xode_get_name(y) , "='", xode_get_data(y) , "'" , s ); |
---|
817 | |
---|
818 | y = xode_get_nextsibling( y ); |
---|
819 | } |
---|
820 | xode_spool_add(s,">"); |
---|
821 | xode_spool_add(s,"\n"); |
---|
822 | |
---|
823 | if( xode_get_data(x)) |
---|
824 | { |
---|
825 | for(i=0; i<=deep; i++) xode_spool_add(s, "\t"); |
---|
826 | xode_spool_add( s , xode_get_data(x)); |
---|
827 | } |
---|
828 | |
---|
829 | y = xode_get_firstchild(x); |
---|
830 | while( y ) |
---|
831 | { |
---|
832 | _xode_to_prettystr(s , y, deep+1); |
---|
833 | y = xode_get_nextsibling(y); |
---|
834 | xode_spool_add(s,"\n"); |
---|
835 | } |
---|
836 | |
---|
837 | for(i=0; i<deep; i++) xode_spool_add(s, "\t"); |
---|
838 | xode_spooler( s , "</" , xode_get_name(x) , ">" , s ); |
---|
839 | |
---|
840 | return; |
---|
841 | } |
---|
842 | |
---|
843 | char * |
---|
844 | xode_to_prettystr( xode x ) |
---|
845 | { |
---|
846 | xode_spool s; |
---|
847 | |
---|
848 | if( !x) return NULL; |
---|
849 | |
---|
850 | s = xode_spool_newfrompool( xode_get_pool(x)); |
---|
851 | |
---|
852 | _xode_to_prettystr( s , x, 0 ); |
---|
853 | |
---|
854 | return xode_spool_tostr(s); |
---|
855 | } |
---|
856 | |
---|