• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

src/roxml.c

Go to the documentation of this file.
00001 
00025 #include "roxml-internal.h"
00026 
00027 void ROXML_API roxml_release(void * data)
00028 {
00029         memory_cell_t *ptr = &head_cell;
00030         memory_cell_t *to_delete = NULL;
00031 
00032         if(data == RELEASE_LAST)        {
00033                 while((ptr->prev != NULL)&&(ptr->prev->id != pthread_self())) { ptr = ptr->prev; } 
00034                 if(ptr->prev == NULL)   { return; }
00035 
00036                 to_delete = ptr->prev;
00037 
00038                 if(to_delete->next) { 
00039                         to_delete->prev->next = to_delete->next;
00040                         to_delete->next->prev = to_delete->prev;
00041                 } else {
00042                         if(to_delete->prev != &head_cell)       {
00043                                 head_cell.prev = to_delete->prev;
00044                         } else {
00045                                 head_cell.prev = NULL;
00046                         }
00047                         to_delete->prev->next = NULL;
00048                 }
00049 
00050                 if(PTR_IS_STAR(to_delete))      {
00051                         int i = 0;
00052                         for(i = 0; i < to_delete->occ; i++) { free(((void**)(to_delete->ptr))[i]); }
00053                 }
00054                 if(to_delete->type != PTR_NONE) {
00055                         free(to_delete->ptr);
00056                         to_delete->type = PTR_NONE;
00057                         free(to_delete);
00058                 }
00059         } else if(data == RELEASE_ALL) {
00060                 head_cell.prev = NULL;
00061                 while((head_cell.next != NULL)) { 
00062                         to_delete = head_cell.next;
00063                         if(to_delete->next) { to_delete->next->prev = &head_cell; }
00064                         head_cell.next = to_delete->next;
00065 
00066                         if(PTR_IS_STAR(to_delete))      {
00067                                 int i = 0;
00068                                 for(i = 0; i < to_delete->occ; i++) { free(((void**)(to_delete->ptr))[i]); }
00069                         }
00070                         free(to_delete->ptr);
00071                         to_delete->ptr = NULL;
00072                         to_delete->type = PTR_NONE;
00073                         free(to_delete);
00074                 }
00075         } else  {
00076                 while((ptr->next != NULL)&&(ptr->next->ptr != data)) { ptr = ptr->next; }
00077                 if(ptr->next == NULL)   { 
00078                         return;
00079                 }
00080 
00081                 to_delete = ptr->next;
00082                 if(to_delete->next) {
00083                         to_delete->next->prev = ptr; 
00084                 } else {
00085                         if(ptr == &head_cell)   {
00086                                 head_cell.prev = NULL;
00087                         } else {
00088                                 head_cell.prev = to_delete->prev;
00089                         }
00090                 }
00091                 ptr->next = to_delete->next;
00092                 if(PTR_IS_STAR(to_delete))      {
00093                         int i = 0;
00094                         for(i = 0; i < to_delete->occ; i++) { free(((void**)(to_delete->ptr))[i]); }
00095                 }
00096                 free(to_delete->ptr);
00097                 to_delete->type = PTR_NONE;
00098                 free(to_delete);
00099         }
00100         if(head_cell.next == &head_cell) { head_cell.next = NULL; }
00101         if(head_cell.prev == &head_cell) { head_cell.prev = NULL; }
00102 }
00103 
00104 char * ROXML_API roxml_get_content(node_t *n, char * buffer, int bufsize, int *size)
00105 {
00106         node_t * ptr;
00107         int total = 0;
00108         char * content = NULL;
00109         
00110         if(n == NULL)   {
00111                 if(buffer)      {
00112                         strcpy(buffer, "");
00113                 }
00114                 return NULL;
00115         }
00116 
00117         if(n->type & ROXML_STD_NODE)    {
00118                 ptr = n->text;
00119                 while(ptr)      {
00120                         total += ptr->end - ptr->pos;
00121                         ptr = ptr->sibl;
00122                 }
00123                 
00124                 content = roxml_malloc(sizeof(char), total+1, PTR_CHAR);
00125                 if(content == NULL) { return NULL; }
00126 
00127                 total = 0;
00128                 ptr = n->text;
00129                 while(ptr)      {
00130                         if(ptr->type & ROXML_FILE) {
00131                                 int ret_len = 0;
00132                                 fseek(ptr->src.fil, ptr->pos, SEEK_SET);
00133                                 ret_len = fread(content+total, ptr->end - ptr->pos, 1, ptr->src.fil);
00134                         } else {
00135                                 memcpy(content+total, ptr->src.buf+ptr->pos, ptr->end - ptr->pos);
00136                         }
00137                         total += ptr->end - ptr->pos;
00138                         ptr = ptr->sibl;
00139                 }
00140         } else if(n->type & ROXML_TXT_NODE)     {
00141                 total = n->end - n->pos;
00142                 content = roxml_malloc(sizeof(char), total+1, PTR_CHAR);
00143                 if(content == NULL) { return NULL; }
00144                 if(n->type & ROXML_FILE) {
00145                         int ret_len = 0;
00146                         fseek(n->src.fil, n->pos, SEEK_SET);
00147                         ret_len = fread(content, n->end - n->pos, 1, n->src.fil);
00148                 } else {
00149                         memcpy(content, n->src.buf+n->pos, n->end - n->pos);
00150                 }
00151         } else if(n->type & ROXML_CMT_NODE)     {
00152                 total = n->end - n->pos - 4;
00153                 content = roxml_malloc(sizeof(char), total+1, PTR_CHAR);
00154                 if(content == NULL) { return NULL; }
00155                 if(n->type & ROXML_FILE) {
00156                         int ret_len = 0;
00157                         fseek(n->src.fil, n->pos+4, SEEK_SET);
00158                         ret_len = fread(content, n->end - n->pos - 4, 1, n->src.fil);
00159                 } else {
00160                         memcpy(content, n->src.buf+n->pos + 4, n->end - n->pos - 4);
00161                 }
00162         } else if(n->type & ROXML_PI_NODE)      {
00163                 total = n->end - n->pos - 2;
00164                 content = roxml_malloc(sizeof(char), total+2, PTR_CHAR);
00165                 if(content == NULL) { return NULL; }
00166                 if(n->type & ROXML_FILE) {
00167                         int ret_len = 0;
00168                         fseek(n->src.fil, n->pos+2, SEEK_SET);
00169                         ret_len = fread(content, n->end - n->pos - 2, 1, n->src.fil);
00170                 } else {
00171                         memcpy(content, n->src.buf+n->pos + 2, n->end - n->pos - 2);
00172                 }
00173         } else if(n->type & ROXML_ATTR_NODE)    {
00174                 node_t *ptr = n->text;
00175                 total = ptr->end - ptr->pos;
00176                 content = roxml_malloc(sizeof(char), total+1, PTR_CHAR);
00177                 if(content == NULL) { return NULL; }
00178                 if(ptr->type & ROXML_FILE) {
00179                         int ret_len = 0;
00180                         fseek(ptr->src.fil, ptr->pos, SEEK_SET);
00181                         ret_len = fread(content, total, 1, ptr->src.fil);
00182                 } else {
00183                         memcpy(content, ptr->src.buf+ptr->pos, total);
00184                 }
00185         }
00186         if(buffer)      {
00187                 strncpy(buffer, content, bufsize);
00188         }
00189         if(size) {
00190                 *size = total;
00191         }
00192         return content;
00193 }
00194 
00195 char * ROXML_API roxml_get_name(node_t *n, char * buffer, int size)
00196 {
00197         int count = 0;
00198         char tmp_name[INTERNAL_BUF_SIZE];
00199         memset(tmp_name, 0, INTERNAL_BUF_SIZE*sizeof(char));
00200 
00201         if(n == NULL)   {
00202                 if(buffer)      {
00203                         strcpy(buffer, "");
00204                         return buffer;
00205                 }
00206                 return NULL;
00207         }
00208 
00209         if(n->prnt == NULL)     {
00210                 strcpy(tmp_name, "documentRoot");
00211         } else if(n->type & ROXML_ATTR_NODE)    {
00212                 int offset = 0;
00213                 char *internal_ptr;
00214                 char internal_buf[INTERNAL_BUF_SIZE];
00215                 if(n->type & ROXML_FILE) {
00216                         int ret_len = 0;
00217                         fseek(n->src.fil, n->pos, SEEK_SET);
00218                         ret_len = fread(internal_buf, INTERNAL_BUF_SIZE, 1, n->src.fil);
00219                         internal_ptr = internal_buf;
00220                 } else {
00221                         internal_ptr = n->src.buf + n->pos;
00222                 }
00223                 while(ROXML_WHITE(internal_ptr[offset])) { offset++; }
00224                 while(count<INTERNAL_BUF_SIZE) { 
00225                         if(internal_ptr[offset] == '=') { break; }
00226                         if(internal_ptr[offset] == '/') { break; }
00227                         if(internal_ptr[offset] == '>') { break; }
00228                         tmp_name[count] = internal_ptr[offset];
00229                         offset++;
00230                         count++;
00231                 }
00232         } else if(n->type & ROXML_STD_NODE)     {
00233                 int offset = 0;
00234                 char *internal_ptr;
00235                 char internal_buf[INTERNAL_BUF_SIZE];
00236                 if(n->type & ROXML_FILE) {
00237                         int ret_len = 0;
00238                         fseek(n->src.fil, n->pos, SEEK_SET);
00239                         ret_len = fread(internal_buf, INTERNAL_BUF_SIZE, 1, n->src.fil);
00240                         internal_ptr = internal_buf;
00241                 } else {
00242                         internal_ptr = n->src.buf + n->pos;
00243                 }
00244                 while((internal_ptr[offset] == '<')||(ROXML_WHITE(internal_ptr[offset]))) { offset++; }
00245                 while(count<INTERNAL_BUF_SIZE) { 
00246                         if(internal_ptr[offset] == '/') { break; }
00247                         if(internal_ptr[offset] == '>') { break; }
00248                         if(ROXML_WHITE(internal_ptr[offset])) { break; }
00249                         tmp_name[count] = internal_ptr[offset];
00250                         offset++;
00251                         count++;
00252                 }
00253         } else if(n->type & ROXML_TXT_NODE) {
00254                 if(buffer) { strcpy(buffer, ""); return buffer; }
00255                 return NULL;
00256         } else if(n->type & ROXML_CMT_NODE) {
00257                 if(buffer) { strcpy(buffer, ""); return buffer; }
00258                 return NULL;
00259         } else if(n->type & ROXML_PI_NODE) {
00260                 if(buffer) { strcpy(buffer, ""); return buffer; }
00261                 return NULL;
00262         }
00263 
00264         if(buffer == NULL)      {
00265                 buffer = (char*)roxml_malloc(sizeof(char), strlen(tmp_name)+1, PTR_CHAR);
00266                 strcpy(buffer, tmp_name);
00267         } else  {
00268                 strncpy(buffer, tmp_name, size);
00269         }
00270         return buffer;
00271 }
00272 
00273 int ROXML_API roxml_get_text_nb(node_t *n)
00274 {
00275         node_t *ptr = n;
00276         int nb = 0;
00277         if(ptr->text)   {
00278                 ptr = ptr->text;
00279                 nb++;
00280                 while(ptr->sibl)        {
00281                         nb++;
00282                         ptr = ptr->sibl;
00283                 }
00284         }
00285         return nb;
00286 }
00287 
00288 node_t * ROXML_API roxml_get_text(node_t *n, int nth)
00289 {
00290         int count = 0;
00291         node_t *ptr = n;
00292         ptr = n->text;
00293         
00294         if(ptr == NULL) {
00295                 return NULL;
00296         }
00297 
00298         if(nth == 0)    {
00299                 return ptr;
00300         }
00301         while((ptr->sibl)&&(nth > count)) {
00302                 count++;
00303                 ptr = ptr->sibl;
00304         }
00305         if(nth > count) { return NULL; }
00306         return ptr;
00307 }
00308 
00309 int ROXML_API roxml_get_attr_nb(node_t *n)
00310 {
00311         node_t *ptr = n;
00312         int nb = 0;
00313         if(ptr->attr)   {
00314                 ptr = ptr->attr;
00315                 nb++;
00316                 while(ptr->sibl)        {
00317                         nb++;
00318                         ptr = ptr->sibl;
00319                 }
00320         }
00321         return nb;
00322 }
00323 
00324 node_t * ROXML_API roxml_get_attr(node_t *n, char * name, int nth)
00325 {
00326         node_t *ptr = n;
00327         ptr = n->attr;
00328         
00329         if(ptr == NULL) {
00330                 return NULL;
00331         }
00332 
00333         if(name == NULL)        {
00334                 int count = 0;
00335                 if(nth == 0)    {
00336                         return ptr;
00337                 }
00338                 while((ptr->sibl)&&(nth > count)) {
00339                         count++;
00340                         ptr = ptr->sibl;
00341                 }
00342                 if(nth > count) { return NULL; }
00343         } else  {
00344                 while(ptr) {
00345                         int ans = strcmp(roxml_get_name(ptr, NULL, 0), name);
00346                         roxml_release(RELEASE_LAST);
00347                         if(ans == 0)    {
00348                                 return ptr;
00349                         }
00350                         ptr = ptr->sibl;
00351                 }
00352         }
00353         return ptr;
00354 }
00355 
00356 void ROXML_API roxml_close(node_t *n)
00357 {
00358         node_t *root = n;
00359         if(root == NULL)        {
00360                 return;
00361         }
00362         while(root->prnt != NULL)       {
00363                 root = root->prnt;
00364         }
00365 
00366         roxml_del_tree(root->chld);
00367         roxml_del_tree(root->text);
00368         roxml_del_tree(root->sibl);
00369         roxml_del_tree(root->attr);
00370         if((root->type & ROXML_FILE) == ROXML_FILE)     {
00371                 fclose(root->src.fil);
00372         }
00373         roxml_free_node(root);
00374 }
00375 
00376 int ROXML_API roxml_get_chld_nb(node_t *n)
00377 {
00378         node_t *ptr = n;
00379         int nb = 0;
00380         if(ptr == NULL) { return -1; }
00381         if(ptr->chld)   {
00382                 ptr = ptr->chld;
00383                 nb++;
00384                 while(ptr->sibl)        {
00385                         nb++;
00386                         ptr = ptr->sibl;
00387                 }
00388         }
00389         return nb;
00390 }
00391 
00392 node_t * ROXML_API roxml_get_chld(node_t *n, char * name, int nth)
00393 {
00394         node_t *ptr = n;
00395         ptr = n->chld;
00396         if(name == NULL)        {
00397                 int count = 0;
00398                 if(nth == 0)    {
00399                         return ptr;
00400                 }
00401                 while((ptr->sibl)&&(nth > count)) {
00402                         count++;
00403                         ptr = ptr->sibl;
00404                 }
00405                 if(nth > count) { return NULL; }
00406         } else  {
00407                 while(ptr) {
00408                         int ans = strcmp(roxml_get_name(ptr, NULL, 0), name);
00409                         roxml_release(RELEASE_LAST);
00410                         if(ans == 0)    {
00411                                 return ptr;
00412                         }
00413                         ptr = ptr->sibl;
00414                 }
00415         }
00416         return ptr;
00417 }
00418 
00419 node_t * ROXML_API roxml_get_parent(node_t *n)
00420 {
00421         if(n->prnt == NULL)     {
00422                 return n;
00423         } else  {
00424                 return n->prnt;
00425         }
00426         return NULL;
00427 }
00428 
00429 int ROXML_API roxml_get_type(node_t *n)
00430 {
00431         return (n->type & (ROXML_ATTR_NODE | ROXML_STD_NODE | ROXML_TXT_NODE | ROXML_PI_NODE | ROXML_CMT_NODE));
00432 }
00433 
00434 int ROXML_API roxml_get_node_position(node_t *n)
00435 {
00436         int idx = 1;
00437         char name[256];
00438         node_t * prnt;
00439         node_t * first;
00440 
00441         if(n == NULL) { return 0; }
00442         
00443         roxml_get_name(n, name, 256);
00444 
00445         prnt = n->prnt;
00446         if(!prnt) {
00447                 return 1;
00448         }
00449         first = prnt->chld;
00450 
00451         while((first)&&(first != n)) {
00452                 char twin[256];
00453                 roxml_get_name(first, twin, 256);
00454                 if(strcmp(name, twin) == 0) { idx++; }
00455                 first = first->sibl;
00456         }
00457 
00458         return idx;
00459 }
00460 
00461 node_t * ROXML_API roxml_load_doc(char *filename)
00462 {
00463         node_t *current_node = NULL;
00464         FILE* file = fopen(filename, "r");
00465         if(file == NULL)        {
00466                 return NULL;
00467         }
00468         current_node = roxml_create_node(0, file, ROXML_STD_NODE | ROXML_FILE);
00469         current_node = roxml_parent_node(NULL, current_node);
00470         return roxml_load(current_node,  file, NULL);
00471 }
00472 
00473 node_t * ROXML_API roxml_load_buf(char *buffer)
00474 {
00475         node_t *current_node = NULL;
00476         if(buffer == NULL)      { return NULL; }
00477         current_node = roxml_create_node(0, buffer, ROXML_STD_NODE | ROXML_BUFF);
00478         current_node = roxml_parent_node(NULL, current_node);
00479         return roxml_load(current_node, NULL, buffer);
00480 }
00481 
00482 node_t ** ROXML_API roxml_xpath(node_t *n, char * path, int *nb_ans)
00483 {
00484         int index = 0;
00485         int count = 0;
00486         xpath_node_t * xpath = NULL;
00487         node_t ** node_set = NULL;
00488         node_t * root = n;
00489         char * full_path_to_find;
00490         char * path_to_find;
00491 
00492         if(n == NULL)   { 
00493                 if(nb_ans) { *nb_ans = 0; }
00494                 return NULL; 
00495         }
00496 
00497         while(root->prnt) { root = root->prnt; }
00498 
00499         full_path_to_find = strdup(path);
00500         path_to_find = full_path_to_find;
00501 
00502         index = roxml_parse_xpath(path_to_find, &xpath, 0);
00503 
00504         node_set = roxml_exec_xpath(root, n, xpath, index, &count);
00505 
00506         roxml_free_xpath(xpath, index);
00507         free(full_path_to_find);
00508 
00509         if(nb_ans)      {
00510                 *nb_ans = count;
00511         }
00512 
00513         if(count == 0)  {
00514                 roxml_release(node_set);
00515                 return NULL;
00516         }
00517 
00518         return node_set;
00519 }
00520 
00521 void ROXML_API roxml_del_node(node_t * n) 
00522 {
00523         if(n == NULL) return;
00524         if(n->type & ROXML_STD_NODE) {
00525                 roxml_del_std_node(n);
00526         } else if(n->type & ROXML_ATTR_NODE) {
00527                 roxml_del_arg_node(n);
00528         } else if(n->type & ROXML_PI_NODE) {
00529                 roxml_del_std_node(n);
00530         } else if(n->type & ROXML_CMT_NODE) {
00531                 roxml_del_std_node(n);
00532         } else if(n->type & ROXML_TXT_NODE) {
00533                 roxml_del_txt_node(n);
00534         }
00535         roxml_free_node(n);
00536 }
00537 
00538 void ROXML_API roxml_commit_changes(node_t *n, char * dest, char ** buffer, int human)
00539 {
00540         int size = 0;
00541         int len = ROXML_LONG_LEN;
00542         FILE *fout = NULL;
00543         char * buf = NULL;
00544 
00545         if(dest) { 
00546                 fout = fopen(dest, "w");
00547         }
00548         if(buffer) {
00549                 buf = (char*)malloc(ROXML_LONG_LEN);
00550                 *buffer = buf;
00551         }
00552         roxml_write_node(n, fout, buf, human, -1, &size, &len);
00553         if(fout) {
00554                 fclose(fout);
00555         }
00556 }
00557 
00558 node_t * roxml_add_node(node_t * parent, int position, int type, char *name, char *value) 
00559 {
00560         int name_l = 0;
00561         int end_node = 0;
00562         int content_l = 0;
00563         int content_pos = 0;
00564         int end_content = 0;
00565         char * buffer = NULL;
00566         node_t * new_node;
00567 
00568         if(parent && !(parent->type & ROXML_STD_NODE)) {
00569                 return NULL;
00570         }
00571         if(value) {
00572                 content_l = strlen(value);
00573         }
00574         if(name) {
00575                 name_l = strlen(name);
00576         }
00577 
00578         if(type & ROXML_ATTR_NODE) {
00579                 if(!name || !value) { return NULL; }
00580                 buffer = (char*)malloc(sizeof(char)*(name_l+content_l+2));
00581                 sprintf(buffer,"%s=%s",name, value);
00582                 content_pos = name_l+1;
00583                 end_node = name_l + 1;
00584                 end_content = name_l + content_l + 2;
00585         } else if(type & ROXML_CMT_NODE) {
00586                 if(!value) { return NULL; }
00587                 buffer = (char*)malloc(sizeof(char)*(content_l+8));
00588                 sprintf(buffer,"<!--%s-->", value);
00589                 content_pos = 0;
00590                 end_node = content_l + 4;
00591                 end_content = content_l + 4;
00592         } else if(type & ROXML_PI_NODE) {
00593                 if(!value) { return NULL; }
00594                 buffer = (char*)malloc(sizeof(char)*(content_l+7));
00595                 sprintf(buffer,"<? %s ?>", value);
00596                 content_pos = 0;
00597                 end_node = content_l + 4;
00598                 end_content = content_l + 4;
00599         } else if(type & ROXML_TXT_NODE) {
00600                 if(!value) { return NULL; }
00601                 buffer = (char*)malloc(sizeof(char)*(content_l+1));
00602                 sprintf(buffer,"%s", value);
00603                 content_pos = 0;
00604                 end_node = content_l + 1;
00605                 end_content = content_l + 1;
00606         } else if(type & ROXML_STD_NODE) {
00607                 if(!name) { return NULL; }
00608                 if(content_l)   {
00609                         if(!value) { return NULL; }
00610                         buffer = (char*)malloc(sizeof(char)*(name_l*2+content_l+6));
00611                         sprintf(buffer,"<%s>%s</%s>",name, value, name);
00612                         content_pos = name_l+2;
00613                         end_node = name_l + content_l + 2;
00614                         end_content = end_node;
00615                 } else {
00616                         buffer = (char*)malloc(sizeof(char)*(name_l+5));
00617                         sprintf(buffer,"<%s />",name);
00618                 }
00619         }
00620 
00621         new_node = roxml_create_node(0, buffer, type | ROXML_PENDING | ROXML_BUFF);
00622         new_node->end = end_node;
00623 
00624         if(content_l && name_l) {
00625                 node_t *new_txt = roxml_create_node(content_pos, buffer, ROXML_TXT_NODE | ROXML_PENDING | ROXML_BUFF);
00626                 roxml_parent_node(new_node, new_txt);
00627                 new_txt->end = end_content;
00628         }
00629 
00630         if(parent == NULL) {
00631                 parent = roxml_create_node(0, NULL, ROXML_STD_NODE | ROXML_PENDING | ROXML_BUFF);
00632                 parent->end = 1;
00633                 roxml_parent_node(parent, new_node);
00634         } else {
00635                 roxml_parent_node_at(parent, new_node, position);
00636         }
00637         return new_node;
00638 }
00639 

Generated on Thu Feb 10 2011 16:58:19 for libroxml by  doxygen 1.7.1