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

src/roxml-internal.c

Go to the documentation of this file.
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 /* IGNORE_EMPTY_TEXT_NODES */
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 /* IGNORE_EMPTY_TEXT_NODES */
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 /* IGNORE_EMPTY_TEXT_NODES */
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                 // ROXML_S_DESC_O_SELF
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                 // ROXML_L_DESC_O_SELF
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                 // ROXML_L_DESC
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                 // ROXML_L_PARENT
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                 // ROXML_S_PARENT
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                 // ROXML_L_SELF
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                 // ROXML_S_SELF
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                 // ROXML_L_ATTR
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                 // ROXML_S_ATTR
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                 // ROXML_L_ANC
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                 // ROXML_L_ANC_O_SELF
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                 // ROXML_L_NEXT_SIBL
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                 // ROXML_L_PREV_SIBL
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                 // ROXML_L_NEXT
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                 // ROXML_L_PREV
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                 // ROXML_L_NS is not handled
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                 // ROXML_L_CHILD
00287                 node->axes = ROXML_ID_CHILD;
00288                 node->name = axes+strlen(ROXML_L_CHILD);
00289         } else {
00290                 // ROXML_S_CHILD
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         // if found a "all document" axes
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                         // ROXML_L_NS is not handled
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         // process all and xpath
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                                 // context node is root
01273                                 orig = root;
01274                         }
01275                         // assign a new request ID
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         // process all or xpath
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                                         // context node is root
01294                                         orig = root;
01295                                 }
01296                                 // assign a new request ID
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 

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