<libroxml  version="2.2.1" />
contact: tristan.lelong@libroxml.net
roxml-internal.c
Go to the documentation of this file.
1 
25 #include "roxml-internal.h"
26 #include "roxml-parse-engine.h"
27 
28 #ifdef __DEBUG
29 unsigned int _nb_node = 0;
30 unsigned int _nb_attr = 0;
31 unsigned int _nb_text = 0;
32 #endif
33 
35 memory_cell_t head_cell = {PTR_NONE, 0, NULL, 0, NULL, NULL};
36 
37 void * ROXML_INT roxml_malloc(int size, int num, int type)
38 {
39  memory_cell_t *cell = &head_cell;
40  while(cell->next != NULL) { cell = cell->next; }
41  cell->next = (memory_cell_t*)malloc(sizeof(memory_cell_t));
42  if(!cell->next) { return NULL; }
43  cell->next->next = NULL;
44  cell->next->prev = cell;
45  cell = cell->next;
46  cell->type = type;
47  cell->id = pthread_self();
48  cell->occ = size;
49  cell->ptr = calloc(num, size);
50  head_cell.prev = cell;
51  return cell->ptr;
52 }
53 
54 int ROXML_INT roxml_read(int pos, int size, char * buffer, node_t * node)
55 {
56  int ret_len = 0;
57 
58  if(size > 0 && buffer) {
59  if(node->type & ROXML_FILE) {
60  fseek(node->src.fil, pos, SEEK_SET);
61  ret_len = fread(buffer, 1, size, node->src.fil);
62  } else {
63  char *r1 = buffer;
64  char const *r2 = node->src.buf+pos;
65 
66  while (size-- && (*r1++ = *r2++));
67  ret_len = r1 - buffer;
68  }
69  }
70  return ret_len;
71 }
72 
73 node_t * ROXML_INT roxml_create_node(int pos, void *src, int type)
74 {
75  node_t *n = (node_t*)calloc(1, sizeof(node_t));
76  n->type = type;
77  n->src.src = src;
78  n->pos = pos;
79  n->end = pos;
80 
81  return n;
82 }
83 
85 {
86  if(n) {
87  n->end = close->pos;
88  free(close);
89 
90 #ifdef __DEBUG
91  if(n->type & ROXML_ELM_NODE) _nb_node++;
92  if(n->type & ROXML_ATTR_NODE) _nb_attr++;
93  if(n->type & ROXML_TXT_NODE) _nb_text++;
94 #endif
95  }
96 }
97 
99 {
100  if(!n) {
101  return;
102  }
103 
104  if(n->type & ROXML_PENDING) {
105  if(n->pos == 0) {
106  free(n->src.buf);
107  }
108  }
109 
110  if(n->priv) {
111  unsigned char id = *(unsigned char*)n->priv;
112 
113  if(id == ROXML_REQTABLE_ID) {
114  xpath_tok_t * tok = (xpath_tok_t*)n->priv;
116  tok = table->next;
117  pthread_mutex_destroy(&table->mut);
118  free(table);
119  while(tok) {
120  xpath_tok_t * to_delete = tok;
121  tok = tok->next;
122  free(to_delete);
123  }
124  } else if(id == ROXML_NS_ID) {
125  roxml_ns_t * ns = (roxml_ns_t*)n->priv;
126  free(ns);
127  }
128  }
129  free(n);
130 }
131 
133 {
134  if(n == NULL) { return; }
135  roxml_del_tree(n->chld);
136  roxml_del_tree(n->sibl);
137  roxml_del_tree(n->attr);
138  roxml_free_node(n);
139 }
140 
141 int roxml_is_number(char *input)
142 {
143  char *end;
144  int is_number = 0;
145  double r = strtod(input, &end);
146 
147  if((end == NULL) ||
148  (roxml_is_separator(end[0])) ||
149  (end[0] == '"') ||
150  (end[0] == '\'') ||
151  (end[0] == '\0'))
152  {
153  is_number = 1;
154  }
155 
156  return is_number;
157 }
158 
159 
161 {
162  int i = 0;
163  char separators[32] = "\t\n ";
164  while(separators[i] != 0) {
165  if(sep == separators[i]) {
166  return 1;
167  }
168  i++;
169  }
170  return 0;
171 }
172 
174 {
175  if(context->nsdef) {
176  context->nsdef = 0;
177  context->candidat_arg->type |= ROXML_NS_NODE;
178 
179  if(context->candidat_val->pos == context->candidat_val->end) {
180  context->candidat_node->ns = NULL;
181  context->candidat_arg->ns = NULL;
182  } else {
183  roxml_ns_t * ns = calloc(1, sizeof(roxml_ns_t)+1);
184  ns->id = ROXML_NS_ID;
185  ns->alias = (char*)ns + sizeof(roxml_ns_t);
186 
187  context->candidat_arg->priv = ns;
188  context->candidat_arg->ns = context->candidat_arg;
189  context->candidat_node->ns = context->candidat_arg;
190 
191  context->candidat_arg->next = context->namespaces;
192  context->namespaces = context->candidat_arg;
193  }
194  }
195 }
196 
198 {
199  if(context->candidat_txt) {
200 #ifdef IGNORE_EMPTY_TEXT_NODES
201  if(context->empty_text_node == 0) {
202 #endif /* IGNORE_EMPTY_TEXT_NODES */
203  node_t * to_be_closed = roxml_create_node(position, context->src, ROXML_TXT_NODE | context->type);
204  context->candidat_txt = roxml_append_node(context->current_node, context->candidat_txt);
205  roxml_close_node(context->candidat_txt, to_be_closed);
206  context->current_node = context->candidat_txt->prnt;
207 #ifdef IGNORE_EMPTY_TEXT_NODES
208  } else {
209  roxml_free_node(context->candidat_txt);
210  }
211 #endif /* IGNORE_EMPTY_TEXT_NODES */
212  context->candidat_txt = NULL;
213  }
214  context->candidat_node = roxml_create_node(position, context->src, ROXML_ELM_NODE | context->type);
215 }
216 
217 node_t * ROXML_INT roxml_load(node_t *current_node, FILE *file, char *buffer)
218 {
219  int error = 0;
220  char int_buffer[ROXML_BULK_READ+1];
221  roxml_load_ctx_t context;
222  roxml_parser_item_t * parser = NULL;
223  xpath_tok_table_t * table = (xpath_tok_table_t*)calloc(1, sizeof(xpath_tok_table_t));
224 
225  memset(&context, 0, sizeof(roxml_load_ctx_t));
226  context.empty_text_node = 1;
227  context.current_node = current_node;
228 
229  parser = roxml_append_parser_item(parser, " ", _func_load_white);
230  parser = roxml_append_parser_item(parser, "<", _func_load_open_node);
231  parser = roxml_append_parser_item(parser, ">", _func_load_close_node);
232  parser = roxml_append_parser_item(parser, "/", _func_load_end_node);
233  parser = roxml_append_parser_item(parser, "'", _func_load_quoted);
234  parser = roxml_append_parser_item(parser, "\"", _func_load_dquoted);
235  parser = roxml_append_parser_item(parser, "\t", _func_load_white);
236  parser = roxml_append_parser_item(parser, "\n", _func_load_white);
237  parser = roxml_append_parser_item(parser, "\r", _func_load_white);
238  parser = roxml_append_parser_item(parser, "!", _func_load_open_spec_node);
239  parser = roxml_append_parser_item(parser, "]", _func_load_close_cdata);
240  parser = roxml_append_parser_item(parser, "-", _func_load_close_comment);
241  parser = roxml_append_parser_item(parser, "?", _func_load_close_pi);
242  parser = roxml_append_parser_item(parser, ":", _func_load_colon);
243  parser = roxml_append_parser_item(parser, NULL, _func_load_default);
244 
245  parser = roxml_parser_prepare(parser);
246 
247  if(file) {
248  int circle = 0;
249  int int_len = 0;
250  context.type = ROXML_FILE;
251  context.src = (void*)file;
252  context.pos = 0;
253  do {
254  int ret = 0;
255  int chunk_len = 0;
256  int_len = fread(int_buffer+circle, 1, ROXML_BULK_READ-circle, file) + circle;
257  int_buffer[int_len] = '\0';
258 
259  if(int_len == ROXML_BULK_READ) {
260  chunk_len = int_len - ROXML_LONG_LEN;
261  } else {
262  chunk_len = int_len;
263  }
264 
265  ret = roxml_parse_line(parser, int_buffer, chunk_len, &context);
266  circle = int_len-ret;
267  if((ret < 0)||(circle < 0)) {
268  error = 1;
269  break;
270  }
271  memmove(int_buffer, int_buffer+ret, circle);
272  } while(int_len == ROXML_BULK_READ);
273  } else {
274  int ret = 0;
275  context.type = ROXML_BUFF;
276  context.src = (void*)buffer;
277  ret = roxml_parse_line(parser, buffer, 0, &context);
278  if(ret < 0) {
279  error = 1;
280  }
281  }
282 
283  roxml_parser_free(parser);
284 
285 #ifdef IGNORE_EMPTY_TEXT_NODES
286  if(context.empty_text_node == 1) {
287  roxml_free_node(context.candidat_txt);
288  }
289 #endif /* IGNORE_EMPTY_TEXT_NODES */
290 
291  if(!error) {
292  node_t * virtroot = NULL;
293  current_node = roxml_get_root(current_node);
294  virtroot = current_node;
295  while(virtroot->prnt) {
296  virtroot = virtroot->prnt;
297  }
298 
299  table->id = ROXML_REQTABLE_ID;
300  table->ids[ROXML_REQTABLE_ID] = 1;
301  pthread_mutex_init(&table->mut, NULL);
302  virtroot->priv = (void*)table;
303  } else {
304  roxml_close(current_node);
305  return NULL;
306  }
307 
308  return current_node;
309 }
310 
312 {
313  int len = 0;
314  char namespace[MAX_NS_LEN];
315 
316  for(len = 0; ns[len] != '\0' && ns[len] != ':'; len++) {
317  namespace[len] = ns[len];
318  }
319  namespace[len] = '\0';
320 
321  while(nsdef) {
322  if(nsdef->priv && strcmp(namespace, ((roxml_ns_t*)nsdef->priv)->alias) == 0) {
323  break;
324  }
325  nsdef = nsdef->next;
326  }
327  return nsdef;
328 }
329 
330 void ROXML_INT roxml_set_type(node_t * n, int type)
331 {
333  n->type |= type;
334 }
335 
336 xpath_node_t * ROXML_INT roxml_set_axes(xpath_node_t *node, char *axes, int *offset)
337 {
338  struct _xpath_axes {
339  char id;
340  char * name;
341  };
342 
343  struct _xpath_axes xpath_axes[14] = {
344  {ROXML_ID_PARENT, ROXML_L_PARENT},
345  {ROXML_ID_PARENT, ROXML_S_PARENT},
346  {ROXML_ID_SELF, ROXML_L_SELF},
347  {ROXML_ID_SELF, ROXML_S_SELF},
348  {ROXML_ID_ATTR, ROXML_L_ATTR},
349  {ROXML_ID_ATTR, ROXML_S_ATTR},
350  {ROXML_ID_ANC, ROXML_L_ANC},
351  {ROXML_ID_ANC_O_SELF, ROXML_L_ANC_O_SELF},
352  {ROXML_ID_NEXT_SIBL, ROXML_L_NEXT_SIBL},
353  {ROXML_ID_PREV_SIBL, ROXML_L_PREV_SIBL},
354  {ROXML_ID_NEXT, ROXML_L_NEXT},
355  {ROXML_ID_PREV, ROXML_L_PREV},
356  {ROXML_ID_NS, ROXML_L_NS},
357  {ROXML_ID_CHILD, ROXML_L_CHILD},
358  };
359 
360  xpath_node_t *tmp_node;
361  if(axes[0] == '/') {
362  axes[0] = '\0';
363  *offset += 1;
364  axes++;
365  }
366  if(axes[0] == '/') {
367  // ROXML_S_DESC_O_SELF
368  node->axes = ROXML_ID_DESC_O_SELF;
369  node->name = axes+1;
370  tmp_node = (xpath_node_t*)calloc(1, sizeof(xpath_node_t));
371  tmp_node->axes = ROXML_ID_CHILD;
372  node->next = tmp_node;
373  if(strlen(node->name) > 0) {
374  tmp_node = (xpath_node_t*)calloc(1, sizeof(xpath_node_t));
375  node->next->next = tmp_node;
376  node = roxml_set_axes(tmp_node, axes+1, offset);
377  }
378  } else if(strncmp(ROXML_L_DESC_O_SELF, axes, strlen(ROXML_L_DESC_O_SELF))==0) {
379  // ROXML_L_DESC_O_SELF
380  node->axes = ROXML_ID_DESC_O_SELF;
381  node->name = axes+strlen(ROXML_L_DESC_O_SELF);
382  *offset += strlen(ROXML_L_DESC_O_SELF);
383  tmp_node = (xpath_node_t*)calloc(1, sizeof(xpath_node_t));
384  tmp_node->axes = ROXML_ID_CHILD;
385  node->next = tmp_node;
386  node = roxml_set_axes(tmp_node, axes+strlen(ROXML_L_DESC_O_SELF), offset);
387  } else if(strncmp(ROXML_L_DESC, axes, strlen(ROXML_L_DESC))==0) {
388  // ROXML_L_DESC
389  node->axes = ROXML_ID_DESC;
390  node->name = axes+strlen(ROXML_L_DESC);
391  *offset += strlen(ROXML_L_DESC);
392  tmp_node = (xpath_node_t*)calloc(1, sizeof(xpath_node_t));
393  tmp_node->axes = ROXML_ID_CHILD;
394  node->next = tmp_node;
395  node = roxml_set_axes(tmp_node, axes+strlen(ROXML_L_DESC), offset);
396  } else {
397  int i = 0;
398 
399  // ROXML_S_CHILD is default
400  node->axes = ROXML_ID_CHILD;
401  node->name = axes;
402 
403  for(i = 0; i < 14; i++) {
404  int len = strlen(xpath_axes[i].name);
405  if(strncmp(xpath_axes[i].name, axes, len)==0) {
406  node->axes = xpath_axes[i].id;
407  node->name = axes+len;
408  break;
409  }
410  }
411  }
412  return node;
413 }
414 
416 {
417  int idx = 1;
418  node_t * prnt;
419  node_t * first;
420  if(n == NULL) { return 0; }
421 
422  prnt = n->prnt;
423  if(!prnt) {
424  return 1;
425  }
426  first = prnt->chld;
427 
428  while((first)&&(first != n)) {
429  idx++;
430  first = first->sibl;
431  }
432 
433  return idx;
434 }
435 
436 int ROXML_INT roxml_parse_xpath(char *path, xpath_node_t ** xpath, int context)
437 {
438  int ret = 0;
439  roxml_xpath_ctx_t ctx;
440  roxml_parser_item_t * parser = NULL;
441  ctx.pos = 0;
442  ctx.nbpath = 1;
443  ctx.bracket = 0;
444  ctx.parenthesys = 0;
445  ctx.quoted = 0;
446  ctx.dquoted = 0;
447  ctx.content_quoted = 0;
448  ctx.is_first_node = 1;
449  ctx.wait_first_node = 1;
450  ctx.shorten_cond = 0;
451  ctx.context = context;
452  ctx.first_node = (xpath_node_t*)calloc(1, sizeof(xpath_node_t));
453  ctx.new_node = ctx.first_node;
454  ctx.new_cond = NULL;
455  ctx.first_node->rel = ROXML_OPERATOR_OR;
456 
457  parser = roxml_append_parser_item(parser, " ", _func_xpath_ignore);
458  parser = roxml_append_parser_item(parser, "\t", _func_xpath_ignore);
459  parser = roxml_append_parser_item(parser, "\n", _func_xpath_ignore);
460  parser = roxml_append_parser_item(parser, "\r", _func_xpath_ignore);
461  parser = roxml_append_parser_item(parser, "\"", _func_xpath_dquote);
462  parser = roxml_append_parser_item(parser, "\'", _func_xpath_quote);
463  parser = roxml_append_parser_item(parser, "/", _func_xpath_new_node);
464  parser = roxml_append_parser_item(parser, "(", _func_xpath_open_parenthesys);
465  parser = roxml_append_parser_item(parser, ")", _func_xpath_close_parenthesys);
466  parser = roxml_append_parser_item(parser, "[", _func_xpath_open_brackets);
467  parser = roxml_append_parser_item(parser, "]", _func_xpath_close_brackets);
468  parser = roxml_append_parser_item(parser, "=", _func_xpath_operator_equal);
469  parser = roxml_append_parser_item(parser, ">", _func_xpath_operator_sup);
470  parser = roxml_append_parser_item(parser, "<", _func_xpath_operator_inf);
471  parser = roxml_append_parser_item(parser, "!", _func_xpath_operator_diff);
472  parser = roxml_append_parser_item(parser, "0", _func_xpath_number);
473  parser = roxml_append_parser_item(parser, "1", _func_xpath_number);
474  parser = roxml_append_parser_item(parser, "2", _func_xpath_number);
475  parser = roxml_append_parser_item(parser, "3", _func_xpath_number);
476  parser = roxml_append_parser_item(parser, "4", _func_xpath_number);
477  parser = roxml_append_parser_item(parser, "5", _func_xpath_number);
478  parser = roxml_append_parser_item(parser, "6", _func_xpath_number);
479  parser = roxml_append_parser_item(parser, "7", _func_xpath_number);
480  parser = roxml_append_parser_item(parser, "8", _func_xpath_number);
481  parser = roxml_append_parser_item(parser, "9", _func_xpath_number);
482  parser = roxml_append_parser_item(parser, "+", _func_xpath_operator_add);
483  parser = roxml_append_parser_item(parser, "-", _func_xpath_operator_subs);
484  parser = roxml_append_parser_item(parser, ROXML_PATH_OR, _func_xpath_path_or);
485  parser = roxml_append_parser_item(parser, ROXML_COND_OR, _func_xpath_condition_or);
486  parser = roxml_append_parser_item(parser, ROXML_COND_AND, _func_xpath_condition_and);
487  parser = roxml_append_parser_item(parser, ROXML_FUNC_POS_STR, _func_xpath_position);
488  parser = roxml_append_parser_item(parser, ROXML_FUNC_FIRST_STR, _func_xpath_first);
489  parser = roxml_append_parser_item(parser, ROXML_FUNC_LAST_STR, _func_xpath_last);
490  parser = roxml_append_parser_item(parser, ROXML_FUNC_NSURI_STR, _func_xpath_nsuri);
491  parser = roxml_append_parser_item(parser, NULL, _func_xpath_default);
492 
493  parser = roxml_parser_prepare(parser);
494  ret = roxml_parse_line(parser, path, 0, &ctx);
495  roxml_parser_free(parser);
496 
497  if(ret >= 0) {
498  if(xpath) {
499  *xpath = ctx.first_node;
500  }
501  return ctx.nbpath;
502  }
503 
505  return -1;
506 }
507 
509 {
510  if(xcond->next) {
511  roxml_free_xcond(xcond->next);
512  }
513  if(xcond->xp) {
514  roxml_free_xpath(xcond->xp, xcond->func2);
515  }
516  free(xcond);
517 }
518 
520 {
521  int i = 0;
522  for(i = 0; i < nb; i++) {
523  if(xpath[i].next) {
524  roxml_free_xpath(xpath[i].next, 1);
525  }
526  if(xpath[i].cond) {
527  roxml_free_xcond(xpath[i].cond);
528  }
529  free(xpath[i].xp_cond);
530  }
531  free(xpath);
532 }
533 
534 double ROXML_INT roxml_double_oper(double a, double b, int op)
535 {
536  if(op == ROXML_OPERATOR_ADD) {
537  return (a+b);
538  } else if(op == ROXML_OPERATOR_SUB) {
539  return (a-b);
540  } else if(op == ROXML_OPERATOR_MUL) {
541  return (a*b);
542  } else if(op == ROXML_OPERATOR_DIV) {
543  return (a/b);
544  }
545  return 0;
546 }
547 
548 int ROXML_INT roxml_double_cmp(double a, double b, int op)
549 {
550  if(op == ROXML_OPERATOR_DIFF) {
551  return (a!=b);
552  } else if(op == ROXML_OPERATOR_EINF) {
553  return (a<=b);
554  } else if(op == ROXML_OPERATOR_INF) {
555  return (a<b);
556  } else if(op == ROXML_OPERATOR_ESUP) {
557  return (a>=b);
558  } else if(op == ROXML_OPERATOR_SUP) {
559  return (a>b);
560  } else if(op == ROXML_OPERATOR_EQU) {
561  return (a==b);
562  }
563  return 0;
564 }
565 
566 int ROXML_INT roxml_string_cmp(char *sa, char *sb, int op)
567 {
568  int result;
569 
570  result = strcmp(sa, sb);
571 
572  if(op == ROXML_OPERATOR_DIFF) {
573  return (result != 0);
574  } else if(op == ROXML_OPERATOR_EINF) {
575  return (result <= 0);
576  } else if(op == ROXML_OPERATOR_INF) {
577  return (result < 0);
578  } else if(op == ROXML_OPERATOR_ESUP) {
579  return (result >= 0);
580  } else if(op == ROXML_OPERATOR_SUP) {
581  return (result > 0);
582  } else if(op == ROXML_OPERATOR_EQU) {
583  return (result == 0);
584  }
585  return 0;
586 }
587 
589 {
590  int first = 1;
591  int valid = 0;
592  xpath_cond_t *condition;
593 
594  if(xn == NULL) { return 1; }
595 
596  condition = xn->cond;
597 
598  if(!condition) {
599  return 1;
600  }
601 
602  while(condition) {
603  int status = 0;
604  double iarg1;
605  double iarg2;
606  char * sarg1;
607  char * sarg2;
608 
609  if(condition->func == ROXML_FUNC_POS) {
610  status = 0;
611  iarg2 = atof(condition->arg2);
612  if(xn->name[0] == '*') {
613  iarg1 = roxml_get_node_internal_position(candidat);
614  } else {
615  iarg1 = roxml_get_node_position(candidat);
616  }
617  status = roxml_double_cmp(iarg1, iarg2, condition->op);
618  } else if(condition->func == ROXML_FUNC_LAST) {
619  status = 0;
620  iarg2 = roxml_get_chld_nb(candidat->prnt);
621  if(xn->name[0] == '*') {
622  iarg1 = roxml_get_node_internal_position(candidat);
623  } else {
624  iarg1 = roxml_get_node_position(candidat);
625  }
626  if(condition->op > 0) {
627  double operand = 0;
628  operand = atof(condition->arg2);
629  iarg2 = roxml_double_oper(iarg2, operand, condition->op);
630  }
631  status = roxml_double_cmp(iarg1, iarg2, ROXML_OPERATOR_EQU);
632  } else if(condition->func == ROXML_FUNC_FIRST) {
633  status = 0;
634  iarg2 = 1;
635  if(xn->name[0] == '*') {
636  iarg1 = roxml_get_node_internal_position(candidat);
637  } else {
638  iarg1 = roxml_get_node_position(candidat);
639  }
640  if(condition->op > 0) {
641  double operand = 0;
642  operand = atof(condition->arg2);
643  iarg2 = roxml_double_oper(iarg2, operand, condition->op);
644  }
645  status = roxml_double_cmp(iarg1, iarg2, ROXML_OPERATOR_EQU);
646  } else if(condition->func == ROXML_FUNC_INTCOMP) {
647  char strval[ROXML_BASE_LEN];
648  node_t *val = roxml_get_attr(candidat, condition->arg1+1, 0);
649  status = 0;
650  if(val) {
651  iarg1 = atof(roxml_get_content(val, strval, ROXML_BASE_LEN, &status));
652  if(status >= ROXML_BASE_LEN) {
653  iarg1 = atof(roxml_get_content(val, NULL, 0, &status));
655  }
656  iarg2 = atof(condition->arg2);
657  status = roxml_double_cmp(iarg1, iarg2, condition->op);
658  }
659  } else if(condition->func == ROXML_FUNC_NSURI) {
660  char strval[ROXML_BASE_LEN];
661  node_t *val = roxml_get_ns(candidat);
662  status = 0;
663  if(val) {
664  sarg1 = roxml_get_content(val, strval, ROXML_BASE_LEN, &status);
665  if(status >= ROXML_BASE_LEN) {
666  sarg1 = roxml_get_content(val, NULL, 0, &status);
667  }
668  sarg2 = condition->arg2;
669  status = roxml_string_cmp(sarg1, sarg2, condition->op);
670  roxml_release(sarg1);
671  } else {
672  sarg2 = condition->arg2;
673  status = roxml_string_cmp("", sarg2, condition->op);
674  }
675  } else if(condition->func == ROXML_FUNC_STRCOMP) {
676  char strval[ROXML_BASE_LEN];
677  node_t *val = roxml_get_attr(candidat, condition->arg1+1, 0);
678  status = 0;
679  if(val) {
680  sarg1 = roxml_get_content(val, strval, ROXML_BASE_LEN, &status);
681  if(status >= ROXML_BASE_LEN) {
682  sarg1 = roxml_get_content(val, NULL, 0, &status);
683  }
684  sarg2 = condition->arg2;
685  status = roxml_string_cmp(sarg1, sarg2, condition->op);
686  roxml_release(sarg1);
687  }
688  } else if(condition->func == ROXML_FUNC_XPATH) {
689  int index = condition->func2;
690  int count = 0;
691  node_t *root = roxml_get_root(candidat);
692  node_t **node_set;
693  status = 0;
694 
695  node_set = roxml_exec_xpath(root, candidat, condition->xp, index, &count);
696 
697  roxml_release(node_set);
698 
699  if(count > 0) { status = 1; }
700 
701  }
702 
703  if(first) {
704  valid = status;
705  first = 0;
706  } else {
707  if(condition->rel == ROXML_OPERATOR_OR) {
708  valid = valid || status;
709  } else if(condition->rel == ROXML_OPERATOR_AND) {
710  valid = valid && status;
711  }
712  }
713  condition = condition->next;
714  }
715 
716  return valid;
717 }
718 
720 {
721  int i = 0;
722  xpath_tok_table_t * table = NULL;
723 
724  while(root->prnt) {
725  root = root->prnt;
726  }
727 
728  table = (xpath_tok_table_t*)root->priv;
729 
730  pthread_mutex_lock(&table->mut);
731  for(i = ROXML_XPATH_FIRST_ID; i < 255; i++) {
732  if(table->ids[i] == 0) {
733  table->ids[i]++;
734  pthread_mutex_unlock(&table->mut);
735  return i;
736  }
737  }
738  pthread_mutex_unlock(&table->mut);
739  return -1;
740 }
741 
742 int ROXML_INT roxml_in_pool(node_t * root, node_t *n, int req_id)
743 {
744  xpath_tok_table_t * table = NULL;
745 
746  while(root->prnt) {
747  root = root->prnt;
748  }
749 
750  table = (xpath_tok_table_t*)root->priv;
751 
752  pthread_mutex_lock(&table->mut);
753  if(n->priv) {
754  xpath_tok_t * tok = (xpath_tok_t*)n->priv;
755  if(tok->id == req_id) {
756  pthread_mutex_unlock(&table->mut);
757  return 1;
758  } else {
759  while(tok) {
760  if(tok->id == req_id) {
761  pthread_mutex_unlock(&table->mut);
762  return 1;
763  }
764  tok = tok->next;
765  }
766  }
767  }
768  pthread_mutex_unlock(&table->mut);
769  return 0;
770 }
771 
772 void ROXML_INT roxml_release_id(node_t *root, node_t **pool, int pool_len, int req_id)
773 {
774  int i = 0;
775  xpath_tok_table_t * table = NULL;
776 
777  while(root->prnt) {
778  root = root->prnt;
779  }
780 
781  table = (xpath_tok_table_t*)root->priv;
782 
783  for(i = 0; i < pool_len; i++) {
784  roxml_del_from_pool(root, pool[i], req_id);
785  }
786  pthread_mutex_lock(&table->mut);
787  table->ids[req_id] = 0;
788  pthread_mutex_unlock(&table->mut);
789 }
790 
791 void roxml_del_from_pool(node_t * root, node_t *n, int req_id)
792 {
793  xpath_tok_table_t * table = NULL;
794 
795  while(root->prnt) {
796  root = root->prnt;
797  }
798 
799  table = (xpath_tok_table_t*)root->priv;
800 
801  pthread_mutex_lock(&table->mut);
802  if(n->priv) {
803  xpath_tok_t * prev = (xpath_tok_t*)n->priv;
804  xpath_tok_t * tok = (xpath_tok_t*)n->priv;
805  if(tok->id == req_id) {
806  n->priv = (void*)tok->next;
807  free(tok);
808  } else {
809  while(tok) {
810  if(tok->id == req_id) {
811  prev->next = tok->next;
812  free(tok);
813  break;
814  }
815  prev = tok;
816  tok = tok->next;
817  }
818  }
819  }
820  pthread_mutex_unlock(&table->mut);
821 }
822 
823 int ROXML_INT roxml_add_to_pool(node_t *root, node_t *n, int req_id)
824 {
825  xpath_tok_table_t * table;
826  xpath_tok_t * tok;
827  xpath_tok_t * last_tok = NULL;
828 
829  while(root->prnt) {
830  root = root->prnt;
831  }
832 
833  if(req_id == 0) { return 1; }
834  table = (xpath_tok_table_t*)root->priv;
835 
836 
837  pthread_mutex_lock(&table->mut);
838  tok = (xpath_tok_t*)n->priv;
839 
840  while(tok) {
841  if(tok->id == req_id) {
842  pthread_mutex_unlock(&table->mut);
843  return 0;
844  }
845  last_tok = tok;
846  tok = (xpath_tok_t*)tok->next;
847  }
848  if(last_tok == NULL) {
849  n->priv = calloc(1, sizeof(xpath_tok_t));
850  last_tok = (xpath_tok_t*)n->priv;
851  } else {
852  last_tok->next = (xpath_tok_t*)calloc(1, sizeof(xpath_tok_t));
853  last_tok = last_tok->next;
854  }
855  last_tok->id = req_id;
856  pthread_mutex_unlock(&table->mut);
857 
858  return 1;
859 }
860 
861 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)
862 {
863 
864  int valid = 0;
865  int path_end = 0;
866  char * axes = NULL;
867  char intern_buff[INTERNAL_BUF_SIZE];
868  char intern_buff2[INTERNAL_BUF_SIZE];
869 
870  if(xn == NULL) {
871  valid = 1;
872  path_end = 1;
873  } else {
874  axes = xn->name;
875 
876  if((axes == NULL) || (strcmp("node()", axes) == 0)) {
877  valid = 1;
878  } else if(strcmp("*", axes) == 0) {
879  if(candidat->type & ROXML_ELM_NODE) { valid = 1; }
880  if(candidat->type & ROXML_ATTR_NODE) { valid = 1; }
881  } else if(strcmp("comment()", axes) == 0) {
882  if(candidat->type & ROXML_CMT_NODE) { valid = 1; }
883  } else if(strcmp("processing-instruction()", axes) == 0) {
884  if(candidat->type & ROXML_PI_NODE) { valid = 1; }
885  } else if(strcmp("text()", axes) == 0) {
886  if(candidat->type & ROXML_TXT_NODE) { valid = 1; }
887  } else if(strcmp("", axes) == 0) {
888  if(xn->abs) {
889  candidat = root;
890  valid = 1;
891  }
892  }
893  if(!valid) {
894  if(candidat->type & ROXML_PI_NODE) { return 0; }
895  if(candidat->type & ROXML_CMT_NODE) { return 0; }
896  }
897  if(xn->next == NULL) { path_end = 1; }
898  if((xn->axes == ROXML_ID_SELF)||(xn->axes == ROXML_ID_PARENT)) { valid = 1; }
899  }
900 
901  if(!valid) {
902  int ns_len = 0;
903  char * name = intern_buff;
904  if(candidat->ns) {
905  name = roxml_get_name(candidat->ns, intern_buff, INTERNAL_BUF_SIZE);
906  ns_len = strlen(name);
907  if(ns_len) {
908  name[ns_len] = ':';
909  ns_len++;
910  }
911  }
912  roxml_get_name(candidat, intern_buff+ns_len, INTERNAL_BUF_SIZE-ns_len);
913  if(name && strcmp(name, axes) == 0) {
914  valid = 1;
915  }
916  }
917 
918  if(valid) {
919  valid = roxml_validate_predicat(xn, candidat);
920  }
921 
922  if((valid)&&(xn->xp_cond)) {
923  int status;
924  char * sarg1;
925  char * sarg2;
926  xpath_cond_t * condition = xn->xp_cond;
927  valid = 0;
928  if(condition->func == ROXML_FUNC_STRCOMP) {
929  char strval[ROXML_BASE_LEN];
930  sarg1 = roxml_get_content(candidat, strval, ROXML_BASE_LEN, &status);
931  if(status >= ROXML_BASE_LEN) {
932  sarg1 = roxml_get_content(candidat, NULL, 0, &status);
933  }
934  sarg2 = condition->arg2;
935  valid = roxml_string_cmp(sarg1, sarg2, condition->op);
936  roxml_release(sarg1);
937  } else if(condition->func == ROXML_FUNC_INTCOMP) {
938  double iarg1;
939  double iarg2;
940  char strval[ROXML_BASE_LEN];
941  iarg1 = atof(roxml_get_content(candidat, strval, ROXML_BASE_LEN, &status));
942  if(status >= ROXML_BASE_LEN) {
943  iarg1 = atof(roxml_get_content(candidat, NULL, 0, &status));
945  }
946  iarg2 = atof(condition->arg2);
947  valid = roxml_double_cmp(iarg1, iarg2, condition->op);
948  }
949  }
950 
951  if((valid)&&(path_end)) {
952  if(roxml_add_to_pool(root, candidat, req_id)) {
953  if(ans) {
954  if((*nb) >= (*max)) {
955  int new_max = (*max)*2;
956  node_t ** new_ans = roxml_malloc(sizeof(node_t*), new_max, PTR_NODE_RESULT);
957  memcpy(new_ans, (*ans), *(max)*sizeof(node_t*));
958  roxml_release(*ans);
959  *ans = new_ans;
960  *max = new_max;
961  }
962  (*ans)[*nb] = candidat;
963  }
964  (*nb)++;
965  }
966  }
967 
968  return valid;
969 }
970 
971 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)
972 {
973  int validate_node = 0;
974 
975  if((req_id == 0) && (*nb > 0)) {
976  return;
977  }
978 
979  if(!xp) { return; }
980 
981  // if found a "all document" axes
982  if(ignore == ROXML_DESC_ONLY) {
983  node_t *current = context->chld;
984  while(current) {
985  roxml_check_node(xp, root, current, ans, nb, max, ignore, req_id);
986  current = current->sibl;
987  }
988  }
989 
990  switch(xp->axes) {
991  case ROXML_ID_CHILD: {
992  node_t *current = context->chld;
993  while(current) {
994  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
995  if(validate_node) {
996  roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
997  }
998  current = current->sibl;
999  }
1000  if((xp->name == NULL)||(strcmp(xp->name, "text()") == 0)||(strcmp(xp->name, "node()") == 0)) {
1001  node_t *current = roxml_get_txt(context, 0);
1002  while(current) {
1003  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1004  current = current->sibl;
1005  }
1006  }
1007  if((xp->name == NULL)||(strcmp(xp->name, "node()") == 0)) {
1008  node_t *current = context->attr;
1009  while(current) {
1010  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1011  current = current->sibl;
1012  }
1013  }
1014  } break;
1015  case ROXML_ID_DESC: {
1016  xp = xp->next;
1017  roxml_check_node(xp, root, context, ans, nb, max, ROXML_DESC_ONLY, req_id);
1018  } break;
1019  case ROXML_ID_DESC_O_SELF: {
1020  xp = xp->next;
1021  validate_node = roxml_validate_axes(root, context, ans, nb, max, xp, req_id);
1022  if(validate_node) {
1023  roxml_check_node(xp->next, root, context, ans, nb, max, ROXML_DIRECT, req_id);
1024  }
1025  roxml_check_node(xp, root, context, ans, nb, max, ROXML_DESC_ONLY, req_id);
1026  } break;
1027  case ROXML_ID_SELF: {
1028  validate_node = roxml_validate_axes(root, context, ans, nb, max, xp, req_id);
1029  roxml_check_node(xp->next, root, context, ans, nb, max, ROXML_DIRECT, req_id);
1030  } break;
1031  case ROXML_ID_PARENT: {
1032  if (context->prnt) {
1033  validate_node = roxml_validate_axes(root, context->prnt, ans, nb, max, xp, req_id);
1034  roxml_check_node(xp->next, root, context->prnt, ans, nb, max, ROXML_DIRECT, req_id);
1035  } else {
1036  validate_node = 0;
1037  }
1038  } break;
1039  case ROXML_ID_ATTR: {
1040  node_t *attribute = context->attr;
1041  while(attribute) {
1042  validate_node = roxml_validate_axes(root, attribute, ans, nb, max, xp, req_id);
1043  if(validate_node) {
1044  roxml_check_node(xp->next, root, context, ans, nb, max, ROXML_DIRECT, req_id);
1045  }
1046  attribute = attribute->sibl;
1047  }
1048  } break;
1049  case ROXML_ID_ANC: {
1050  node_t *current = context->prnt;
1051  while(current) {
1052  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1053  if(validate_node) {
1054  roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
1055  }
1056  current = current->prnt;
1057  }
1058  } break;
1059  case ROXML_ID_NEXT_SIBL: {
1060  node_t *current = context->sibl;
1061  while(current) {
1062  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1063  if(validate_node) {
1064  roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
1065  }
1066  current = current->sibl;
1067  }
1068  } break;
1069  case ROXML_ID_PREV_SIBL: {
1070  node_t *current = context->prnt->chld;
1071  while(current != context) {
1072  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1073  if(validate_node) {
1074  roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
1075  }
1076  current = current->sibl;
1077  }
1078  } break;
1079  case ROXML_ID_NEXT: {
1080  node_t *current = context;
1081  while(current) {
1082  node_t * following = current->sibl;
1083  while(following) {
1084  validate_node = roxml_validate_axes(root, following, ans, nb, max, xp, req_id);
1085  if(validate_node) {
1086  roxml_check_node(xp->next, root, following, ans, nb, max, ROXML_DIRECT, req_id);
1087  } else {
1088  xp->axes = ROXML_ID_CHILD;
1089  roxml_check_node(xp, root, following, ans, nb, max, ROXML_DESC_ONLY, req_id);
1090  xp->axes = ROXML_ID_NEXT;
1091  }
1092  following = following->sibl;
1093  }
1094  following = current->prnt->chld;
1095  while(following != current) { following = following->sibl; }
1096  current = following->sibl;
1097  }
1098  } break;
1099  case ROXML_ID_PREV: {
1100  node_t *current = context;
1101  while(current && current->prnt) {
1102  node_t *preceding = current->prnt->chld;
1103  while(preceding != current) {
1104  validate_node = roxml_validate_axes(root, preceding, ans, nb, max, xp, req_id);
1105  if(validate_node) {
1106  roxml_check_node(xp->next, root, preceding, ans, nb, max, ROXML_DIRECT, req_id);
1107  } else {
1108  xp->axes = ROXML_ID_CHILD;
1109  roxml_check_node(xp, root, preceding, ans, nb, max, ROXML_DESC_ONLY, req_id);
1110  xp->axes = ROXML_ID_PREV;
1111  }
1112  preceding = preceding->sibl;
1113  }
1114  current = current->prnt;
1115  }
1116  } break;
1117  case ROXML_ID_NS: {
1118  validate_node = roxml_validate_axes(root, context->ns, ans, nb, max, xp, req_id);
1119  if(validate_node) {
1120  roxml_check_node(xp->next, root, context, ans, nb, max, ROXML_DIRECT, req_id);
1121  }
1122  } break;
1123  case ROXML_ID_ANC_O_SELF: {
1124  node_t *current = context;
1125  while(current) {
1126  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1127  if(validate_node) {
1128  roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
1129  }
1130  current = current->prnt;
1131  }
1132  } break;
1133  }
1134 
1135 
1136  return;
1137 }
1138 
1140 {
1141  if(parent == NULL) {
1142  return n;
1143  }
1144 
1145  n->prnt = parent;
1146 
1147  if(parent->ns && ((parent->ns->type & ROXML_INVALID) != ROXML_INVALID) && ((roxml_ns_t*)parent->ns->priv)->alias[0] == '\0') {
1148  if(n->ns == NULL) {
1149  n->ns = parent->ns;
1150  }
1151  }
1152 
1153  if(n->type & ROXML_ATTR_NODE) {
1154  if(parent->attr) {
1155  node_t *attr = parent->attr;
1156  while(attr->sibl) {
1157  attr = attr->sibl;
1158  }
1159  attr->sibl = n;
1160  } else {
1161  parent->attr = n;
1162  }
1163  } else {
1164  if(parent->next) {
1165  parent->next->sibl = n;
1166  } else {
1167  parent->chld = n;
1168  }
1169  parent->next = n;
1170  }
1171 
1172  return n;
1173 }
1174 
1175 node_t * ROXML_INT roxml_parent_node(node_t *parent, node_t * n, int position)
1176 {
1177  int nb;
1178 
1179  if(n == NULL) { return NULL; }
1180  if(parent == NULL) { return n; }
1181 
1182  if(position == 0) {
1183  return roxml_append_node(parent, n);
1184  }
1185 
1186  if(n->type & ROXML_ATTR_NODE) {
1187  nb = roxml_get_attr_nb(n->prnt);
1188  } else {
1190  }
1191 
1192  if(position > nb) {
1193  return roxml_append_node(parent, n);
1194  }
1195 
1196  n->prnt = parent;
1197 
1198  if(parent->ns && ((parent->ns->type & ROXML_INVALID) != ROXML_INVALID) && ((roxml_ns_t*)parent->ns->priv)->alias[0] == '\0') {
1199  if(n->ns == NULL) {
1200  n->ns = parent->ns;
1201  }
1202  }
1203 
1204  if(position == 1) {
1205  if(n->type & ROXML_ATTR_NODE) {
1206  n->sibl = parent->attr;
1207  parent->attr = n;
1208  } else {
1209  n->sibl = parent->chld;
1210  parent->chld = n;
1211  }
1212  } else {
1213  int i;
1214  node_t * prev = parent->chld;
1215  node_t * next = parent->chld;
1216 
1217  if(n->type & ROXML_ATTR_NODE) {
1218  next = parent->attr;
1219  }
1220  for(i = 1; i < position; i++) {
1221  prev = next;
1222  next = next->sibl;
1223  }
1224  n->sibl = next;
1225  prev->sibl = n;
1226  }
1227  return n;
1228 }
1229 
1230 void ROXML_INT roxml_print_space(FILE *f, char ** buf, int * offset, int * len, int lvl)
1231 {
1232  int i = 0;
1233 
1234  if(lvl > 0) {
1235  if(buf && *buf) {
1236  int pos = *offset + lvl;
1237  if(pos >= *len) {
1238  *buf = realloc(*buf, *len+ROXML_LONG_LEN);
1239  memset(*buf+*len, 0, ROXML_LONG_LEN);
1240  *len += ROXML_LONG_LEN;
1241  }
1242  for(; i < lvl; i++) {
1243  strcat(*buf, " ");
1244  }
1245  *offset = pos;
1246  }
1247  if(f) {
1248  for(; i < lvl; i++) {
1249  fwrite(" ", 1, 1, f);
1250  }
1251  }
1252  }
1253 }
1254 
1255 void ROXML_INT roxml_write_string(char ** buf, FILE * f, char * str, int *offset, int * len)
1256 {
1257  int min_len = strlen(str);
1258  int pos = *offset + min_len;
1259  int appended_space = ROXML_LONG_LEN*((int)(min_len/ROXML_LONG_LEN)+1);
1260 
1261  if((pos >= *len) && (buf) && (*buf)) {
1262  *buf = realloc(*buf, *len+appended_space);
1263  memset(*buf+*len, 0, appended_space);
1264  *len += appended_space;
1265  }
1266  if(f) { fprintf(f, "%s", str); }
1267  if(buf && *buf) { strcat(*buf+(*offset), str); }
1268  *offset = pos;
1269 }
1270 
1271 void ROXML_INT roxml_write_node(node_t * n, FILE *f, char ** buf, int human, int lvl, int *offset, int *len)
1272 {
1273  char name[ROXML_BASE_LEN];
1274  char ns[ROXML_BASE_LEN];
1275  roxml_get_name(n, name, ROXML_BASE_LEN);
1276  if(human) {
1277  roxml_print_space(f, buf, offset, len, lvl);
1278  }
1279  if((n->type & ROXML_NODE_TYPES) == ROXML_ELM_NODE) {
1280  node_t *attr = n->attr;
1281  if(n->prnt) {
1282  roxml_write_string(buf, f, "<", offset, len);
1283  if(n->ns) {
1284  roxml_get_name(n->ns, ns, ROXML_BASE_LEN);
1285  if(ns[0] != '\0') {
1286  roxml_write_string(buf, f, ns, offset, len);
1287  roxml_write_string(buf, f, ":", offset, len);
1288  }
1289  }
1290  roxml_write_string(buf, f, name, offset, len);
1291  }
1292  while(attr) {
1293  int status = 0;
1294  char *value;
1295  char arg[ROXML_BASE_LEN];
1296  char val[ROXML_BASE_LEN];
1297  char arg_ns[ROXML_BASE_LEN];
1298  roxml_get_name(attr, arg, ROXML_BASE_LEN);
1299  value = roxml_get_content(attr, val, ROXML_BASE_LEN, &status);
1300  if(status >= ROXML_BASE_LEN) {
1301  value = roxml_get_content(attr, NULL, 0, &status);
1302  }
1303  roxml_write_string(buf, f, " ", offset, len);
1304  if(attr->type & ROXML_NS_NODE) {
1305  roxml_write_string(buf, f, "xmlns", offset, len);
1306  if(arg[0] != '\0') {
1307  roxml_write_string(buf, f, ":", offset, len);
1308  }
1309  }
1310  if(attr->ns) {
1311  roxml_get_name(attr->ns, arg_ns, ROXML_BASE_LEN);
1312  if(arg_ns[0] != '\0') {
1313  roxml_write_string(buf, f, arg_ns, offset, len);
1314  roxml_write_string(buf, f, ":", offset, len);
1315  }
1316  }
1317  roxml_write_string(buf, f, arg, offset, len);
1318  roxml_write_string(buf, f, "=\"", offset, len);
1319  roxml_write_string(buf, f, value, offset, len);
1320  roxml_write_string(buf, f, "\"", offset, len);
1321  attr = attr->sibl;
1322  roxml_release(value);
1323  }
1324  if(n->chld) {
1325  node_t *chld = n->chld;
1326  if(n->prnt) {
1327  roxml_write_string(buf, f, ">", offset, len);
1328  if(human) {
1329  roxml_write_string(buf, f, "\n", offset, len);
1330  }
1331  }
1332  while(chld) {
1333  char val[ROXML_LONG_LEN];
1334  if(chld->type & ROXML_TXT_NODE) {
1335  char *value;
1336  int status;
1337  if(human) {
1338  roxml_print_space(f, buf, offset, len, lvl+1);
1339  }
1340  value = roxml_get_content(chld, val, ROXML_LONG_LEN, &status);
1341  if(status >= ROXML_LONG_LEN) {
1342  value = roxml_get_content(chld, NULL, 0, &status);
1343  }
1344  if((chld->type & ROXML_CDATA_NODE) == ROXML_CDATA_NODE) {
1345  roxml_write_string(buf, f, "<![CDATA[", offset, len);
1346  roxml_write_string(buf, f, value, offset, len);
1347  roxml_write_string(buf, f, "]]>", offset, len);
1348  } else {
1349  char * end = value + status - 2;
1350  char * strip = value;
1351  while(roxml_is_separator(end[0])) {
1352  end[0] = '\0';
1353  end--;
1354  }
1355  while(roxml_is_separator(strip[0])) {
1356  strip++;
1357  }
1358 
1359  roxml_write_string(buf, f, strip, offset, len);
1360  }
1361  if(human) {
1362  roxml_write_string(buf, f, "\n", offset, len);
1363  }
1364  chld = chld->sibl;
1365  roxml_release(value);
1366  } else {
1367  roxml_write_node(chld, f, buf, human, lvl+1, offset, len);
1368  chld = chld->sibl;
1369  }
1370  }
1371  if(n->prnt) {
1372  if(human) {
1373  roxml_print_space(f, buf, offset, len, lvl);
1374  }
1375  roxml_write_string(buf, f, "</", offset, len);
1376  if(n->ns) {
1377  if(ns[0] != '\0') {
1378  roxml_write_string(buf, f, ns, offset, len);
1379  roxml_write_string(buf, f, ":", offset, len);
1380  }
1381  }
1382  roxml_write_string(buf, f, name, offset, len);
1383  roxml_write_string(buf, f, ">", offset, len);
1384  if(human) {
1385  roxml_write_string(buf, f, "\n", offset, len);
1386  }
1387  }
1388  } else {
1389  roxml_write_string(buf, f, "/>", offset, len);
1390  if(human) {
1391  roxml_write_string(buf, f, "\n", offset, len);
1392  }
1393  }
1394  } else {
1395  char *name;
1396  char *value;
1397  int status;
1398  char val[ROXML_LONG_LEN];
1399  char head[8];
1400  char tail[8];
1401 
1402  if((n->type & ROXML_NODE_TYPES) == ROXML_CMT_NODE) {
1403  strcpy(head, "<!--");
1404  strcpy(tail, "-->");
1405  } else if((n->type & ROXML_NODE_TYPES) == ROXML_DOCTYPE_NODE) {
1406  strcpy(head, "<");
1407  strcpy(tail, ">");
1408  } else if((n->type & ROXML_NODE_TYPES) == ROXML_PI_NODE) {
1409  strcpy(head, "<?");
1410  strcpy(tail, "?>");
1411  }
1412 
1413  roxml_write_string(buf, f, head, offset, len);
1414 
1415  name = roxml_get_name(n, val, ROXML_LONG_LEN);
1416  if(name[0]) {
1417  roxml_write_string(buf, f, name, offset, len);
1418  } else {
1419  name = NULL;
1420  }
1421 
1422  value = roxml_get_content(n, val, ROXML_LONG_LEN, &status);
1423  if(status >= ROXML_LONG_LEN) {
1424  value = roxml_get_content(n, NULL, 0, &status);
1425  }
1426  if(name && value && value[0]) {
1427  roxml_write_string(buf, f, " ", offset, len);
1428  }
1429  roxml_write_string(buf, f, value, offset, len);
1430  roxml_release(value);
1431 
1432  roxml_write_string(buf, f, tail, offset, len);
1433 
1434  if(human) {
1435  roxml_write_string(buf, f, "\n", offset, len);
1436  }
1437  }
1438 }
1439 
1441 {
1442  node_t * attr = NULL;
1443  node_t * chld = NULL;
1444 
1445  if(!n) {
1446  return;
1447  }
1448 
1449  if(n->ns == ns) {
1450  if(n->prnt) {
1451  n->ns = n->prnt->ns;
1452  } else {
1453  n->ns = NULL;
1454  }
1455  }
1456 
1457  chld = n->chld;
1458  while(chld) {
1459  roxml_reset_ns(chld, ns);
1460  chld = chld->sibl;
1461  }
1462 
1463  attr = n->attr;
1464  while(attr) {
1465  if((attr->type & ROXML_NS_NODE) == 0) {
1466  if(attr->ns == ns) {
1467  attr->ns = attr->prnt->ns;
1468  }
1469  }
1470  attr = attr->sibl;
1471  }
1472 }
1473 
1475 {
1476  node_t *current = n->prnt->attr;
1477 
1478  if(n->type & ROXML_NS_NODE) {
1479  roxml_reset_ns(n->prnt, n);
1480  }
1481 
1482  if(current == n) {
1483  n->prnt->attr = n->sibl;
1484  } else if(current) {
1485  while(current->sibl && current->sibl != n) {
1486  current = current->sibl;
1487  }
1488  current->sibl = n->sibl;
1489  }
1490  roxml_del_tree(n->chld);
1491  return;
1492 }
1493 
1495 {
1496  node_t *current = n->prnt->chld;
1497  while(current && (current->type & ROXML_TXT_NODE) == 0) {
1498  current = current->sibl;
1499  }
1500  if(n->prnt && n->prnt->next == n) {
1501  n->prnt->next = n->sibl;
1502  }
1503  if(current == n) {
1504  n->prnt->chld = n->sibl;
1505  } else if(current) {
1506  while(current->sibl && current->sibl != n) {
1507  current = current->sibl;
1508  }
1509  current->sibl = n->sibl;
1510  }
1511 
1512 }
1513 
1515 {
1516  node_t *current = n->prnt->chld;
1517  if(n->prnt && n->prnt->next == n) {
1518  n->prnt->next = n->sibl;
1519  }
1520  if(current == n) {
1521  n->prnt->chld = n->sibl;
1522  } else if(current) {
1523  while(current->sibl && current->sibl != n) {
1524  current = current->sibl;
1525  }
1526  current->sibl = n->sibl;
1527  }
1528  roxml_del_tree(n->chld);
1529  roxml_del_tree(n->attr);
1530 }
1531 
1532 void roxml_compute_and(node_t * root, node_t **node_set, int *count, int cur_req_id, int prev_req_id)
1533 {
1534  int i = 0;
1535  for(i = 0; i < *count; i++) {
1536  if((!roxml_in_pool(root, node_set[i], cur_req_id)) || (!roxml_in_pool(root, node_set[i], prev_req_id))) {
1537  (*count)--;
1538  roxml_del_from_pool(root, node_set[i], cur_req_id);
1539  roxml_del_from_pool(root, node_set[i], prev_req_id);
1540  if(*count > 0) {
1541  node_set[i] = node_set[(*count)-1];
1542  }
1543  }
1544  }
1545 }
1546 
1547 void roxml_compute_or(node_t * root, node_t **node_set, int *count, int req_id, int glob_id)
1548 {
1549  int i = 0;
1550  for(i = 0; i < *count; i++) {
1551  if(roxml_in_pool(root, node_set[i], req_id)) {
1552  roxml_add_to_pool(root, node_set[i], glob_id);
1553  roxml_del_from_pool(root, node_set[i], req_id);
1554  }
1555  }
1556 }
1557 
1558 
1559 node_t ** roxml_exec_xpath(node_t *root, node_t *n, xpath_node_t *xpath, int index, int * count)
1560 {
1561  int path_id;
1562  int max_answers = 1;
1563  int glob_id = 0;
1564  int * req_ids = NULL;
1565 
1566  node_t **node_set = roxml_malloc(sizeof(node_t*), max_answers, PTR_NODE_RESULT);
1567 
1568  *count = 0;
1569  req_ids = calloc(index, sizeof(int));
1570  glob_id = roxml_request_id(root);
1571 
1572  // process all and xpath
1573  for(path_id = 0; path_id < index; path_id++) {
1574  xpath_node_t *cur_xpath = NULL;
1575  xpath_node_t *next_xpath = NULL;
1576  cur_xpath = &xpath[path_id];
1577  if(path_id < index-1) { next_xpath = &xpath[path_id+1]; }
1578 
1579  if((cur_xpath->rel == ROXML_OPERATOR_AND)||((next_xpath) && (next_xpath->rel == ROXML_OPERATOR_AND))) {
1580  int req_id = roxml_request_id(root);
1581 
1582  node_t *orig = n;
1583  if(cur_xpath->abs) {
1584  // context node is root
1585  orig = root;
1586  }
1587  // assign a new request ID
1588  roxml_check_node(cur_xpath, root, orig, &node_set, count, &max_answers, ROXML_DIRECT, req_id);
1589 
1590  if(cur_xpath->rel == ROXML_OPERATOR_AND) {
1591  roxml_compute_and(root, node_set, count, req_id, req_ids[path_id-1]);
1592  }
1593  req_ids[path_id] = req_id;
1594  }
1595  }
1596 
1597  // process all or xpath
1598  for(path_id = 0; path_id < index; path_id++) {
1599  node_t *orig = n;
1600  xpath_node_t *cur_xpath = &xpath[path_id];
1601 
1602  if(cur_xpath->rel == ROXML_OPERATOR_OR) {
1603  if(req_ids[path_id] == 0) {
1604  if(cur_xpath->abs) {
1605  // context node is root
1606  orig = root;
1607  }
1608  // assign a new request ID
1609  roxml_check_node(cur_xpath, root, orig, &node_set, count, &max_answers, ROXML_DIRECT, glob_id);
1610  } else {
1611  roxml_compute_or(root, node_set, count, req_ids[path_id+1], glob_id);
1612  roxml_release_id(root, node_set, *count, req_ids[path_id+1]);
1613  }
1614  }
1615  }
1616  roxml_release_id(root, node_set, *count, glob_id);
1617 
1618  for(path_id = 0; path_id < index; path_id++) {
1619  if(req_ids[path_id] != 0) {
1620  roxml_release_id(root, node_set, *count, req_ids[path_id]);
1621  }
1622  }
1623 
1624  free(req_ids);
1625 
1626  return node_set;
1627 }
1628