1/* minixml.c : the minimum size a xml parser can be ! */
2/* Project : miniupnp
3 * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * Author : Thomas Bernard
5
6Copyright (c) 2005-2007, Thomas BERNARD
7All rights reserved.
8
9Redistribution and use in source and binary forms, with or without
10modification, are permitted provided that the following conditions are met:
11
12    * Redistributions of source code must retain the above copyright notice,
13      this list of conditions and the following disclaimer.
14    * Redistributions in binary form must reproduce the above copyright notice,
15      this list of conditions and the following disclaimer in the documentation
16      and/or other materials provided with the distribution.
17    * The name of the author may not be used to endorse or promote products
18	  derived from this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30POSSIBILITY OF SUCH DAMAGE.
31*/
32#include "minixml.h"
33
34/* parseatt : used to parse the argument list
35 * return 0 (false) in case of success and -1 (true) if the end
36 * of the xmlbuffer is reached. */
37int parseatt(struct xmlparser * p)
38{
39	const char * attname;
40	int attnamelen;
41	const char * attvalue;
42	int attvaluelen;
43	while(p->xml < p->xmlend)
44	{
45		if(*p->xml=='/' || *p->xml=='>')
46			return 0;
47		if( !IS_WHITE_SPACE(*p->xml) )
48		{
49			char sep;
50			attname = p->xml;
51			attnamelen = 0;
52			while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) )
53			{
54				attnamelen++; p->xml++;
55				if(p->xml >= p->xmlend)
56					return -1;
57			}
58			while(*(p->xml++) != '=')
59			{
60				if(p->xml >= p->xmlend)
61					return -1;
62			}
63			while(IS_WHITE_SPACE(*p->xml))
64			{
65				p->xml++;
66				if(p->xml >= p->xmlend)
67					return -1;
68			}
69			sep = *p->xml;
70			if(sep=='\'' || sep=='\"')
71			{
72				p->xml++;
73				if(p->xml >= p->xmlend)
74					return -1;
75				attvalue = p->xml;
76				attvaluelen = 0;
77				while(*p->xml != sep)
78				{
79					attvaluelen++; p->xml++;
80					if(p->xml >= p->xmlend)
81						return -1;
82				}
83			}
84			else
85			{
86				attvalue = p->xml;
87				attvaluelen = 0;
88				while(   !IS_WHITE_SPACE(*p->xml)
89					  && *p->xml != '>' && *p->xml != '/')
90				{
91					attvaluelen++; p->xml++;
92					if(p->xml >= p->xmlend)
93						return -1;
94				}
95			}
96			/*printf("%.*s='%.*s'\n",
97			       attnamelen, attname, attvaluelen, attvalue);*/
98			if(p->attfunc)
99				p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen);
100		}
101		p->xml++;
102	}
103	return -1;
104}
105
106/* parseelt parse the xml stream and
107 * call the callback functions when needed... */
108void parseelt(struct xmlparser * p)
109{
110	int i;
111	const char * elementname;
112	while(p->xml < (p->xmlend - 1))
113	{
114		if((p->xml)[0]=='<' && (p->xml)[1]!='?')
115		{
116			i = 0; elementname = ++p->xml;
117			while( !IS_WHITE_SPACE(*p->xml)
118				  && (*p->xml!='>') && (*p->xml!='/')
119				 )
120			{
121				i++; p->xml++;
122				if (p->xml >= p->xmlend)
123					return;
124				/* to ignore namespace : */
125				if(*p->xml==':')
126				{
127					i = 0;
128					elementname = ++p->xml;
129				}
130			}
131			if(i>0)
132			{
133				if(p->starteltfunc)
134					p->starteltfunc(p->data, elementname, i);
135				if(parseatt(p))
136					return;
137				if(*p->xml!='/')
138				{
139					const char * data;
140					i = 0; data = ++p->xml;
141					if (p->xml >= p->xmlend)
142						return;
143					while( IS_WHITE_SPACE(*p->xml) )
144					{
145						p->xml++;
146						if (p->xml >= p->xmlend)
147							return;
148					}
149					while(*p->xml!='<')
150					{
151						i++; p->xml++;
152						if (p->xml >= p->xmlend)
153							return;
154					}
155					if(i>=0 && p->datafunc)
156						p->datafunc(p->data, data, i);
157				}
158			}
159			else if(*p->xml == '/')
160			{
161				i = 0; elementname = ++p->xml;
162				if (p->xml >= p->xmlend)
163					return;
164				while((*p->xml != '>'))
165				{
166					i++; p->xml++;
167					if (p->xml >= p->xmlend)
168						return;
169				}
170				if(p->endeltfunc)
171					p->endeltfunc(p->data, elementname, i);
172				p->xml++;
173			}
174		}
175		else
176		{
177			p->xml++;
178		}
179	}
180}
181
182/* the parser must be initialized before calling this function */
183void parsexml(struct xmlparser * parser)
184{
185	parser->xml = parser->xmlstart;
186	parser->xmlend = parser->xmlstart + parser->xmlsize;
187	parseelt(parser);
188}
189
190
191