00001
00025 #include "roxml-internal.h"
00026 #include "roxml-parse-engine.h"
00027
00028 #ifdef __DEBUG
00029 unsigned int _nb_node = 0;
00030 unsigned int _nb_attr = 0;
00031 unsigned int _nb_text = 0;
00032 #endif
00033
00035 memory_cell_t head_cell = {PTR_NONE, 0, NULL, 0, NULL, NULL};
00036
00037 void * ROXML_INT roxml_malloc(int size, int num, int type)
00038 {
00039 memory_cell_t *cell = &head_cell;
00040 while(cell->next != NULL) { cell = cell->next; }
00041 cell->next = (memory_cell_t*)malloc(sizeof(memory_cell_t));
00042 if(!cell->next) { return NULL; }
00043 cell->next->next = NULL;
00044 cell->next->prev = cell;
00045 cell = cell->next;
00046 cell->type = type;
00047 cell->id = pthread_self();
00048 cell->occ = size;
00049 cell->ptr = calloc(num, size);
00050 head_cell.prev = cell;
00051 return cell->ptr;
00052 }
00053
00054 node_t * ROXML_INT roxml_create_node(int pos, void *src, int type)
00055 {
00056 node_t *n = (node_t*)calloc(1, sizeof(node_t));
00057 n->type = type;
00058 n->src.src = src;
00059 n->pos = pos;
00060 n->end = pos;
00061
00062 return n;
00063 }
00064
00065 void ROXML_INT roxml_close_node(node_t *n, node_t *close)
00066 {
00067 n->end = close->pos;
00068 free(close);
00069
00070 if((n->type & ROXML_STD_NODE) == ROXML_STD_NODE) {
00071 n->next = NULL;
00072 }
00073
00074 #ifdef __DEBUG
00075 if(n->type & ROXML_STD_NODE) _nb_node++;
00076 if(n->type & ROXML_ATTR_NODE) _nb_attr++;
00077 if(n->type & ROXML_TXT_NODE) _nb_text++;
00078 #endif
00079 }
00080
00081 void ROXML_INT roxml_free_node(node_t *n)
00082 {
00083 if(n->type & ROXML_PENDING) {
00084 if(n->pos == 0) {
00085 free(n->src.buf);
00086 }
00087 }
00088 if(n->priv) {
00089 xpath_tok_t * tok = (xpath_tok_t*)n->priv;
00090 if(tok->id == ROXML_REQTABLE_ID) {
00091 xpath_tok_table_t * table = (xpath_tok_table_t*)n->priv;
00092 tok = table->next;
00093 free(table);
00094 }
00095 while(tok) {
00096 xpath_tok_t * to_delete = tok;
00097 tok = tok->next;
00098 free(to_delete);
00099 }
00100 }
00101 free(n);
00102 }
00103
00104 void ROXML_INT roxml_del_tree(node_t *n)
00105 {
00106 if(n == NULL) { return; }
00107 roxml_del_tree(n->chld);
00108 roxml_del_tree(n->text);
00109 roxml_del_tree(n->sibl);
00110 roxml_del_tree(n->attr);
00111 roxml_free_node(n);
00112 }
00113
00114 void ROXML_INT roxml_process_begin_node(roxml_load_ctx_t *context, int position)
00115 {
00116 if(context->candidat_txt) {
00117 #ifdef IGNORE_EMPTY_TEXT_NODES
00118 if(context->empty_text_node == 0) {
00119 #endif
00120 node_t * to_be_closed = roxml_create_node(position, context->src, ROXML_TXT_NODE | context->type);
00121 roxml_close_node(context->candidat_txt, to_be_closed);
00122 #ifdef IGNORE_EMPTY_TEXT_NODES
00123 } else {
00124 roxml_del_node(context->candidat_txt);
00125 }
00126 #endif
00127 context->candidat_txt = NULL;
00128 }
00129 context->candidat_node = roxml_create_node(position, context->src, ROXML_STD_NODE | context->type);
00130 }
00131
00132 node_t * ROXML_INT roxml_load(node_t *current_node, FILE *file, char *buffer)
00133 {
00134 char int_buffer[ROXML_BULK_READ+1];
00135 int int_len = 0;
00136 roxml_load_ctx_t context;
00137 roxml_parser_item_t * parser = NULL;
00138
00139 memset(&context, 0, sizeof(roxml_load_ctx_t));
00140 context.empty_text_node = 1;
00141 context.current_node = current_node;
00142
00143 parser = roxml_append_parser_item(parser, " ", _func_load_white);
00144 parser = roxml_append_parser_item(parser, "<", _func_load_open_node);
00145 parser = roxml_append_parser_item(parser, ">", _func_load_close_node);
00146 parser = roxml_append_parser_item(parser, "/", _func_load_end_node);
00147 parser = roxml_append_parser_item(parser, "'", _func_load_quoted);
00148 parser = roxml_append_parser_item(parser, "\"", _func_load_dquoted);
00149 parser = roxml_append_parser_item(parser, "\t", _func_load_white);
00150 parser = roxml_append_parser_item(parser, "\n", _func_load_white);
00151 parser = roxml_append_parser_item(parser, "\r", _func_load_white);
00152 parser = roxml_append_parser_item(parser, "!", _func_load_open_spec_node);
00153 parser = roxml_append_parser_item(parser, "]", _func_load_close_cdata);
00154 parser = roxml_append_parser_item(parser, "-", _func_load_close_comment);
00155 parser = roxml_append_parser_item(parser, "?", _func_load_close_pi);
00156 parser = roxml_append_parser_item(parser, NULL, _func_load_default);
00157
00158 parser = roxml_parser_prepare(parser);
00159
00160 if(file) {
00161 context.type = ROXML_FILE;
00162 context.src = (void*)file;
00163 context.pos = 0;
00164 do {
00165 int ret = 0;
00166 int_len = fread(int_buffer, 1, ROXML_BULK_READ, file);
00167 int_buffer[int_len] = '\0';
00168
00169 ret = roxml_parse_line(parser, int_buffer, int_len, &context);
00170 } while(int_len == ROXML_BULK_READ);
00171 } else {
00172 context.type = ROXML_BUFF;
00173 context.src = (void*)buffer;
00174 roxml_parse_line(parser, buffer, 0, &context);
00175 }
00176
00177 roxml_parser_free(parser);
00178
00179 #ifdef IGNORE_EMPTY_TEXT_NODES
00180 if(context.empty_text_node == 1) {
00181 roxml_del_node(context.candidat_txt);
00182 }
00183 #endif
00184
00185 while(current_node->prnt) { current_node = current_node->prnt; }
00186 return current_node;
00187 }
00188
00189 void ROXML_INT roxml_set_type(node_t * n, int type)
00190 {
00191 n->type &= ~(ROXML_ATTR_NODE|ROXML_STD_NODE|ROXML_TXT_NODE|ROXML_CMT_NODE|ROXML_PI_NODE);
00192 n->type |= type;
00193 }
00194
00195 xpath_node_t * ROXML_INT roxml_set_axes(xpath_node_t *node, char *axes, int *offset)
00196 {
00197 xpath_node_t *tmp_node;
00198 if(axes[0] == '/') {
00199 axes[0] = '\0';
00200 *offset += 1;
00201 axes++;
00202 }
00203 if(axes[0] == '/') {
00204
00205 node->axes = ROXML_ID_DESC_O_SELF;
00206 node->name = axes+1;
00207 tmp_node = (xpath_node_t*)calloc(1, sizeof(xpath_node_t));
00208 tmp_node->axes = ROXML_ID_CHILD;
00209 node->next = tmp_node;
00210 if(strlen(node->name) > 0) {
00211 tmp_node = (xpath_node_t*)calloc(1, sizeof(xpath_node_t));
00212 node->next->next = tmp_node;
00213 node = roxml_set_axes(tmp_node, axes+1, offset);
00214 }
00215 } else if(strncmp(ROXML_L_DESC_O_SELF, axes, strlen(ROXML_L_DESC_O_SELF))==0) {
00216
00217 node->axes = ROXML_ID_DESC_O_SELF;
00218 node->name = axes+strlen(ROXML_L_DESC_O_SELF);
00219 *offset += strlen(ROXML_L_DESC_O_SELF);
00220 tmp_node = (xpath_node_t*)calloc(1, sizeof(xpath_node_t));
00221 tmp_node->axes = ROXML_ID_CHILD;
00222 node->next = tmp_node;
00223 node = roxml_set_axes(tmp_node, axes+strlen(ROXML_L_DESC_O_SELF), offset);
00224 } else if(strncmp(ROXML_L_DESC, axes, strlen(ROXML_L_DESC))==0) {
00225
00226 node->axes = ROXML_ID_DESC;
00227 node->name = axes+strlen(ROXML_L_DESC);
00228 *offset += strlen(ROXML_L_DESC);
00229 tmp_node = (xpath_node_t*)calloc(1, sizeof(xpath_node_t));
00230 tmp_node->axes = ROXML_ID_CHILD;
00231 node->next = tmp_node;
00232 node = roxml_set_axes(tmp_node, axes+strlen(ROXML_L_DESC), offset);
00233 } else if(strncmp(ROXML_L_PARENT, axes, strlen(ROXML_L_PARENT))==0) {
00234
00235 node->axes = ROXML_ID_PARENT;
00236 node->name = axes+strlen(ROXML_L_PARENT);
00237 } else if(strncmp(ROXML_S_PARENT, axes, strlen(ROXML_S_PARENT))==0) {
00238
00239 node->axes = ROXML_ID_PARENT;
00240 node->name = axes+strlen(ROXML_S_PARENT);
00241 } else if(strncmp(ROXML_L_SELF, axes, strlen(ROXML_L_SELF))==0) {
00242
00243 node->axes = ROXML_ID_SELF;
00244 node->name = axes+strlen(ROXML_L_SELF);
00245 } else if(strncmp(ROXML_S_SELF, axes, strlen(ROXML_S_SELF))==0) {
00246
00247 node->axes = ROXML_ID_SELF;
00248 node->name = axes+strlen(ROXML_S_SELF);
00249 } else if(strncmp(ROXML_L_ATTR, axes, strlen(ROXML_L_ATTR))==0) {
00250
00251 node->axes = ROXML_ID_ATTR;
00252 node->name = axes+strlen(ROXML_L_ATTR);
00253 } else if(strncmp(ROXML_S_ATTR, axes, strlen(ROXML_S_ATTR))==0) {
00254
00255 node->axes = ROXML_ID_ATTR;
00256 node->name = axes+strlen(ROXML_S_ATTR);
00257 } else if(strncmp(ROXML_L_ANC, axes, strlen(ROXML_L_ANC))==0) {
00258
00259 node->axes = ROXML_ID_ANC;
00260 node->name = axes+strlen(ROXML_L_ANC);
00261 } else if(strncmp(ROXML_L_ANC_O_SELF, axes, strlen(ROXML_L_ANC_O_SELF))==0) {
00262
00263 node->axes = ROXML_ID_ANC_O_SELF;
00264 node->name = axes+strlen(ROXML_L_ANC_O_SELF);
00265 } else if(strncmp(ROXML_L_NEXT_SIBL, axes, strlen(ROXML_L_NEXT_SIBL))==0) {
00266
00267 node->axes = ROXML_ID_NEXT_SIBL;
00268 node->name = axes+strlen(ROXML_L_NEXT_SIBL);
00269 } else if(strncmp(ROXML_L_PREV_SIBL, axes, strlen(ROXML_L_PREV_SIBL))==0) {
00270
00271 node->axes = ROXML_ID_PREV_SIBL;
00272 node->name = axes+strlen(ROXML_L_PREV_SIBL);
00273 } else if(strncmp(ROXML_L_NEXT, axes, strlen(ROXML_L_NEXT))==0) {
00274
00275 node->axes = ROXML_ID_NEXT;
00276 node->name = axes+strlen(ROXML_L_NEXT);
00277 } else if(strncmp(ROXML_L_PREV, axes, strlen(ROXML_L_PREV))==0) {
00278
00279 node->axes = ROXML_ID_PREV;
00280 node->name = axes+strlen(ROXML_L_PREV);
00281 } else if(strncmp(ROXML_L_NS, axes, strlen(ROXML_L_NS))==0) {
00282
00283 node->axes = ROXML_ID_NS;
00284 node->name = axes+strlen(ROXML_L_NS);
00285 } else if(strncmp(ROXML_L_CHILD, axes, strlen(ROXML_L_CHILD))==0) {
00286
00287 node->axes = ROXML_ID_CHILD;
00288 node->name = axes+strlen(ROXML_L_CHILD);
00289 } else {
00290
00291 node->axes = ROXML_ID_CHILD;
00292 node->name = axes;
00293 }
00294 return node;
00295 }
00296 int ROXML_INT roxml_get_node_internal_position(node_t *n)
00297 {
00298 int idx = 1;
00299 node_t * prnt;
00300 node_t * first;
00301 if(n == NULL) { return 0; }
00302
00303 prnt = n->prnt;
00304 if(!prnt) {
00305 return 1;
00306 }
00307 first = prnt->chld;
00308
00309 while((first)&&(first != n)) {
00310 idx++;
00311 first = first->sibl;
00312 }
00313
00314 return idx;
00315 }
00316
00317 int ROXML_INT roxml_parse_xpath(char *path, xpath_node_t ** xpath, int context)
00318 {
00319 roxml_xpath_ctx_t ctx;
00320 roxml_parser_item_t * parser = NULL;
00321 ctx.pos = 0;
00322 ctx.nbpath = 1;
00323 ctx.bracket = 0;
00324 ctx.parenthesys = 0;
00325 ctx.quoted = 0;
00326 ctx.dquoted = 0;
00327 ctx.is_first_node = 1;
00328 ctx.wait_first_node = 1;
00329 ctx.shorten_cond = 0;
00330 ctx.context = context;
00331 ctx.first_node = (xpath_node_t*)calloc(1, sizeof(xpath_node_t));
00332 ctx.new_node = ctx.first_node;
00333 ctx.new_cond = NULL;
00334 ctx.first_node->rel = ROXML_OPERATOR_OR;
00335
00336 parser = roxml_append_parser_item(parser, " ", _func_xpath_ignore);
00337 parser = roxml_append_parser_item(parser, "\t", _func_xpath_ignore);
00338 parser = roxml_append_parser_item(parser, "\n", _func_xpath_ignore);
00339 parser = roxml_append_parser_item(parser, "\r", _func_xpath_ignore);
00340 parser = roxml_append_parser_item(parser, "/", _func_xpath_new_node);
00341 parser = roxml_append_parser_item(parser, "(", _func_xpath_open_parenthesys);
00342 parser = roxml_append_parser_item(parser, ")", _func_xpath_close_parenthesys);
00343 parser = roxml_append_parser_item(parser, "[", _func_xpath_open_brackets);
00344 parser = roxml_append_parser_item(parser, "]", _func_xpath_close_brackets);
00345 parser = roxml_append_parser_item(parser, "=", _func_xpath_operator_equal);
00346 parser = roxml_append_parser_item(parser, ">", _func_xpath_operator_sup);
00347 parser = roxml_append_parser_item(parser, "<", _func_xpath_operator_inf);
00348 parser = roxml_append_parser_item(parser, "!", _func_xpath_operator_diff);
00349 parser = roxml_append_parser_item(parser, "0", _func_xpath_number);
00350 parser = roxml_append_parser_item(parser, "1", _func_xpath_number);
00351 parser = roxml_append_parser_item(parser, "2", _func_xpath_number);
00352 parser = roxml_append_parser_item(parser, "3", _func_xpath_number);
00353 parser = roxml_append_parser_item(parser, "4", _func_xpath_number);
00354 parser = roxml_append_parser_item(parser, "5", _func_xpath_number);
00355 parser = roxml_append_parser_item(parser, "6", _func_xpath_number);
00356 parser = roxml_append_parser_item(parser, "7", _func_xpath_number);
00357 parser = roxml_append_parser_item(parser, "8", _func_xpath_number);
00358 parser = roxml_append_parser_item(parser, "9", _func_xpath_number);
00359 parser = roxml_append_parser_item(parser, "+", _func_xpath_operator_add);
00360 parser = roxml_append_parser_item(parser, "-", _func_xpath_operator_subs);
00361 parser = roxml_append_parser_item(parser, ROXML_PATH_OR, _func_xpath_path_or);
00362 parser = roxml_append_parser_item(parser, ROXML_COND_OR, _func_xpath_condition_or);
00363 parser = roxml_append_parser_item(parser, ROXML_COND_AND, _func_xpath_condition_and);
00364 parser = roxml_append_parser_item(parser, ROXML_FUNC_POS_STR, _func_xpath_position);
00365 parser = roxml_append_parser_item(parser, ROXML_FUNC_FIRST_STR, _func_xpath_first);
00366 parser = roxml_append_parser_item(parser, ROXML_FUNC_LAST_STR, _func_xpath_last);
00367 parser = roxml_append_parser_item(parser, NULL, _func_xpath_default);
00368
00369 parser = roxml_parser_prepare(parser);
00370 roxml_parse_line(parser, path, 0, &ctx);
00371 roxml_parser_free(parser);
00372
00373 if(xpath) {
00374 *xpath = ctx.first_node;
00375 }
00376 return ctx.nbpath;
00377 }
00378
00379 void ROXML_INT roxml_free_xcond(xpath_cond_t *xcond)
00380 {
00381 if(xcond->next) {
00382 roxml_free_xcond(xcond->next);
00383 }
00384 if(xcond->xp) {
00385 roxml_free_xpath(xcond->xp, xcond->func2);
00386 }
00387 free(xcond);
00388 }
00389
00390 void ROXML_INT roxml_free_xpath(xpath_node_t *xpath, int nb)
00391 {
00392 int i = 0;
00393 for(i = 0; i < nb; i++) {
00394 if(xpath[i].next) {
00395 roxml_free_xpath(xpath[i].next, 1);
00396 }
00397 if(xpath[i].cond) {
00398 roxml_free_xcond(xpath[i].cond);
00399 }
00400 free(xpath[i].xp_cond);
00401 }
00402 free(xpath);
00403 }
00404
00405 double ROXML_INT roxml_double_oper(double a, double b, int op)
00406 {
00407 if(op == ROXML_OPERATOR_ADD) {
00408 return (a+b);
00409 } else if(op == ROXML_OPERATOR_SUB) {
00410 return (a-b);
00411 } else if(op == ROXML_OPERATOR_MUL) {
00412 return (a*b);
00413 } else if(op == ROXML_OPERATOR_DIV) {
00414 return (a/b);
00415 }
00416 return 0;
00417 }
00418
00419 int ROXML_INT roxml_double_cmp(double a, double b, int op)
00420 {
00421 if(op == ROXML_OPERATOR_DIFF) {
00422 return (a!=b);
00423 } else if(op == ROXML_OPERATOR_EINF) {
00424 return (a<=b);
00425 } else if(op == ROXML_OPERATOR_INF) {
00426 return (a<b);
00427 } else if(op == ROXML_OPERATOR_ESUP) {
00428 return (a>=b);
00429 } else if(op == ROXML_OPERATOR_SUP) {
00430 return (a>b);
00431 } else if(op == ROXML_OPERATOR_EQU) {
00432 return (a==b);
00433 }
00434 return 0;
00435 }
00436
00437 int ROXML_INT roxml_validate_predicat(xpath_node_t *xn, node_t *candidat)
00438 {
00439 int first = 1;
00440 int valid = 0;
00441 xpath_cond_t *condition;
00442
00443 if(xn == NULL) { return 1; }
00444
00445 condition = xn->cond;
00446
00447 if(!condition) {
00448 return 1;
00449 }
00450
00451 while(condition) {
00452 int status = 0;
00453 double iarg1;
00454 double iarg2;
00455 char * sarg1;
00456 char * sarg2;
00457
00458 if(condition->func == ROXML_FUNC_POS) {
00459 status = 0;
00460 iarg2 = atof(condition->arg2);
00461 if(xn->name[0] == '*') {
00462 iarg1 = roxml_get_node_internal_position(candidat);
00463 } else {
00464 iarg1 = roxml_get_node_position(candidat);
00465 }
00466 status = roxml_double_cmp(iarg1, iarg2, condition->op);
00467 } else if(condition->func == ROXML_FUNC_LAST) {
00468 status = 0;
00469 iarg2 = roxml_get_chld_nb(candidat->prnt);
00470 if(xn->name[0] == '*') {
00471 iarg1 = roxml_get_node_internal_position(candidat);
00472 } else {
00473 iarg1 = roxml_get_node_position(candidat);
00474 }
00475 if(condition->op > 0) {
00476 double operand = 0;
00477 operand = atof(condition->arg2);
00478 iarg2 = roxml_double_oper(iarg2, operand, condition->op);
00479 }
00480 status = roxml_double_cmp(iarg1, iarg2, ROXML_OPERATOR_EQU);
00481 } else if(condition->func == ROXML_FUNC_FIRST) {
00482 status = 0;
00483 iarg2 = 1;
00484 if(xn->name[0] == '*') {
00485 iarg1 = roxml_get_node_internal_position(candidat);
00486 } else {
00487 iarg1 = roxml_get_node_position(candidat);
00488 }
00489 if(condition->op > 0) {
00490 double operand = 0;
00491 operand = atof(condition->arg2);
00492 iarg2 = roxml_double_oper(iarg2, operand, condition->op);
00493 }
00494 status = roxml_double_cmp(iarg1, iarg2, ROXML_OPERATOR_EQU);
00495 } else if(condition->func == ROXML_FUNC_INTCOMP) {
00496 char strval[ROXML_BASE_LEN];
00497 node_t *val = roxml_get_attr(candidat, condition->arg1+1, 0);
00498 status = 0;
00499 if(val) {
00500 iarg1 = atof(roxml_get_content(val, strval, ROXML_BASE_LEN, &status));
00501 if(status >= ROXML_BASE_LEN) {
00502 iarg1 = atof(roxml_get_content(val, NULL, 0, &status));
00503 }
00504 iarg2 = atof(condition->arg2);
00505 status = roxml_double_cmp(iarg1, iarg2, condition->op);
00506 roxml_release(RELEASE_LAST);
00507 }
00508 } else if(condition->func == ROXML_FUNC_STRCOMP) {
00509 char strval[ROXML_BASE_LEN];
00510 node_t *val = roxml_get_attr(candidat, condition->arg1+1, 0);
00511 status = 0;
00512 if(val) {
00513 sarg1 = roxml_get_content(val, strval, ROXML_BASE_LEN, &status);
00514 if(status >= ROXML_BASE_LEN) {
00515 sarg1 = roxml_get_content(val, NULL, 0, &status);
00516 }
00517 sarg2 = condition->arg2;
00518 status = (strcmp(sarg1, sarg2)==0);
00519 roxml_release(sarg1);
00520 }
00521 } else if(condition->func == ROXML_FUNC_XPATH) {
00522 int index = condition->func2;
00523 int count = 0;
00524 node_t *root = candidat;
00525 node_t **node_set;
00526 status = 0;
00527
00528 while(root->prnt) { root = root->prnt; }
00529
00530 node_set = roxml_exec_xpath(root, candidat, condition->xp, index, &count);
00531
00532 roxml_release(node_set);
00533
00534 if(count > 0) { status = 1; }
00535
00536 }
00537
00538 if(first) {
00539 valid = status;
00540 first = 0;
00541 } else {
00542 if(condition->rel == ROXML_OPERATOR_OR) {
00543 valid = valid || status;
00544 } else if(condition->rel == ROXML_OPERATOR_AND) {
00545 valid = valid && status;
00546 }
00547 }
00548 condition = condition->next;
00549 }
00550
00551 return valid;
00552 }
00553
00554 int ROXML_INT roxml_request_id(node_t *root)
00555 {
00556 int i = 0;
00557 xpath_tok_table_t * table = NULL;
00558 if(root->priv == NULL) {
00559 table = (xpath_tok_table_t*)calloc(1, sizeof(xpath_tok_table_t));
00560 table->id = ROXML_REQTABLE_ID;
00561 table->ids[ROXML_REQTABLE_ID] = 1;
00562 pthread_mutex_init(&table->mut, NULL);
00563 root->priv = (void*)table;
00564 }
00565 table = (xpath_tok_table_t*)root->priv;
00566 pthread_mutex_lock(&table->mut);
00567 for(i = 1; i < 255; i++) {
00568 if(table->ids[i] == 0) {
00569 table->ids[i]++;
00570 pthread_mutex_unlock(&table->mut);
00571 return i;
00572 }
00573 }
00574 pthread_mutex_unlock(&table->mut);
00575 return -1;
00576 }
00577
00578 int ROXML_INT roxml_in_pool(node_t * root, node_t *n, int req_id)
00579 {
00580 xpath_tok_table_t * table = (xpath_tok_table_t*)root->priv;
00581 pthread_mutex_lock(&table->mut);
00582 if(n->priv) {
00583 xpath_tok_t * tok = (xpath_tok_t*)n->priv;
00584 if(tok->id == req_id) {
00585 pthread_mutex_unlock(&table->mut);
00586 return 1;
00587 } else {
00588 while(tok) {
00589 if(tok->id == req_id) {
00590 pthread_mutex_unlock(&table->mut);
00591 return 1;
00592 }
00593 tok = tok->next;
00594 }
00595 }
00596 }
00597 pthread_mutex_unlock(&table->mut);
00598 return 0;
00599 }
00600
00601 void ROXML_INT roxml_release_id(node_t *root, node_t **pool, int pool_len, int req_id)
00602 {
00603 int i = 0;
00604 xpath_tok_table_t * table = (xpath_tok_table_t*)root->priv;
00605 for(i = 0; i < pool_len; i++) {
00606 roxml_del_from_pool(root, pool[i], req_id);
00607 }
00608 pthread_mutex_lock(&table->mut);
00609 table->ids[req_id] = 0;
00610 pthread_mutex_unlock(&table->mut);
00611 }
00612
00613 void roxml_del_from_pool(node_t * root, node_t *n, int req_id)
00614 {
00615 xpath_tok_table_t * table = (xpath_tok_table_t*)root->priv;
00616 pthread_mutex_lock(&table->mut);
00617 if(n->priv) {
00618 xpath_tok_t * prev = (xpath_tok_t*)n->priv;
00619 xpath_tok_t * tok = (xpath_tok_t*)n->priv;
00620 if(tok->id == req_id) {
00621 n->priv = (void*)tok->next;
00622 free(tok);
00623 } else {
00624 while(tok) {
00625 if(tok->id == req_id) {
00626 prev->next = tok->next;
00627 free(tok);
00628 break;
00629 }
00630 prev = tok;
00631 tok = tok->next;
00632 }
00633 }
00634 }
00635 pthread_mutex_unlock(&table->mut);
00636 }
00637
00638 int ROXML_INT roxml_add_to_pool(node_t *root, node_t *n, int req_id)
00639 {
00640 xpath_tok_table_t * table;
00641 xpath_tok_t * tok;
00642 xpath_tok_t * last_tok = NULL;
00643
00644 if(req_id == 0) { return 1; }
00645 table = (xpath_tok_table_t*)root->priv;
00646
00647
00648 pthread_mutex_lock(&table->mut);
00649 tok = (xpath_tok_t*)n->priv;
00650
00651 while(tok) {
00652 if(tok->id == req_id) {
00653 pthread_mutex_unlock(&table->mut);
00654 return 0;
00655 }
00656 last_tok = tok;
00657 tok = tok->next;
00658 }
00659 if(last_tok == NULL) {
00660 n->priv = calloc(1, sizeof(xpath_tok_t));
00661 last_tok = (xpath_tok_t*)n->priv;
00662 } else {
00663 last_tok->next = (xpath_tok_t*)calloc(1, sizeof(xpath_tok_t));
00664 last_tok = last_tok->next;
00665 }
00666 last_tok->id = req_id;
00667 pthread_mutex_unlock(&table->mut);
00668
00669 return 1;
00670 }
00671
00672 int ROXML_INT roxml_validate_axes(node_t *root, node_t *candidat, node_t ***ans, int *nb, int *max, xpath_node_t *xn, int req_id)
00673 {
00674
00675 int valid = 0;
00676 int path_end = 0;
00677 char * axes = NULL;
00678 char intern_buff[INTERNAL_BUF_SIZE];
00679
00680 if(xn == NULL) {
00681 valid = 1;
00682 path_end = 1;
00683 } else {
00684 axes = xn->name;
00685
00686 if((axes == NULL) || (strcmp("node()", axes) == 0)) {
00687 valid = 1;
00688 } else if(strcmp("*", axes) == 0) {
00689 if(candidat->type & ROXML_STD_NODE) { valid = 1; }
00690 if(candidat->type & ROXML_ATTR_NODE) { valid = 1; }
00691 } else if(strcmp("comment()", axes) == 0) {
00692 if(candidat->type & ROXML_CMT_NODE) { valid = 1; }
00693 } else if(strcmp("processing-instruction()", axes) == 0) {
00694 if(candidat->type & ROXML_PI_NODE) { valid = 1; }
00695 } else if(strcmp("text()", axes) == 0) {
00696 if(candidat->type & ROXML_TXT_NODE) { valid = 1; }
00697 } else if(strcmp("", axes) == 0) {
00698 if(xn->abs) {
00699 candidat = root;
00700 valid = 1;
00701 }
00702 }
00703 if(!valid) {
00704 if(candidat->type & ROXML_PI_NODE) { return 0; }
00705 if(candidat->type & ROXML_CMT_NODE) { return 0; }
00706 }
00707 if(xn->next == NULL) { path_end = 1; }
00708 if((xn->axes == ROXML_ID_SELF)||(xn->axes == ROXML_ID_PARENT)) { valid = 1; }
00709 }
00710
00711 if(!valid) {
00712 char * name = roxml_get_name(candidat, intern_buff, INTERNAL_BUF_SIZE);
00713 if(name && strcmp(name, axes) == 0) {
00714 valid = 1;
00715 }
00716 roxml_release(name);
00717 }
00718
00719 if(valid) {
00720 valid = roxml_validate_predicat(xn, candidat);
00721 }
00722
00723 if((valid)&&(xn->xp_cond)) {
00724 int status;
00725 char * sarg1;
00726 char * sarg2;
00727 xpath_cond_t * condition = xn->xp_cond;
00728 valid = 0;
00729 if(condition->func == ROXML_FUNC_STRCOMP) {
00730 char strval[ROXML_BASE_LEN];
00731 sarg1 = roxml_get_content(candidat, strval, ROXML_BASE_LEN, &status);
00732 if(status >= ROXML_BASE_LEN) {
00733 sarg1 = roxml_get_content(candidat, NULL, 0, &status);
00734 }
00735 sarg2 = condition->arg2;
00736 valid = (strcmp(sarg1, sarg2)==0);
00737 roxml_release(sarg1);
00738 } else if(condition->func == ROXML_FUNC_INTCOMP) {
00739 double iarg1;
00740 double iarg2;
00741 char strval[ROXML_BASE_LEN];
00742 iarg1 = atof(roxml_get_content(candidat, strval, ROXML_BASE_LEN, &status));
00743 if(status >= ROXML_BASE_LEN) {
00744 iarg1 = atof(roxml_get_content(candidat, NULL, 0, &status));
00745 }
00746 iarg2 = atof(condition->arg2);
00747 valid = roxml_double_cmp(iarg1, iarg2, condition->op);
00748 roxml_release(RELEASE_LAST);
00749 }
00750 }
00751
00752 if((valid)&&(path_end)) {
00753 if(roxml_add_to_pool(root, candidat, req_id)) {
00754 if(ans) {
00755 if((*nb) >= (*max)) {
00756 int new_max = (*max)*2;
00757 node_t ** new_ans = roxml_malloc(sizeof(node_t*), new_max, PTR_NODE_RESULT);
00758 memcpy(new_ans, (*ans), *(max)*sizeof(node_t*));
00759 roxml_release(*ans);
00760 *ans = new_ans;
00761 *max = new_max;
00762 }
00763 (*ans)[*nb] = candidat;
00764 }
00765 (*nb)++;
00766 }
00767 }
00768
00769 return valid;
00770 }
00771
00772 void ROXML_INT roxml_check_node(xpath_node_t *xp, node_t *root, node_t *context, node_t ***ans, int *nb, int *max, int ignore, int req_id)
00773 {
00774 int validate_node = 0;
00775
00776 if((req_id == 0) && (*nb > 0)) {
00777 return;
00778 }
00779
00780 if(!xp) { return; }
00781
00782
00783 if(ignore == ROXML_DESC_ONLY) {
00784 node_t *current = context->chld;
00785 while(current) {
00786 roxml_check_node(xp, root, current, ans, nb, max, ignore, req_id);
00787 current = current->sibl;
00788 }
00789 }
00790
00791 switch(xp->axes) {
00792 case ROXML_ID_CHILD: {
00793 node_t *current = context->chld;
00794 while(current) {
00795 validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
00796 if(validate_node) {
00797 roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
00798 }
00799 current = current->sibl;
00800 }
00801 if((xp->name == NULL)||(strcmp(xp->name, "text()") == 0)||(strcmp(xp->name, "node()") == 0)) {
00802 node_t *current = context->text;
00803 while(current) {
00804 validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
00805 current = current->sibl;
00806 }
00807 }
00808 if((xp->name == NULL)||(strcmp(xp->name, "node()") == 0)) {
00809 node_t *current = context->attr;
00810 while(current) {
00811 validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
00812 current = current->sibl;
00813 }
00814 }
00815 } break;
00816 case ROXML_ID_DESC: {
00817 xp = xp->next;
00818 roxml_check_node(xp, root, context, ans, nb, max, ROXML_DESC_ONLY, req_id);
00819 } break;
00820 case ROXML_ID_DESC_O_SELF: {
00821 xp = xp->next;
00822 validate_node = roxml_validate_axes(root, context, ans, nb, max, xp, req_id);
00823 if(validate_node) {
00824 roxml_check_node(xp->next, root, context, ans, nb, max, ROXML_DIRECT, req_id);
00825 }
00826 roxml_check_node(xp, root, context, ans, nb, max, ROXML_DESC_ONLY, req_id);
00827 } break;
00828 case ROXML_ID_SELF: {
00829 validate_node = roxml_validate_axes(root, context, ans, nb, max, xp, req_id);
00830 roxml_check_node(xp->next, root, context, ans, nb, max, ROXML_DIRECT, req_id);
00831 } break;
00832 case ROXML_ID_PARENT: {
00833 validate_node = roxml_validate_axes(root, context->prnt, ans, nb, max, xp, req_id);
00834 roxml_check_node(xp->next, root, context->prnt, ans, nb, max, ROXML_DIRECT, req_id);
00835 } break;
00836 case ROXML_ID_ATTR: {
00837 node_t *attribute = context->attr;
00838 while(attribute) {
00839 validate_node = roxml_validate_axes(root, attribute, ans, nb, max, xp, req_id);
00840 if(validate_node) {
00841 roxml_check_node(xp->next, root, context, ans, nb, max, ROXML_DIRECT, req_id);
00842 }
00843 attribute = attribute->sibl;
00844 }
00845 } break;
00846 case ROXML_ID_ANC: {
00847 node_t *current = context->prnt;
00848 while(current) {
00849 validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
00850 if(validate_node) {
00851 roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
00852 }
00853 current = current->prnt;
00854 }
00855 } break;
00856 case ROXML_ID_NEXT_SIBL: {
00857 node_t *current = context->sibl;
00858 while(current) {
00859 validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
00860 if(validate_node) {
00861 roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
00862 }
00863 current = current->sibl;
00864 }
00865 } break;
00866 case ROXML_ID_PREV_SIBL: {
00867 node_t *current = context->prnt->chld;
00868 while(current != context) {
00869 validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
00870 if(validate_node) {
00871 roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
00872 }
00873 current = current->sibl;
00874 }
00875 } break;
00876 case ROXML_ID_NEXT: {
00877 node_t *current = context;
00878 while(current) {
00879 node_t * following = current->sibl;
00880 while(following) {
00881 validate_node = roxml_validate_axes(root, following, ans, nb, max, xp, req_id);
00882 if(validate_node) {
00883 roxml_check_node(xp->next, root, following, ans, nb, max, ROXML_DIRECT, req_id);
00884 } else {
00885 xp->axes = ROXML_ID_CHILD;
00886 roxml_check_node(xp, root, following, ans, nb, max, ROXML_DESC_ONLY, req_id);
00887 xp->axes = ROXML_ID_NEXT;
00888 }
00889 following = following->sibl;
00890 }
00891 following = current->prnt->chld;
00892 while(following != current) { following = following->sibl; }
00893 current = following->sibl;
00894 }
00895 } break;
00896 case ROXML_ID_PREV: {
00897 node_t *current = context;
00898 while(current && current->prnt) {
00899 node_t *preceding = current->prnt->chld;
00900 while(preceding != current) {
00901 validate_node = roxml_validate_axes(root, preceding, ans, nb, max, xp, req_id);
00902 if(validate_node) {
00903 roxml_check_node(xp->next, root, preceding, ans, nb, max, ROXML_DIRECT, req_id);
00904 } else {
00905 xp->axes = ROXML_ID_CHILD;
00906 roxml_check_node(xp, root, preceding, ans, nb, max, ROXML_DESC_ONLY, req_id);
00907 xp->axes = ROXML_ID_PREV;
00908 }
00909 preceding = preceding->sibl;
00910 }
00911 current = current->prnt;
00912 }
00913 } break;
00914 case ROXML_ID_NS: {
00915
00916 } break;
00917 case ROXML_ID_ANC_O_SELF: {
00918 node_t *current = context;
00919 while(current) {
00920 validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
00921 if(validate_node) {
00922 roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
00923 }
00924 current = current->prnt;
00925 }
00926 } break;
00927 }
00928
00929
00930 return;
00931 }
00932
00933 void ROXML_INT roxml_parent_node_at(node_t *parent, node_t * n, int position)
00934 {
00935 int nb_child = 0;
00936
00937 if(n == NULL) { return; }
00938 if(parent == NULL) { return; }
00939
00940 n->prnt = parent;
00941
00942 if((n->type & ROXML_STD_NODE)||
00943 (n->type & ROXML_CMT_NODE)||
00944 (n->type & ROXML_PI_NODE))
00945 {
00946 nb_child = roxml_get_chld_nb(parent);
00947 } else if(n->type & ROXML_TXT_NODE) {
00948 nb_child = roxml_get_text_nb(parent);
00949 } else if(n->type & ROXML_ATTR_NODE) {
00950 nb_child = roxml_get_attr_nb(parent);
00951 }
00952
00953 if(position <= 0) { position = nb_child+1; }
00954
00955 if(position == 1) {
00956 if((n->type & ROXML_STD_NODE)||
00957 (n->type & ROXML_CMT_NODE)||
00958 (n->type & ROXML_PI_NODE))
00959 {
00960 node_t *first = parent->chld;
00961 parent->chld = n;
00962 n->sibl = first;
00963 } else if(n->type & ROXML_TXT_NODE) {
00964 node_t *first = parent->text;
00965 parent->text = n;
00966 n->sibl = first;
00967 } else if(n->type & ROXML_ATTR_NODE) {
00968 node_t *first = parent->attr;
00969 parent->attr = n;
00970 n->sibl = first;
00971 }
00972 } else {
00973 int i;
00974 node_t * prev = NULL;
00975 node_t * next = NULL;
00976 if((n->type & ROXML_STD_NODE)||
00977 (n->type & ROXML_CMT_NODE)||
00978 (n->type & ROXML_PI_NODE))
00979 {
00980 prev = parent->chld;
00981 next = parent->chld;
00982 } else if(n->type & ROXML_TXT_NODE) {
00983 prev = parent->text;
00984 next = parent->text;
00985 } else if(n->type & ROXML_ATTR_NODE) {
00986 prev = parent->attr;
00987 next = parent->attr;
00988 }
00989 for(i = 1; (i < nb_child+1) && (i < position); i++) {
00990 prev = next;
00991 next = next->sibl;
00992 }
00993 prev->sibl = n;
00994 n->sibl = next;
00995 }
00996 }
00997
00998 void ROXML_INT roxml_print_space(FILE *f, char ** buf, int * offset, int * len, int lvl)
00999 {
01000 int i = 0;
01001 if(*buf) {
01002 int pos = *offset + lvl;
01003 if(pos >= *len) { *buf = realloc(*buf, *len+ROXML_LONG_LEN); }
01004 for(; i < lvl; i++) {
01005 strcat(*buf, " ");
01006 }
01007 *offset = pos;
01008 }
01009 if(f) {
01010 for(; i < lvl; i++) {
01011 fwrite(" ", 1, 1, f);
01012 }
01013 }
01014 }
01015
01016 void ROXML_INT roxml_write_string(char ** buf, FILE * f, char * str, int *offset, int * len)
01017 {
01018 int pos = *offset + strlen(str);
01019 if((pos >= *len)&&(*buf)) { *buf = realloc(*buf, *len+ROXML_LONG_LEN); }
01020 if(f) { fprintf(f, "%s", str); }
01021 if(*buf) { strcat(*buf+(*offset), str); }
01022 *offset = pos;
01023 }
01024
01025 void ROXML_INT roxml_write_node(node_t * n, FILE *f, char * buf, int human, int lvl, int *offset, int *len)
01026 {
01027 char name[ROXML_BASE_LEN];
01028 roxml_get_name(n, name, ROXML_BASE_LEN);
01029 if(human) {
01030 roxml_print_space(f, &buf, offset, len, lvl);
01031 }
01032 if(roxml_get_type(n) == ROXML_STD_NODE) {
01033 node_t *attr = n->attr;
01034 if(n->prnt) {
01035 roxml_write_string(&buf, f, "<", offset, len);
01036 roxml_write_string(&buf, f, name, offset, len);
01037 }
01038 while(attr) {
01039 int status = 0;
01040 char *value;
01041 char arg[ROXML_BASE_LEN];
01042 char val[ROXML_BASE_LEN];
01043 roxml_get_name(attr, arg, ROXML_BASE_LEN);
01044 value = roxml_get_content(attr, val, ROXML_BASE_LEN, &status);
01045 if(status >= ROXML_BASE_LEN) {
01046 value = roxml_get_content(attr, NULL, 0, &status);
01047 }
01048 roxml_write_string(&buf, f, " ", offset, len);
01049 roxml_write_string(&buf, f, arg, offset, len);
01050 roxml_write_string(&buf, f, "=\"", offset, len);
01051 roxml_write_string(&buf, f, value, offset, len);
01052 roxml_write_string(&buf, f, "\"", offset, len);
01053 attr = attr->sibl;
01054 roxml_release(value);
01055 }
01056 if(n->chld || n->text) {
01057 node_t *chld = n->chld;
01058 node_t *text = n->text;
01059 if(n->prnt) {
01060 roxml_write_string(&buf, f, ">", offset, len);
01061 if(human) {
01062 roxml_write_string(&buf, f, "\n", offset, len);
01063 }
01064 }
01065 while(chld || text) {
01066 char val[ROXML_LONG_LEN];
01067 if(text) {
01068 char *value;
01069 int status;
01070 if(human) {
01071 roxml_print_space(f, &buf, offset, len, lvl+1);
01072 }
01073 value = roxml_get_content(text, val, ROXML_LONG_LEN, &status);
01074 if(status >= ROXML_LONG_LEN) {
01075 value = roxml_get_content(text, NULL, 0, &status);
01076 }
01077 roxml_write_string(&buf, f, value, offset, len);
01078 if(human) {
01079 roxml_write_string(&buf, f, "\n", offset, len);
01080 }
01081 text = text->sibl;
01082 roxml_release(value);
01083 }
01084 if(chld) {
01085 roxml_write_node(chld, f, buf, human, lvl+1, offset, len);
01086 chld = chld->sibl;
01087 }
01088 }
01089 if(n->prnt) {
01090 if(human) {
01091 roxml_print_space(f, &buf, offset, len, lvl);
01092 }
01093 roxml_write_string(&buf, f, "</", offset, len);
01094 roxml_write_string(&buf, f, name, offset, len);
01095 roxml_write_string(&buf, f, ">", offset, len);
01096 if(human) {
01097 roxml_write_string(&buf, f, "\n", offset, len);
01098 }
01099 }
01100 } else {
01101 roxml_write_string(&buf, f, "/>", offset, len);
01102 if(human) {
01103 roxml_write_string(&buf, f, "\n", offset, len);
01104 }
01105 }
01106 } else if(roxml_get_type(n) == ROXML_CMT_NODE) {
01107 char *value;
01108 int status;
01109 char val[ROXML_LONG_LEN];
01110 roxml_write_string(&buf, f, "<!--", offset, len);
01111 value = roxml_get_content(n, val, ROXML_LONG_LEN, &status);
01112 if(status >= ROXML_LONG_LEN) {
01113 value = roxml_get_content(n, NULL, 0, &status);
01114 }
01115 roxml_write_string(&buf, f, value, offset, len);
01116 roxml_release(value);
01117 roxml_write_string(&buf, f, "-->", offset, len);
01118 if(human) {
01119 roxml_write_string(&buf, f, "\n", offset, len);
01120 }
01121 } else if(roxml_get_type(n) == ROXML_PI_NODE) {
01122 char *value;
01123 int status;
01124 char val[ROXML_LONG_LEN];
01125 roxml_write_string(&buf, f, "<?", offset, len);
01126 value = roxml_get_content(n, val, ROXML_LONG_LEN, &status);
01127 if(status >= ROXML_LONG_LEN) {
01128 value = roxml_get_content(n, NULL, 0, &status);
01129 }
01130 roxml_write_string(&buf, f, value, offset, len);
01131 roxml_release(value);
01132 roxml_write_string(&buf, f, "?>", offset, len);
01133 if(human) {
01134 roxml_write_string(&buf, f, "\n", offset, len);
01135 }
01136 }
01137 }
01138
01139 void ROXML_INT roxml_del_arg_node(node_t * n)
01140 {
01141 node_t *current = n->prnt->attr;
01142 if(current == n) {
01143 n->prnt->attr = n->sibl;
01144 } else if(current) {
01145 while(current->sibl && current->sibl != n) {
01146 current = current->sibl;
01147 }
01148 current->sibl = n->sibl;
01149 }
01150 return;
01151 }
01152
01153 void ROXML_INT roxml_del_txt_node(node_t * n)
01154 {
01155 node_t *current = n->prnt->text;
01156 if(current == n) {
01157 n->prnt->text = n->sibl;
01158 } else if(current) {
01159 while(current->sibl && current->sibl != n) {
01160 current = current->sibl;
01161 }
01162 current->sibl = n->sibl;
01163 }
01164 }
01165
01166 void ROXML_INT roxml_del_std_node(node_t * n)
01167 {
01168 node_t *current = n->prnt->chld;
01169 if(current == n) {
01170 n->prnt->chld = n->sibl;
01171 } else if(current) {
01172 while(current->sibl && current->sibl != n) {
01173 current = current->sibl;
01174 }
01175 current->sibl = n->sibl;
01176 }
01177 roxml_del_tree(n->chld);
01178 roxml_del_tree(n->text);
01179 roxml_del_tree(n->attr);
01180 }
01181
01182 node_t * roxml_parent_node(node_t *parent, node_t *n)
01183 {
01184 n->prnt = parent;
01185 if(parent) {
01186 if(roxml_get_type(n) == ROXML_ATTR_NODE) {
01187 if(parent->attr) {
01188 parent->attr->next->sibl = n;
01189 parent->attr->next = n;
01190 } else {
01191 parent->attr = n;
01192 parent->attr->next = n;
01193 }
01194 } else if(roxml_get_type(n) == ROXML_TXT_NODE){
01195 if(parent->text) {
01196 parent->text->next->sibl = n;
01197 parent->text->next = n;
01198 } else {
01199 parent->text = n;
01200 parent->text->next = n;
01201 }
01202 } else if((roxml_get_type(n) == ROXML_STD_NODE)||
01203 (roxml_get_type(n) == ROXML_CMT_NODE)||
01204 (roxml_get_type(n) == ROXML_PI_NODE))
01205 {
01206 if(parent->chld) {
01207 parent->next->sibl = n;
01208 parent->next->next = n;
01209 parent->next = n;
01210 } else {
01211 parent->chld = n;
01212 parent->next = n;
01213 }
01214 }
01215 }
01216
01217 return n;
01218 }
01219
01220 void roxml_compute_and(node_t * root, node_t **node_set, int *count, int cur_req_id, int prev_req_id)
01221 {
01222 int i = 0;
01223 for(i = 0; i < *count; i++) {
01224 if((!roxml_in_pool(root, node_set[i], cur_req_id)) || (!roxml_in_pool(root, node_set[i], prev_req_id))) {
01225 (*count)--;
01226 roxml_del_from_pool(root, node_set[i], cur_req_id);
01227 roxml_del_from_pool(root, node_set[i], prev_req_id);
01228 if(*count > 0) {
01229 node_set[i] = node_set[(*count)-1];
01230 }
01231 }
01232 }
01233 }
01234
01235 void roxml_compute_or(node_t * root, node_t **node_set, int *count, int req_id, int glob_id)
01236 {
01237 int i = 0;
01238 for(i = 0; i < *count; i++) {
01239 if(roxml_in_pool(root, node_set[i], req_id)) {
01240 roxml_add_to_pool(root, node_set[i], glob_id);
01241 roxml_del_from_pool(root, node_set[i], req_id);
01242 }
01243 }
01244 }
01245
01246
01247 node_t ** roxml_exec_xpath(node_t *root, node_t *n, xpath_node_t *xpath, int index, int * count)
01248 {
01249 int path_id;
01250 int max_answers = 1;
01251 int glob_id = 0;
01252 int * req_ids = NULL;
01253
01254 node_t **node_set = roxml_malloc(sizeof(node_t*), max_answers, PTR_NODE_RESULT);
01255
01256 *count = 0;
01257 req_ids = calloc(index, sizeof(int));
01258 glob_id = roxml_request_id(root);
01259
01260
01261 for(path_id = 0; path_id < index; path_id++) {
01262 xpath_node_t *cur_xpath = NULL;
01263 xpath_node_t *next_xpath = NULL;
01264 cur_xpath = &xpath[path_id];
01265 if(path_id < index-1) { next_xpath = &xpath[path_id+1]; }
01266
01267 if((cur_xpath->rel == ROXML_OPERATOR_AND)||((next_xpath) && (next_xpath->rel == ROXML_OPERATOR_AND))) {
01268 int req_id = roxml_request_id(root);
01269
01270 node_t *orig = n;
01271 if(cur_xpath->abs) {
01272
01273 orig = root;
01274 }
01275
01276 roxml_check_node(cur_xpath, root, orig, &node_set, count, &max_answers, ROXML_DIRECT, req_id);
01277
01278 if(cur_xpath->rel == ROXML_OPERATOR_AND) {
01279 roxml_compute_and(root, node_set, count, req_id, req_ids[path_id-1]);
01280 }
01281 req_ids[path_id] = req_id;
01282 }
01283 }
01284
01285
01286 for(path_id = 0; path_id < index; path_id++) {
01287 node_t *orig = n;
01288 xpath_node_t *cur_xpath = &xpath[path_id];
01289
01290 if(cur_xpath->rel == ROXML_OPERATOR_OR) {
01291 if(req_ids[path_id] == 0) {
01292 if(cur_xpath->abs) {
01293
01294 orig = root;
01295 }
01296
01297 roxml_check_node(cur_xpath, root, orig, &node_set, count, &max_answers, ROXML_DIRECT, glob_id);
01298 } else {
01299 roxml_compute_or(root, node_set, count, req_ids[path_id+1], glob_id);
01300 roxml_release_id(root, node_set, *count, req_ids[path_id+1]);
01301 }
01302 }
01303 }
01304 roxml_release_id(root, node_set, *count, glob_id);
01305
01306 for(path_id = 0; path_id < index; path_id++) {
01307 if(req_ids[path_id] != 0) {
01308 roxml_release_id(root, node_set, *count, req_ids[path_id]);
01309 }
01310 }
01311
01312 free(req_ids);
01313
01314 return node_set;
01315 }
01316