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