Skip to content

Commit 192ad59

Browse files
xml.c:
new file
1 parent 492eba0 commit 192ad59

1 file changed

Lines changed: 374 additions & 0 deletions

File tree

strings/xml.c

Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
/* Copyright (C) 2000 MySQL AB
2+
3+
This program is free software; you can redistribute it and/or modify
4+
it under the terms of the GNU General Public License as published by
5+
the Free Software Foundation; either version 2 of the License, or
6+
(at your option) any later version.
7+
8+
This program is distributed in the hope that it will be useful,
9+
but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
GNU General Public License for more details.
12+
13+
You should have received a copy of the GNU General Public License
14+
along with this program; if not, write to the Free Software
15+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16+
17+
#include "my_global.h"
18+
#include "m_string.h"
19+
#include "my_xml.h"
20+
21+
22+
#define MY_XML_EOF 'E'
23+
#define MY_XML_STRING 'S'
24+
#define MY_XML_IDENT 'I'
25+
#define MY_XML_EQ '='
26+
#define MY_XML_LT '<'
27+
#define MY_XML_GT '>'
28+
#define MY_XML_SLASH '/'
29+
#define MY_XML_COMMENT 'C'
30+
#define MY_XML_TEXT 'T'
31+
#define MY_XML_QUESTION '?'
32+
#define MY_XML_EXCLAM '!'
33+
34+
typedef struct xml_attr_st
35+
{
36+
const char *beg;
37+
const char *end;
38+
} MY_XML_ATTR;
39+
40+
static const char *lex2str(int lex)
41+
{
42+
switch(lex)
43+
{
44+
case MY_XML_EOF: return "EOF";
45+
case MY_XML_STRING: return "STRING";
46+
case MY_XML_IDENT: return "IDENT";
47+
case MY_XML_EQ: return "'='";
48+
case MY_XML_LT: return "'<'";
49+
case MY_XML_GT: return "'>'";
50+
case MY_XML_SLASH: return "'/'";
51+
case MY_XML_COMMENT: return "COMMENT";
52+
case MY_XML_TEXT: return "TEXT";
53+
case MY_XML_QUESTION: return "'?'";
54+
case MY_XML_EXCLAM: return "'!'";
55+
}
56+
return "UNKNOWN";
57+
}
58+
59+
static void my_xml_norm_text(MY_XML_ATTR *a)
60+
{
61+
for ( ; (a->beg < a->end) && strchr(" \t\r\n",a->beg[0]) ; a->beg++ );
62+
for ( ; (a->beg < a->end) && strchr(" \t\r\n",a->end[-1]) ; a->end-- );
63+
}
64+
65+
66+
static int my_xml_scan(MY_XML_PARSER *p,MY_XML_ATTR *a)
67+
{
68+
int lex;
69+
70+
for( ; ( p->cur < p->end) && strchr(" \t\r\n",p->cur[0]) ; p->cur++);
71+
72+
if (p->cur >= p->end)
73+
{
74+
a->beg=p->end;
75+
a->end=p->end;
76+
lex=MY_XML_EOF;
77+
goto ret;
78+
}
79+
80+
a->beg=p->cur;
81+
a->end=p->cur;
82+
83+
if (!memcmp(p->cur,"<!--",4))
84+
{
85+
for( ; (p->cur < p->end) && memcmp(p->cur, "-->", 3); p->cur++);
86+
if(!memcmp(p->cur, "-->", 3))
87+
p->cur+=3;
88+
a->end=p->cur;
89+
lex=MY_XML_COMMENT;
90+
}
91+
else if (strchr("?=/<>!",p->cur[0]))
92+
{
93+
p->cur++;
94+
a->end=p->cur;
95+
lex=a->beg[0];
96+
}
97+
else if ( (p->cur[0]=='"') || (p->cur[0]=='\'') )
98+
{
99+
p->cur++;
100+
for( ; ( p->cur < p->end ) && (p->cur[0]!=a->beg[0]); p->cur++);
101+
a->end=p->cur;
102+
if (a->beg[0]==p->cur[0])p->cur++;
103+
a->beg++;
104+
my_xml_norm_text(a);
105+
lex=MY_XML_STRING;
106+
}
107+
else
108+
{
109+
for( ; (p->cur < p->end) && !strchr("?'\"=/<> \t\r\n", p->cur[0]); p->cur++);
110+
a->end=p->cur;
111+
my_xml_norm_text(a);
112+
lex=MY_XML_IDENT;
113+
}
114+
115+
#if 0
116+
printf("LEX=%s[%d]\n",lex2str(lex),a->end-a->beg);
117+
#endif
118+
119+
ret:
120+
return lex;
121+
}
122+
123+
124+
static int my_xml_value(MY_XML_PARSER *st, const char *str, uint len)
125+
{
126+
return (st->value) ? (st->value)(st,str,len) : MY_XML_OK;
127+
}
128+
129+
130+
static int my_xml_enter(MY_XML_PARSER *st, const char *str, uint len)
131+
{
132+
if ( (st->attrend-st->attr+len+1)>sizeof(st->attr))
133+
{
134+
sprintf(st->errstr,"To deep XML");
135+
return MY_XML_ERROR;
136+
}
137+
if (st->attrend > st->attr)
138+
{
139+
st->attrend[0]='.';
140+
st->attrend++;
141+
}
142+
memcpy(st->attrend,str,len);
143+
st->attrend+=len;
144+
st->attrend[0]='\0';
145+
return st->enter ? st->enter(st,st->attr,st->attrend-st->attr) : MY_XML_OK;
146+
}
147+
148+
static void mstr(char *s,const char *src,uint l1, uint l2)
149+
{
150+
l1 = l1<l2 ? l1 : l2;
151+
memcpy(s,src,l1);
152+
s[l1]='\0';
153+
}
154+
155+
static int my_xml_leave(MY_XML_PARSER *p, const char *str, uint slen)
156+
{
157+
char *e;
158+
uint glen;
159+
char s[32];
160+
char g[32];
161+
int rc;
162+
163+
/* Find previous '.' or beginning */
164+
for( e=p->attrend; (e>p->attr) && (e[0]!='.') ; e--);
165+
glen = (e[0]=='.') ? (p->attrend-e-1) : p->attrend-e;
166+
167+
if (str && (slen != glen))
168+
{
169+
mstr(s,str,sizeof(s)-1,slen);
170+
mstr(g,e+1,sizeof(g)-1,glen),
171+
sprintf(p->errstr,"'</%s>' unexpected ('</%s>' wanted)",s,g);
172+
return MY_XML_ERROR;
173+
}
174+
175+
rc = p->leave ? p->leave(p,p->attr,p->attrend-p->attr) : MY_XML_OK;
176+
177+
*e='\0';
178+
p->attrend=e;
179+
180+
return rc;
181+
}
182+
183+
184+
int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
185+
{
186+
p->attrend=p->attr;
187+
p->beg=str;
188+
p->cur=str;
189+
p->end=str+len;
190+
191+
while ( p->cur < p->end )
192+
{
193+
MY_XML_ATTR a;
194+
if(p->cur[0]=='<')
195+
{
196+
int lex;
197+
int question=0;
198+
int exclam=0;
199+
200+
lex=my_xml_scan(p,&a);
201+
202+
if (MY_XML_COMMENT==lex)
203+
{
204+
continue;
205+
}
206+
207+
lex=my_xml_scan(p,&a);
208+
209+
if (MY_XML_SLASH==lex)
210+
{
211+
if(MY_XML_IDENT!=(lex=my_xml_scan(p,&a)))
212+
{
213+
sprintf(p->errstr,"1: %s unexpected (ident wanted)",lex2str(lex));
214+
return MY_XML_ERROR;
215+
}
216+
if(MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg))
217+
return MY_XML_ERROR;
218+
lex=my_xml_scan(p,&a);
219+
goto gt;
220+
}
221+
222+
if (MY_XML_EXCLAM==lex)
223+
{
224+
lex=my_xml_scan(p,&a);
225+
exclam=1;
226+
}
227+
else if (MY_XML_QUESTION==lex)
228+
{
229+
lex=my_xml_scan(p,&a);
230+
question=1;
231+
}
232+
233+
if (MY_XML_IDENT==lex)
234+
{
235+
if(MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg))
236+
return MY_XML_ERROR;
237+
}
238+
else
239+
{
240+
sprintf(p->errstr,"3: %s unexpected (ident or '/' wanted)",lex2str(lex));
241+
return MY_XML_ERROR;
242+
}
243+
244+
while ((MY_XML_IDENT==(lex=my_xml_scan(p,&a))) || (MY_XML_STRING==lex))
245+
{
246+
MY_XML_ATTR b;
247+
if(MY_XML_EQ==(lex=my_xml_scan(p,&b)))
248+
{
249+
lex=my_xml_scan(p,&b);
250+
if ( (lex==MY_XML_IDENT) || (lex=MY_XML_STRING) )
251+
{
252+
if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
253+
(MY_XML_OK!=my_xml_value(p,b.beg,b.end-b.beg)) ||
254+
(MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
255+
return MY_XML_ERROR;
256+
}
257+
else
258+
{
259+
sprintf(p->errstr,"4: %s unexpected (ident or string wanted)",lex2str(lex));
260+
return MY_XML_ERROR;
261+
}
262+
}
263+
else if ( (MY_XML_STRING==lex) || (MY_XML_IDENT==lex) )
264+
{
265+
if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
266+
(MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
267+
return MY_XML_ERROR;
268+
}
269+
else
270+
break;
271+
}
272+
273+
if (lex==MY_XML_SLASH)
274+
{
275+
if(MY_XML_OK!=my_xml_leave(p,NULL,0))
276+
return MY_XML_ERROR;
277+
lex=my_xml_scan(p,&a);
278+
}
279+
280+
gt:
281+
if (question)
282+
{
283+
if (lex!=MY_XML_QUESTION)
284+
{
285+
sprintf(p->errstr,"6: %s unexpected ('?' wanted)",lex2str(lex));
286+
return MY_XML_ERROR;
287+
}
288+
if(MY_XML_OK!=my_xml_leave(p,NULL,0))
289+
return MY_XML_ERROR;
290+
lex=my_xml_scan(p,&a);
291+
}
292+
293+
if (exclam)
294+
{
295+
if(MY_XML_OK!=my_xml_leave(p,NULL,0))
296+
return MY_XML_ERROR;
297+
}
298+
299+
if (lex!=MY_XML_GT)
300+
{
301+
sprintf(p->errstr,"5: %s unexpected ('>' wanted)",lex2str(lex));
302+
return MY_XML_ERROR;
303+
}
304+
}
305+
else
306+
{
307+
a.beg=p->cur;
308+
for ( ; (p->cur < p->end) && (p->cur[0]!='<') ; p->cur++);
309+
a.end=p->cur;
310+
311+
my_xml_norm_text(&a);
312+
if (a.beg!=a.end)
313+
{
314+
my_xml_value(p,a.beg,a.end-a.beg);
315+
}
316+
}
317+
}
318+
return MY_XML_OK;
319+
}
320+
321+
void my_xml_parser_create(MY_XML_PARSER *p)
322+
{
323+
bzero((void*)p,sizeof(p[0]));
324+
}
325+
326+
void my_xml_parser_free(MY_XML_PARSER *p __attribute__((unused)))
327+
{
328+
}
329+
330+
void my_xml_set_value_handler(MY_XML_PARSER *p, int (*action)(MY_XML_PARSER *p, const char *s, uint l))
331+
{
332+
p->value=action;
333+
}
334+
335+
void my_xml_set_enter_handler(MY_XML_PARSER *p, int (*action)(MY_XML_PARSER *p, const char *s, uint l))
336+
{
337+
p->enter=action;
338+
}
339+
340+
void my_xml_set_leave_handler(MY_XML_PARSER *p, int (*action)(MY_XML_PARSER *p, const char *s, uint l))
341+
{
342+
p->leave=action;
343+
}
344+
345+
void my_xml_set_user_data(MY_XML_PARSER *p, void *user_data)
346+
{
347+
p->user_data=user_data;
348+
}
349+
350+
const char *my_xml_error_string(MY_XML_PARSER *p)
351+
{
352+
return p->errstr;
353+
}
354+
355+
356+
uint my_xml_error_pos(MY_XML_PARSER *p)
357+
{
358+
const char *beg=p->beg;
359+
const char *s;
360+
for ( s=p->beg ; s<p->cur; s++)
361+
if (s[0]=='\n')
362+
beg=s;
363+
return p->cur-beg;
364+
}
365+
366+
uint my_xml_error_lineno(MY_XML_PARSER *p)
367+
{
368+
uint res=0;
369+
const char *s;
370+
for ( s=p->beg ; s<p->cur; s++)
371+
if (s[0]=='\n')
372+
res++;
373+
return res;
374+
}

0 commit comments

Comments
 (0)