<libroxml  version="3.0.2" />
contact: tristan.lelong@libroxml.net
roxml_content.c
Go to the documentation of this file.
1 
12 #include <string.h>
13 #include <stdlib.h>
14 #include "roxml_mem.h"
15 #include "roxml_file.h"
16 #include "roxml_buff.h"
17 
19  char code;
20  char *escape;
21 };
22 
23 struct roxml_escape_char specials[5] = {
24  { .code = '"', .escape = "&quot;" },
25  { .code = '\'', .escape = "&apos;" },
26  { .code = '<', .escape = "&lt;"},
27  { .code = '>', .escape = "&gt;"},
28  { .code = '&', .escape = "&amp;"}
29 };
30 
31 ROXML_API int roxml_escape(const char *buf, int decode, char *out)
32 {
33  size_t i = 0;
34  size_t l = 0;
35  for (; i < strlen(buf); ) {
36  int s = 0;
37  for (; s < 5; s++) {
38  if (decode && (strncmp(specials[s].escape, buf+i, strlen(specials[s].escape)) == 0)) {
39  if (out)
40  out[l] = specials[s].code;
41  l += 1;
42  i += strlen(specials[s].escape);
43  break;
44  } else if (!decode && (buf[i] == specials[s].code)) {
45  if (out)
46  strcpy(out+l, specials[s].escape);
47  l += strlen(specials[s].escape);
48  i += 1;
49  break;
50  }
51  }
52  if (s == 5) {
53  if (out)
54  out[l] = buf[i];
55  l += 1;
56  i += 1;
57  }
58  }
59  if (out)
60  out[l] = '\0';
61  return l;
62 }
63 
74 ROXML_STATIC ROXML_INT inline int roxml_read(int pos, int size, char *buffer, node_t *node)
75 {
76  int len = 0;
77 
78  if (size > 0 && buffer) {
79  if (node->type & ROXML_FILE)
80  len = roxml_read_file(pos, size, buffer, node);
81  else
82  len = roxml_read_buff(pos, size, buffer, node);
83  }
84 
85  return len;
86 }
87 
88 ROXML_STATIC ROXML_INT inline int roxml_content_size(node_t *n, int *offset)
89 {
90  int total = 0;
91 
92  *offset = 0;
93 
94  if (!n)
95  return 0;
96 
97  if (n->type & ROXML_ELM_NODE) {
98  node_t *ptr = n->chld;
99  while (ptr) {
100  if ((ptr->type & ROXML_NODE_TYPES) == ROXML_TXT_NODE)
101  total += ptr->end - ptr->pos;
102  ptr = ptr->sibl;
103  }
104  } else if (n->type & ROXML_ATTR_NODE) {
105  if (n->chld) {
106  total = n->chld->end - n->chld->pos;
107  *offset = n->chld->pos;
108  }
109  } else {
110  int name_len = 0;
111 
112  ROXML_GET_BASE_BUFFER(name);
113 
114  roxml_get_name(n, name, ROXML_BASE_LEN);
115  name_len = strlen(name);
116 
117  ROXML_PUT_BASE_BUFFER(name);
118 
119  if (n->type & ROXML_DOCTYPE_NODE)
120  name_len += 2;
121  else if (n->type & ROXML_TXT_NODE)
122  name_len = 0;
123  else if (n->type & ROXML_CMT_NODE)
124  name_len = 4;
125  else if (n->type & ROXML_PI_NODE)
126  name_len += 3;
127 
128  total = n->end - n->pos - name_len;
129  *offset = n->pos + name_len;
130  }
131  return total;
132 }
133 
134 ROXML_STATIC ROXML_INT inline char *roxml_prepare_buffer(node_t *n, char *buffer, int contentsize, int size)
135 {
136  if (n == NULL) {
137  if (buffer)
138  memset(buffer, 0, size);
139  return NULL;
140  }
141  if (buffer == NULL)
142  buffer = roxml_malloc(sizeof(char), contentsize + 1, PTR_CHAR);
143  memset(buffer, 0, size);
144 
145  return buffer;
146 }
147 
148 ROXML_API char *roxml_get_content(node_t *n, char *buffer, int bufsize, int *size)
149 {
150  int total = 0;
151  int content_offset;
152  int content_size;
153  char *content;
154 
155  if (n == ROXML_INVALID_DOC)
156  return NULL;
157 
158  content_size = roxml_content_size(n, &content_offset);
159  content = roxml_prepare_buffer(n, buffer, content_size, bufsize);
160 
161  if (buffer != content)
162  bufsize = content_size + 1;
163  if (content_size > bufsize - 1)
164  content_size = bufsize - 1;
165  if (content == NULL) {
166  if (size)
167  *size = 0;
168  return buffer;
169  }
170 
171  if (n->type & ROXML_ELM_NODE) {
172  node_t *ptr = n->chld;
173 
174  while (ptr) {
175  if (ptr->type & ROXML_TXT_NODE) {
176  int len = 0;
177  int read_size = ptr->end - ptr->pos;
178 
179  if (total + read_size > bufsize - 1)
180  read_size = bufsize - total - 1;
181  len += roxml_read(ptr->pos, read_size, content + total, ptr);
182 
183  total += len;
184  }
185  ptr = ptr->sibl;
186  }
187  } else {
188  node_t *target = n;
189  if (n->type & ROXML_ATTR_NODE)
190  target = n->chld;
191  total = roxml_read(content_offset, content_size, content, target);
192  }
193 
194  content[total] = '\0';
195  if (size)
196  *size = total + 1;
197  return content;
198 }
199 
200 ROXML_STATIC ROXML_INT inline int roxml_name_size(node_t *n, int size, int *offset)
201 {
202  int total = 0;
203 
204  *offset = 0;
205 
206  if (!n)
207  return 0;
208 
209  if ((n->type & ROXML_TXT_NODE) || (n->type & ROXML_CMT_NODE)) {
210  total = 0;
211  } else {
212  *offset = n->pos;
213 
214  if (n->type & ROXML_PI_NODE)
215  *offset += 2;
216  else if (n->type & ROXML_DOCTYPE_NODE)
217  *offset += 1;
218 
219  total = ROXML_BASE_LEN;
220  }
221 
222  return total;
223 }
224 
225 ROXML_API char *roxml_get_name(node_t *n, char *buffer, int size)
226 {
227  int content_offset;
228  int content_size;
229  char *content;
230 
231  if (n == ROXML_INVALID_DOC)
232  return NULL;
233 
234  content_size = roxml_name_size(n, size, &content_offset);
235  content = roxml_prepare_buffer(n, buffer, content_size, size);
236 
237  if (buffer != content)
238  size = content_size + 1;
239  if (content_size > size - 1)
240  content_size = size - 1;
241  if (content == NULL)
242  return buffer;
243  if (content_size == 0)
244  return content;
245 
246  memset(content, 0, content_size);
247 
248  if (n->prnt == NULL) {
249  strcpy(content, "documentRoot");
250  } else if (n->type & ROXML_NS_NODE) {
251  roxml_ns_t *ns = (roxml_ns_t *)n->priv;
252  if (ns)
253  strncpy(content, ns->alias, size);
254  else
255  content[0] = '\0';
256  } else {
257  int total = 0;
258  int count = 0;
259  char *begin = content;
260 
261  total = roxml_read(content_offset, content_size, content, n);
262 
263  while (ROXML_WHITE(begin[0]) || begin[0] == '<')
264  begin++;
265 
266  if (n->type & ROXML_PI_NODE) {
267  for (; count < total; count++) {
268  if (ROXML_WHITE(begin[count]))
269  break;
270  else if ((begin[count] == '?') && (begin[count + 1] == '>'))
271  break;
272  }
273  } else if (n->type & ROXML_ELM_NODE) {
274  for (; count < total; count++) {
275  if (ROXML_WHITE(begin[count]))
276  break;
277  else if ((begin[count] == '/') && (begin[count + 1] == '>'))
278  break;
279  else if (begin[count] == '>')
280  break;
281  }
282  } else if (n->type & ROXML_ATTR_NODE) {
283  for (; count < total; count++) {
284  if (ROXML_WHITE(begin[count]))
285  break;
286  else if (begin[count] == '=')
287  break;
288  else if (begin[count] == '>')
289  break;
290  else if ((begin[count] == '/') && (begin[count + 1] == '>'))
291  break;
292  }
293  } else if (n->type & ROXML_DOCTYPE_NODE) {
294  for (; count < total; count++) {
295  if (ROXML_WHITE(begin[count]))
296  break;
297  else if (begin[count] == '>')
298  break;
299  }
300  }
301  begin[count++] = '\0';
302  memmove(content, begin, count);
303  }
304 
305  return content;
306 }
307 
309 {
310  node_t *ptr = n;
311  int nb;
312 
313  if (n == ROXML_INVALID_DOC)
314  return -1;
315 
316  nb = 0;
317  if (ptr->chld) {
318  ptr = ptr->chld;
319  do {
320  if (ptr->type & type)
321  nb++;
322  ptr = ptr->sibl;
323  } while (ptr);
324  }
325 
326  if (type & ROXML_ATTR_NODE) {
327  ptr = n->attr;
328  while (ptr) {
329  nb++;
330  ptr = ptr->sibl;
331  }
332  }
333  return nb;
334 }
335 
336 ROXML_STATIC ROXML_INT inline node_t *roxml_get_nodes_by_name(node_t *n, int type, char *name)
337 {
338  node_t *ptr;
339 
340  if (n->attr && (type & ROXML_ATTR_NODE))
341  ptr = n->attr;
342  else
343  ptr = n->chld;
344 
345  while (ptr) {
346  if ((ptr->type & ROXML_NODE_TYPES) & type) {
347  int ans = strcmp(roxml_get_name(ptr, NULL, 0), name);
349  if (ans == 0)
350  return ptr;
351  }
352  ptr = ptr->sibl;
353  }
354  return NULL;
355 }
356 
357 ROXML_STATIC ROXML_INT inline node_t *roxml_get_nodes_by_nth(node_t *n, int type, int nth)
358 {
359  node_t *ptr;
360  int count = 0;
361 
362  if (n->ns && (type & ROXML_NS_NODE)) {
363  ptr = n->ns;
364  if (nth == 0)
365  return ptr;
366  } else if (n->attr && (type & ROXML_ATTR_NODE)) {
367  ptr = n->attr;
368  if (nth == 0)
369  return ptr;
370  while ((ptr->sibl) && (nth > count)) {
371  ptr = ptr->sibl;
372  count++;
373  }
374  } else {
375  ptr = n->chld;
376  while (ptr && !((ptr->type & ROXML_NODE_TYPES) & type))
377  ptr = ptr->sibl;
378  }
379  if (nth > count) {
380  ptr = n->chld;
381  while (ptr && !((ptr->type & ROXML_NODE_TYPES) & type))
382  ptr = ptr->sibl;
383  while (ptr && (ptr->sibl) && (nth > count)) {
384  ptr = ptr->sibl;
385  if ((ptr->type & ROXML_NODE_TYPES) & type)
386  count++;
387  }
388  }
389  if (nth > count)
390  return NULL;
391  return ptr;
392 }
393 
394 ROXML_API node_t *roxml_get_nodes(node_t *n, int type, char *name, int nth)
395 {
396  if (n == ROXML_INVALID_DOC)
397  return ROXML_INVALID_DOC;
398  else if (name == NULL)
399  return roxml_get_nodes_by_nth(n, type, nth);
400  else
401  return roxml_get_nodes_by_name(n, type, name);
402 }
403 
405 {
406  return roxml_get_nodes(n, ROXML_NS_NODE, NULL, 0);
407 }
408 
410 {
412 }
413 
414 ROXML_API inline node_t *roxml_get_pi(node_t *n, int nth)
415 {
416  return roxml_get_nodes(n, ROXML_PI_NODE, NULL, nth);
417 }
418 
420 {
422 }
423 
424 ROXML_API inline node_t *roxml_get_cmt(node_t *n, int nth)
425 {
426  return roxml_get_nodes(n, ROXML_CMT_NODE, NULL, nth);
427 }
428 
430 {
432 }
433 
434 ROXML_API inline node_t *roxml_get_txt(node_t *n, int nth)
435 {
436  return roxml_get_nodes(n, ROXML_TXT_NODE, NULL, nth);
437 }
438 
440 {
442 }
443 
444 ROXML_API inline node_t *roxml_get_attr(node_t *n, char *name, int nth)
445 {
446  return roxml_get_nodes(n, ROXML_ATTR_NODE, name, nth);
447 }
448 
450 {
452 }
453 
454 ROXML_API inline node_t *roxml_get_chld(node_t *n, char *name, int nth)
455 {
456  return roxml_get_nodes(n, ROXML_ELM_NODE, name, nth);
457 }
458 
460 {
461  if (n == ROXML_INVALID_DOC)
462  return ROXML_INVALID_NODE;
463  return (n->type & ROXML_NODE_TYPES);
464 }
465 
467 {
468  int idx = 1;
469  char name[256];
470  node_t *prnt;
471  node_t *first;
472 
473  if (n == ROXML_INVALID_DOC)
474  return 0;
475 
476  roxml_get_name(n, name, 256);
477 
478  prnt = n->prnt;
479  if (!prnt)
480  return 1;
481  first = prnt->chld;
482 
483  while ((first) && (first != n)) {
484  char twin[256];
485 
486  roxml_get_name(first, twin, 256);
487  if (strcmp(name, twin) == 0)
488  idx++;
489  first = first->sibl;
490  }
491 
492  return idx;
493 }
#define ROXML_FILE
ROXML_API node_t * roxml_get_ns(node_t *n)
namespace getter function
#define ROXML_INVALID_DOC
Definition: roxml.h:235
ROXML_API int roxml_get_cmt_nb(node_t *n)
comments number getter function
#define ROXML_NS_NODE
Definition: roxml.h:102
ROXML_API node_t * roxml_get_txt(node_t *n, int nth)
text node getter function
node_t structure
Definition: roxml_types.h:133
ROXML_API int roxml_get_nodes_nb(node_t *n, int type)
number of nodes getter function
ROXML_API int roxml_get_chld_nb(node_t *n)
chlds number getter function
ROXML_API void roxml_release(void *data)
memory cleanning function
Definition: roxml_mem.c:109
struct node * attr
Definition: roxml_types.h:145
ROXML_INT int roxml_read_buff(int pos, int size, char *buffer, node_t *node)
read xml doc function
Definition: roxml_buff.c:16
#define ROXML_ATTR_NODE
Definition: roxml.h:51
#define RELEASE_LAST
Definition: roxml.h:228
roxml_pos_t end
Definition: roxml_types.h:141
#define ROXML_INVALID_NODE
Definition: roxml.h:43
ROXML_API node_t * roxml_get_attr(node_t *n, char *name, int nth)
attribute getter function
#define ROXML_PI_NODE
Definition: roxml.h:94
struct node * chld
Definition: roxml_types.h:143
ROXML_API int roxml_get_txt_nb(node_t *n)
text node number getter function
ROXML_STATIC ROXML_INT int roxml_read(int pos, int size, char *buffer, node_t *node)
read xml doc function
Definition: roxml_content.c:74
char * alias
Definition: roxml_types.h:122
#define ROXML_API
Definition: roxml.h:24
#define ROXML_DOCTYPE_NODE
Definition: roxml.h:134
ROXML_INT int roxml_read_file(int pos, int size, char *buffer, node_t *node)
read xml doc function
Definition: roxml_file.c:18
ROXML_API int roxml_escape(const char *buf, int decode, char *out)
XML encoding/decoding function.
Definition: roxml_content.c:31
struct node * sibl
Definition: roxml_types.h:142
File XML document backend.
#define ROXML_CMT_NODE
Definition: roxml.h:86
ROXML_API node_t * roxml_get_cmt(node_t *n, int nth)
comment getter function
roxml_pos_t pos
Definition: roxml_types.h:140
ROXML_API node_t * roxml_get_nodes(node_t *n, int type, char *name, int nth)
nodes getter function
struct node * ns
Definition: roxml_types.h:147
namespace structure
Definition: roxml_types.h:119
ROXML_API char * roxml_get_content(node_t *n, char *buffer, int bufsize, int *size)
content getter function
#define ROXML_ELM_NODE
Definition: roxml.h:70
XML internal memory management module.
ROXML_API int roxml_get_type(node_t *n)
node type function
ROXML_API node_t * roxml_get_chld(node_t *n, char *name, int nth)
chld getter function
void * priv
Definition: roxml_types.h:148
struct node * prnt
Definition: roxml_types.h:144
#define ROXML_WHITE(n)
#define ROXML_BASE_LEN
Definition: roxml_defines.h:91
ROXML_API node_t * roxml_get_pi(node_t *n, int nth)
process-instruction getter function
#define ROXML_NODE_TYPES
Definition: roxml.h:158
ROXML_API int roxml_get_pi_nb(node_t *n)
process-instruction number getter function
#define ROXML_TXT_NODE
Definition: roxml.h:78
unsigned short type
Definition: roxml_types.h:134
#define PTR_CHAR
ROXML_API char * roxml_get_name(node_t *n, char *buffer, int size)
name getter function
buffer XML document backend
ROXML_INT void * roxml_malloc(int size, int num, int type)
alloc memory function
Definition: roxml_mem.c:124
ROXML_API int roxml_get_attr_nb(node_t *n)
number of attribute getter function
ROXML_API int roxml_get_node_position(node_t *n)
node get position function