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