00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "xode.h"
00027
00028 static int _xode_strcmp(const char *a, const char *b)
00029 {
00030 if(a == NULL || b == NULL) return -1;
00031
00032 return strcmp(a,b);
00033 }
00034
00036 static xode _xode_new(xode_pool p, const char* name, unsigned int type)
00037 {
00038 xode result = NULL;
00039 if (type > XODE_TYPE_LAST)
00040 return NULL;
00041
00042 if (type != XODE_TYPE_CDATA && name == NULL)
00043 return NULL;
00044
00045 if (p == NULL)
00046 {
00047 p = xode_pool_heap(1*1024);
00048 }
00049
00050
00051 result = (xode)xode_pool_malloc(p, sizeof(_xode));
00052 memset(result, '\0', sizeof(_xode));
00053
00054
00055 if (type != XODE_TYPE_CDATA)
00056 result->name = xode_pool_strdup(p,name);
00057 result->type = type;
00058 result->p = p;
00059 return result;
00060 }
00061
00062 static xode _xode_appendsibling(xode lastsibling, const char* name, unsigned int type)
00063 {
00064 xode result;
00065
00066 result = _xode_new(xode_get_pool(lastsibling), name, type);
00067 if (result != NULL)
00068 {
00069
00070 result->prev = lastsibling;
00071 lastsibling->next = result;
00072 }
00073 return result;
00074 }
00075
00076 static xode _xode_insert(xode parent, const char* name, unsigned int type)
00077 {
00078 xode result;
00079
00080 if(parent == NULL || name == NULL) return NULL;
00081
00082
00083 if (parent->firstchild == NULL)
00084 {
00085 result = _xode_new(parent->p, name, type);
00086 parent->firstchild = result;
00087 }
00088
00089 else
00090 {
00091 result= _xode_appendsibling(parent->lastchild, name, type);
00092 }
00093 result->parent = parent;
00094 parent->lastchild = result;
00095 return result;
00096
00097 }
00098
00099 static xode _xode_search(xode firstsibling, const char* name, unsigned int type)
00100 {
00101 xode current;
00102
00103
00104
00105 current = firstsibling;
00106 while (current != NULL)
00107 {
00108 if (name != NULL && (current->type == type) && (_xode_strcmp(current->name, name) == 0))
00109 return current;
00110 else
00111 current = current->next;
00112 }
00113 return NULL;
00114 }
00115
00116 static char* _xode_merge(xode_pool p, char* dest, unsigned int destsize, const char* src, unsigned int srcsize)
00117 {
00118 char* result;
00119 result = (char*)xode_pool_malloc(p, destsize + srcsize + 1);
00120 memcpy(result, dest, destsize);
00121 memcpy(result+destsize, src, srcsize);
00122 result[destsize + srcsize] = '\0';
00123
00124
00125 p->size -= destsize;
00126
00127 return result;
00128 }
00129
00130 static void _xode_hidesibling(xode child)
00131 {
00132 if(child == NULL)
00133 return;
00134
00135 if(child->prev != NULL)
00136 child->prev->next = child->next;
00137 if(child->next != NULL)
00138 child->next->prev = child->prev;
00139 }
00140
00141 static void _xode_tag2str(xode_spool s, xode node, int flag)
00142 {
00143 xode tmp;
00144
00145 if(flag==0 || flag==1)
00146 {
00147 xode_spooler(s,"<",xode_get_name(node),s);
00148 tmp = xode_get_firstattrib(node);
00149 while(tmp) {
00150 xode_spooler(s," ",xode_get_name(tmp),"='",xode_strescape(xode_get_pool(node),xode_get_data(tmp)),"'",s);
00151 tmp = xode_get_nextsibling(tmp);
00152 }
00153 if(flag==0)
00154 xode_spool_add(s,"/>");
00155 else
00156 xode_spool_add(s,">");
00157 }
00158 else
00159 {
00160 xode_spooler(s,"</",xode_get_name(node),">",s);
00161 }
00162 }
00163
00164 static xode_spool _xode_tospool(xode node)
00165 {
00166 xode_spool s;
00167 int level=0,dir=0;
00168 xode tmp;
00169
00170 if(!node || xode_get_type(node) != XODE_TYPE_TAG)
00171 return NULL;
00172
00173 s = xode_spool_newfrompool(xode_get_pool(node));
00174 if(!s) return(NULL);
00175
00176 while(1)
00177 {
00178 if(dir==0)
00179 {
00180 if(xode_get_type(node) == XODE_TYPE_TAG)
00181 {
00182 if(xode_has_children(node))
00183 {
00184 _xode_tag2str(s,node,1);
00185 node = xode_get_firstchild(node);
00186 level++;
00187 continue;
00188 }
00189 else
00190 {
00191 _xode_tag2str(s,node,0);
00192 }
00193 }
00194 else
00195 {
00196 xode_spool_add(s,xode_strescape(xode_get_pool(node),xode_get_data(node)));
00197 }
00198 }
00199
00200 tmp = xode_get_nextsibling(node);
00201 if(!tmp)
00202 {
00203 node = xode_get_parent(node);
00204 level--;
00205 if(level>=0) _xode_tag2str(s,node,2);
00206 if(level<1) break;
00207 dir = 1;
00208 }
00209 else
00210 {
00211 node = tmp;
00212 dir = 0;
00213 }
00214 }
00215
00216 return s;
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 xode xode_new(const char* name)
00235 {
00236 return _xode_new(NULL, name, XODE_TYPE_TAG);
00237 }
00238
00239
00240
00241
00242 xode xode_new_tag(const char* name)
00243 {
00244 return _xode_new(NULL, name, XODE_TYPE_TAG);
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 xode xode_new_frompool(xode_pool p, const char* name)
00259 {
00260 return _xode_new(p, name, XODE_TYPE_TAG);
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 xode xode_insert_tag(xode parent, const char* name)
00276 {
00277 return _xode_insert(parent, name, XODE_TYPE_TAG);
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 xode xode_insert_cdata(xode parent, const char* CDATA, unsigned int size)
00297 {
00298 xode result;
00299
00300 if(CDATA == NULL || parent == NULL)
00301 return NULL;
00302
00303 if(size == -1)
00304 size = strlen(CDATA);
00305
00306 if ((parent->lastchild != NULL) && (parent->lastchild->type == XODE_TYPE_CDATA))
00307 {
00308 result = parent->lastchild;
00309 result->data = _xode_merge(result->p, result->data, result->data_sz, CDATA, size);
00310 result->data_sz = result->data_sz + size;
00311 }
00312 else
00313 {
00314 result = _xode_insert(parent, "", XODE_TYPE_CDATA);
00315 if (result != NULL)
00316 {
00317 result->data = (char*)xode_pool_malloc(result->p, size + 1);
00318 memcpy(result->data, CDATA, size);
00319 result->data[size] = '\0';
00320 result->data_sz = size;
00321 }
00322 }
00323
00324 return result;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 xode xode_get_tag(xode parent, const char* name)
00344 {
00345 char *str, *slash, *qmark, *equals;
00346 xode step, ret;
00347
00348 if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL;
00349
00350 if(strstr(name, "/") == NULL && strstr(name,"?") == NULL)
00351 return _xode_search(parent->firstchild, name, XODE_TYPE_TAG);
00352
00353
00354 str = strdup(name);
00355 slash = strstr(str, "/");
00356 qmark = strstr(str, "?");
00357 equals = strstr(str, "=");
00358
00359 if(qmark != NULL && (slash == NULL || qmark < slash))
00360 {
00361
00362 *qmark = '\0';
00363 qmark++;
00364 if(equals != NULL)
00365 {
00366 *equals = '\0';
00367 equals++;
00368 }
00369
00370 for(step = parent->firstchild; step != NULL; step = xode_get_nextsibling(step))
00371 {
00372 if(xode_get_type(step) != XODE_TYPE_TAG)
00373 continue;
00374
00375 if(*str != '\0')
00376 if(_xode_strcmp(xode_get_name(step),str) != 0)
00377 continue;
00378
00379 if(xode_get_attrib(step,qmark) == NULL)
00380 continue;
00381
00382 if(equals != NULL && _xode_strcmp(xode_get_attrib(step,qmark),equals) != 0)
00383 continue;
00384
00385 break;
00386 }
00387
00388 free(str);
00389 return step;
00390 }
00391
00392
00393 *slash = '\0';
00394 ++slash;
00395
00396 for(step = parent->firstchild; step != NULL; step = xode_get_nextsibling(step))
00397 {
00398 if(xode_get_type(step) != XODE_TYPE_TAG) continue;
00399
00400 if(_xode_strcmp(xode_get_name(step),str) != 0)
00401 continue;
00402
00403 ret = xode_get_tag(step, slash);
00404 if(ret != NULL)
00405 {
00406 free(str);
00407 return ret;
00408 }
00409 }
00410
00411 free(str);
00412 return NULL;
00413 }
00414
00415
00416
00417 char *xode_get_tagdata(xode parent, const char *name)
00418 {
00419 xode tag;
00420
00421 tag = xode_get_tag(parent, name);
00422 if(tag == NULL) return NULL;
00423
00424 return xode_get_data(tag);
00425 }
00426
00427
00428 void xode_put_attrib(xode owner, const char* name, const char* value)
00429 {
00430 xode attrib;
00431
00432 if(owner == NULL || name == NULL || value == NULL) return;
00433
00434
00435
00436 if (owner->firstattrib == NULL)
00437 {
00438 attrib = _xode_new(owner->p, name, XODE_TYPE_ATTRIB);
00439 owner->firstattrib = attrib;
00440 owner->lastattrib = attrib;
00441 }
00442 else
00443 {
00444 attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB);
00445 if(attrib == NULL)
00446 {
00447 attrib = _xode_appendsibling(owner->lastattrib, name, XODE_TYPE_ATTRIB);
00448 owner->lastattrib = attrib;
00449 }
00450 }
00451
00452 attrib->data_sz = strlen(value);
00453 attrib->data = xode_pool_strdup(owner->p, value);
00454
00455 }
00456
00457 char* xode_get_attrib(xode owner, const char* name)
00458 {
00459 xode attrib;
00460
00461 if (owner != NULL && owner->firstattrib != NULL)
00462 {
00463 attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB);
00464 if (attrib != NULL)
00465 return (char*)attrib->data;
00466 }
00467 return NULL;
00468 }
00469
00470 void xode_put_vattrib(xode owner, const char* name, void *value)
00471 {
00472 xode attrib;
00473
00474 if (owner != NULL)
00475 {
00476 attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB);
00477 if (attrib == NULL)
00478 {
00479 xode_put_attrib(owner, name, "");
00480 attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB);
00481 }
00482 if (attrib != NULL)
00483 attrib->firstchild = (xode)value;
00484 }
00485 }
00486
00487 void* xode_get_vattrib(xode owner, const char* name)
00488 {
00489 xode attrib;
00490
00491 if (owner != NULL && owner->firstattrib != NULL)
00492 {
00493 attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB);
00494 if (attrib != NULL)
00495 return (void*)attrib->firstchild;
00496 }
00497 return NULL;
00498 }
00499
00500 xode xode_get_firstattrib(xode parent)
00501 {
00502 if (parent != NULL)
00503 return parent->firstattrib;
00504 return NULL;
00505 }
00506
00507 xode xode_get_firstchild(xode parent)
00508 {
00509 if (parent != NULL)
00510 return parent->firstchild;
00511 return NULL;
00512 }
00513
00514 xode xode_get_lastchild(xode parent)
00515 {
00516 if (parent != NULL)
00517 return parent->lastchild;
00518 return NULL;
00519 }
00520
00521 xode xode_get_nextsibling(xode sibling)
00522 {
00523 if (sibling != NULL)
00524 return sibling->next;
00525 return NULL;
00526 }
00527
00528 xode xode_get_prevsibling(xode sibling)
00529 {
00530 if (sibling != NULL)
00531 return sibling->prev;
00532 return NULL;
00533 }
00534
00535 xode xode_get_parent(xode node)
00536 {
00537 if (node != NULL)
00538 return node->parent;
00539 return NULL;
00540 }
00541
00542 char* xode_get_name(xode node)
00543 {
00544 if (node != NULL)
00545 return node->name;
00546 return NULL;
00547 }
00548
00549 char* xode_get_data(xode node)
00550 {
00551 xode cur;
00552
00553 if(node == NULL) return NULL;
00554
00555 if(xode_get_type(node) == XODE_TYPE_TAG)
00556 {
00557 for(cur = xode_get_firstchild(node); cur != NULL; cur = xode_get_nextsibling(cur))
00558 if(xode_get_type(cur) == XODE_TYPE_CDATA)
00559 return cur->data;
00560 }else{
00561 return node->data;
00562 }
00563 return NULL;
00564 }
00565
00566 int xode_get_datasz(xode node)
00567 {
00568
00569 if( node == NULL )
00570 {
00571 return (int)(long)NULL;
00572 }
00573 else if(xode_get_type(node) == XODE_TYPE_TAG)
00574 {
00575 xode cur;
00576 for(cur = xode_get_firstchild(node); cur != NULL; cur = xode_get_nextsibling(cur))
00577 if(xode_get_type(cur) == XODE_TYPE_CDATA)
00578 return cur->data_sz;
00579 }else{
00580 return node->data_sz;
00581 }
00582 return (int)(long)NULL;
00583 }
00584
00585 int xode_get_type(xode node)
00586 {
00587 if (node != NULL)
00588 {
00589 return node->type;
00590 }
00591 return (int)(long)NULL;
00592 }
00593
00594 int xode_has_children(xode node)
00595 {
00596 if ((node != NULL) && (node->firstchild != NULL))
00597 return 1;
00598 return 0;
00599 }
00600
00601 int xode_has_attribs(xode node)
00602 {
00603 if ((node != NULL) && (node->firstattrib != NULL))
00604 return 1;
00605 return 0;
00606 }
00607
00608 xode_pool xode_get_pool(xode node)
00609 {
00610 if (node != NULL)
00611 return node->p;
00612 return (xode_pool)NULL;
00613 }
00614
00615 void xode_hide(xode child)
00616 {
00617 xode parent;
00618
00619 if(child == NULL || child->parent == NULL)
00620 return;
00621
00622 parent = child->parent;
00623
00624
00625 _xode_hidesibling(child);
00626
00627
00628 if(parent->firstchild == child)
00629 parent->firstchild = child->next;
00630 if(parent->lastchild == child)
00631 parent->lastchild = child->prev;
00632 }
00633
00634 void xode_hide_attrib(xode parent, const char *name)
00635 {
00636 xode attrib;
00637
00638 if(parent == NULL || parent->firstattrib == NULL || name == NULL)
00639 return;
00640
00641 attrib = _xode_search(parent->firstattrib, name, XODE_TYPE_ATTRIB);
00642 if(attrib == NULL)
00643 return;
00644
00645
00646 _xode_hidesibling(attrib);
00647
00648
00649 if(parent->firstattrib == attrib)
00650 parent->firstattrib = attrib->next;
00651 if(parent->lastattrib == attrib)
00652 parent->lastattrib = attrib->prev;
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 char *xode_to_str(xode node)
00668 {
00669 return xode_spool_tostr(_xode_tospool(node));
00670 }
00671
00672
00673
00674 int xode_cmp(xode a, xode b)
00675 {
00676 int ret = 0;
00677
00678 while(1)
00679 {
00680 if(a == NULL && b == NULL)
00681 return 0;
00682
00683 if(a == NULL || b == NULL)
00684 return -1;
00685
00686 if(xode_get_type(a) != xode_get_type(b))
00687 return -1;
00688
00689 switch(xode_get_type(a))
00690 {
00691 case XODE_TYPE_ATTRIB:
00692 ret = _xode_strcmp(xode_get_name(a), xode_get_name(b));
00693 if(ret != 0)
00694 return -1;
00695 ret = _xode_strcmp(xode_get_data(a), xode_get_data(b));
00696 if(ret != 0)
00697 return -1;
00698 break;
00699 case XODE_TYPE_TAG:
00700 ret = _xode_strcmp(xode_get_name(a), xode_get_name(b));
00701 if(ret != 0)
00702 return -1;
00703 ret = xode_cmp(xode_get_firstattrib(a), xode_get_firstattrib(b));
00704 if(ret != 0)
00705 return -1;
00706 ret = xode_cmp(xode_get_firstchild(a), xode_get_firstchild(b));
00707 if(ret != 0)
00708 return -1;
00709 break;
00710 case XODE_TYPE_CDATA:
00711 ret = _xode_strcmp(xode_get_data(a), xode_get_data(b));
00712 if(ret != 0)
00713 return -1;
00714 }
00715 a = xode_get_nextsibling(a);
00716 b = xode_get_nextsibling(b);
00717 }
00718 }
00719
00720
00721 xode xode_insert_tagnode(xode parent, xode node)
00722 {
00723 xode child;
00724
00725 child = xode_insert_tag(parent, xode_get_name(node));
00726 if (xode_has_attribs(node))
00727 xode_insert_node(child, xode_get_firstattrib(node));
00728 if (xode_has_children(node))
00729 xode_insert_node(child, xode_get_firstchild(node));
00730
00731 return child;
00732 }
00733
00734
00735 void xode_insert_node(xode parent, xode node)
00736 {
00737 if(node == NULL || parent == NULL)
00738 return;
00739
00740 while(node != NULL)
00741 {
00742 switch(xode_get_type(node))
00743 {
00744 case XODE_TYPE_ATTRIB:
00745 xode_put_attrib(parent, xode_get_name(node), xode_get_data(node));
00746 break;
00747 case XODE_TYPE_TAG:
00748 xode_insert_tagnode(parent, node);
00749 break;
00750 case XODE_TYPE_CDATA:
00751 xode_insert_cdata(parent, xode_get_data(node), xode_get_datasz(node));
00752 }
00753 node = xode_get_nextsibling(node);
00754 }
00755 }
00756
00757
00758
00759 xode xode_dup(xode x)
00760 {
00761 xode x2;
00762
00763 if(x == NULL)
00764 return NULL;
00765
00766 x2 = xode_new(xode_get_name(x));
00767
00768 if (xode_has_attribs(x))
00769 xode_insert_node(x2, xode_get_firstattrib(x));
00770 if (xode_has_children(x))
00771 xode_insert_node(x2, xode_get_firstchild(x));
00772
00773 return x2;
00774 }
00775
00776 xode xode_dup_frompool(xode_pool p, xode x)
00777 {
00778 xode x2;
00779
00780 if(x == NULL)
00781 return NULL;
00782
00783 x2 = xode_new_frompool(p, xode_get_name(x));
00784
00785 if (xode_has_attribs(x))
00786 xode_insert_node(x2, xode_get_firstattrib(x));
00787 if (xode_has_children(x))
00788 xode_insert_node(x2, xode_get_firstchild(x));
00789
00790 return x2;
00791 }
00792
00793 xode xode_wrap(xode x,const char *wrapper)
00794 {
00795 xode wrap;
00796 if(x==NULL||wrapper==NULL) return NULL;
00797 wrap=xode_new_frompool(xode_get_pool(x),wrapper);
00798 if(wrap==NULL) return NULL;
00799 wrap->firstchild=x;
00800 wrap->lastchild=x;
00801 x->parent=wrap;
00802 return wrap;
00803 }
00804
00805 void xode_free(xode node)
00806 {
00807 if(node == NULL)
00808 return;
00809
00810 xode_pool_free(node->p);
00811 }
00812
00813
00814 void
00815 _xode_to_prettystr( xode_spool s, xode x, int deep )
00816 {
00817 int i;
00818 xode y;
00819
00820 if(xode_get_type(x) != XODE_TYPE_TAG) return;
00821
00822 for(i=0; i<deep; i++) xode_spool_add(s, "\t");
00823
00824 xode_spooler( s , "<" , xode_get_name(x) , s );
00825
00826 y = xode_get_firstattrib(x);
00827 while( y )
00828 {
00829 xode_spooler( s , " " , xode_get_name(y) , "='", xode_get_data(y) , "'" , s );
00830
00831 y = xode_get_nextsibling( y );
00832 }
00833 xode_spool_add(s,">");
00834 xode_spool_add(s,"\n");
00835
00836 if( xode_get_data(x))
00837 {
00838 for(i=0; i<=deep; i++) xode_spool_add(s, "\t");
00839 xode_spool_add( s , xode_get_data(x));
00840 }
00841
00842 y = xode_get_firstchild(x);
00843 while( y )
00844 {
00845 _xode_to_prettystr(s , y, deep+1);
00846 y = xode_get_nextsibling(y);
00847 xode_spool_add(s,"\n");
00848 }
00849
00850 for(i=0; i<deep; i++) xode_spool_add(s, "\t");
00851 xode_spooler( s , "</" , xode_get_name(x) , ">" , s );
00852
00853 return;
00854 }
00855
00856 char *
00857 xode_to_prettystr( xode x )
00858 {
00859 xode_spool s;
00860
00861 if( !x) return NULL;
00862
00863 s = xode_spool_newfrompool( xode_get_pool(x));
00864
00865 _xode_to_prettystr( s , x, 0 );
00866
00867 return xode_spool_tostr(s);
00868 }
00869