<libroxml  version="3.0.2" />
contact: tristan.lelong@libroxml.net
roxml_parser.c
Go to the documentation of this file.
1
12#include <stdlib.h>
13#include <string.h>
14#include "roxml_parser.h"
15
16/* #define DEBUG_PARSING */
17#define ROXML_PARSER_NCELLS 256
18#define ROXML_PARSER_NCELLS_MAX 512
19
20#define ROXML_PARSER_ITEM(parser, item) (parser + item)
21
22ROXML_INT int roxml_parser_multiple(roxml_parser_item_t *parser, char *chunk, void *data)
23{
24 roxml_parser_item_t *item = ROXML_PARSER_ITEM(parser, *chunk)->next;
25
26 /* collision can only occurs on callbacks
27 * that verify the chunk value so we can
28 * just call all cb in turns */
29 while (item) {
30 int ret = item->func(parser, chunk, data);
31
32 if (ret > 0)
33 return ret;
34 else if (ret < 0)
35 return -1;
36 item = item->next;
37 }
38 return 0;
39}
40
41ROXML_INT roxml_parser_item_t *roxml_append_parser_item(roxml_parser_item_t *parser, char *key, roxml_parse_func func)
42{
43 if (!parser)
44 parser = roxml_parser_allocate();
45
46 if (!ROXML_PARSER_ITEM(parser, *key)->func) {
47 /* first callback registered */
48 ROXML_PARSER_ITEM(parser, *key)->func = func;
49 } else if (!ROXML_PARSER_ITEM(parser, *key)->next){
50 /* second callback registered:
51 * 1) find free cells in collision pool
52 * 2) initialize cells
53 * 3) enable multiple callbacks.
54 */
55 roxml_parser_item_t *collision = parser + ROXML_PARSER_NCELLS;
56
57 while (collision->func)
58 collision++;
59
60 /* relocate existing callback in collision pool */
61 ROXML_PARSER_ITEM(parser, *key)->next = collision;
62 collision->func = ROXML_PARSER_ITEM(parser, *key)->func;
63 collision->next = collision + 1;
64
65 /* next available callback is right after (since we do not free single entries) */
66 collision++;
67 collision->func = func;
68 collision->next = NULL;
69
70 ROXML_PARSER_ITEM(parser, *key)->func = roxml_parser_multiple;
71 } else {
72 /* third or more callback registered: just append */
74 roxml_parser_item_t *collision = ROXML_PARSER_ITEM(parser, *key);
75 while (collision->next)
76 collision = collision->next;
77 last = collision;
78 while (collision->func)
79 collision++;
80 last->next = collision;
81 collision->func = func;
82 collision->next = NULL;
83 }
84
85 return parser;
86}
87
89{
90 roxml_parser_item_t *parser;
91
92 /* allocate a new parser.
93 * 512 cells allow up to 256 collisions. */
94 parser = malloc(sizeof(roxml_parser_item_t) * ROXML_PARSER_NCELLS_MAX);
95 memset(parser, 0 , sizeof(roxml_parser_item_t) * ROXML_PARSER_NCELLS_MAX);
96
97 return parser;
98}
99
101{
102 free(parser);
103}
104
106{
107 int i;
109 roxml_parser_item_t *collision;
110
111 new = roxml_parser_allocate();
112 collision = new + ROXML_PARSER_NCELLS;
113
114 for (i = 0; i < ROXML_PARSER_NCELLS; i++) {
115 /* copy parser and assign default */
116 if (parser[i].func) {
117 new[i].func = parser[i].func;
118
119 if (parser[i].next) {
120 roxml_parser_item_t *item = parser[i].next;
121
122 new[i].next = collision;
123
124 /* group all collision callbacks in collision pool */
125 while (1) {
126 collision->func = item->func;
127
128 if (item->next)
129 collision->next = collision + 1;
130 else
131 break;
132
133 collision = collision->next;
134 item = item->next;
135 }
136 collision++;
137 }
138 } else {
139 new[i].func = parser[0].func;
140 new[i].next = parser[0].next;
141 }
142 }
143
144 roxml_parser_free(parser);
145
146 return new;
147}
148
149ROXML_INT int roxml_parse_line(roxml_parser_item_t *parser, char *line, int len, void *ctx)
150{
151 char *line_end = line;
152 char *chunk = line;
153
154 if (len > 0)
155 line_end = line + len;
156 else
157 line_end = line + strlen(line);
158
159 while (chunk < line_end) {
160 /* main callbacks */
161 int ret = ROXML_PARSER_ITEM(parser, *chunk)->func(parser, chunk, ctx);
162
163 if (ret > 0) {
164 chunk += ret;
165 continue;
166 } else if (ret < 0) {
167 return ret;
168 }
169
170 /* default callbacks */
171 ret = ROXML_PARSER_ITEM(parser, 0)->func(parser, chunk, ctx);
172
173 if (ret > 0) {
174 chunk += ret;
175 continue;
176 } else if (ret < 0) {
177 return ret;
178 }
179 }
180
181 return (chunk - line);
182}
ROXML_INT int roxml_parse_line(roxml_parser_item_t *parser, char *line, int len, void *ctx)
line parsing function
ROXML_INT roxml_parser_item_t * roxml_parser_prepare(roxml_parser_item_t *parser)
parser preparation function
ROXML_INT roxml_parser_item_t * roxml_parser_allocate(void)
parser table allocation
ROXML_INT roxml_parser_item_t * roxml_append_parser_item(roxml_parser_item_t *parser, char *key, roxml_parse_func func)
parser item creation function
ROXML_INT void roxml_parser_free(roxml_parser_item_t *parser)
parser table deletion
Parsing engine.
the parser item struct