ecere/gui/Window: Prevent uninitialized values if base Window methods not overridden...
[sdk] / extras / XMLParser.ec
1 public import "ecere"
2
3 #define MAX_TAG_LEN  2048
4
5 enum WordStatus
6 {
7    None,
8    Normal,
9    Quoted
10 };
11
12 static WordStatus GetKeyWordEx(char ** input, char * keyWord, int maxSize, bool treatEqual)
13 {
14    char * string = *input;
15    char ch;
16    int c = 0;
17    bool quoted = false, start = true, wasQuoted = false;
18
19    for(; (ch = *string); string++)
20    {
21       if(!quoted && wasQuoted)
22          break;
23
24       if((ch == ' ' || ch == '\t') && !quoted)
25       {
26          if(!start) break;
27       }
28       else
29       {
30          if(!quoted && ((ch == ',' || (treatEqual && ch == '=')) || ch == '>') )
31             break;
32          else if(ch == '\"' /*|| ch == '\''*/)
33          {
34             quoted ^= true;
35             wasQuoted = true;
36             start = false;
37          }
38          else if(ch != '\r' && ch != '\n')
39          {
40             if(c < maxSize)
41                keyWord[c++] = ch;
42             start = false;
43          }
44       }
45    }
46    for(;*string == '>' || *string == ',' || *string == ' ' || *string == '=' || *string == '\t' || *string == '\r' || *string == '\n'; string++);
47    keyWord[c] = '\0';
48    *input = string;
49    return (c > 0) ? (wasQuoted ? Quoted : Normal) : None;
50 }
51
52 static WordStatus GetKeyWord(char ** input, char * keyWord, int maxSize)
53 {
54    return GetKeyWordEx(input, keyWord, maxSize, true);
55 }
56
57 #define CHARBUFSIZE  65536
58
59 class XMLParser
60 {
61    virtual void ProcessKeyword(const char * keyWord);
62    virtual void ProcessCharacterData(const char * data);
63
64    char keyWord[1024];
65    char * string;
66    int xmlDepth;
67    bool closingTag;
68    bool openingTag;
69    char * characterData;
70    uint charBufSize;
71
72    charBufSize = CHARBUFSIZE;
73
74    ~XMLParser()
75    {
76       delete characterData;
77    }
78
79    bool GetWord()
80    {
81       if(string && string[0])
82       {
83          GetKeyWord(&string, keyWord, sizeof(keyWord));
84          return true;
85       }
86       return false;
87    }
88
89    bool Parse(const char * inputString, int count)
90    {
91       bool insideTag = false;
92       char tag[MAX_TAG_LEN];
93       int tagLen = 0;
94       bool commented = false;
95       byte lastCh = ' ';
96       int stringPos;
97       char * characterData = this.characterData;
98       int charLen = 0;
99       int oldDepth = xmlDepth;
100       tag[0] = 0;
101
102       closingTag = false;
103
104       // Preparse to check for completeness
105       for(stringPos = 0; stringPos < count; stringPos++)
106       {
107          byte ch = inputString[stringPos];
108
109          if(commented)
110          {
111             if((ch == '-' && tagLen < 2) || (ch == '>' && tagLen == 2))
112             {
113                tag[tagLen++] = ch;
114                tag[tagLen] = '\0';
115                if(!strcmp(tag,  "-->"))
116                {
117                   commented = false;
118                }
119             }
120             else
121                tagLen = 0;
122          }
123          else if(insideTag)
124          {
125             if(ch == '/' && lastCh == '<')
126                closingTag = true;
127
128             if(ch == '<')
129             {
130                insideTag++;
131                openingTag = true;
132             }
133             else if(ch == '>')
134             {
135                if(closingTag)
136                   xmlDepth--;
137                else if(lastCh != '?' && lastCh != '/' && tag[0] != '!')
138                   xmlDepth++;
139                else
140                {
141                   closingTag = true;
142                   openingTag = true;
143                }
144
145                insideTag--;
146                if(!insideTag)
147                   tag[tagLen] = '\0';
148                else
149                {
150                   tag[tagLen++] = ch;
151                   tag[tagLen] = '\0';
152                }
153                closingTag = false;
154             }
155             else if(ch != '/' || lastCh != '<')
156             {
157                tag[tagLen++] = ch;
158                tag[tagLen] = '\0';
159             }
160             else
161                openingTag = false;
162             if(!strcmp(tag, "!--"))
163             {
164                commented = true;
165                insideTag = false;
166                tagLen = 0;
167                tag[tagLen] = '\0';
168             }
169          }
170          else
171          {
172             if(ch == '<')
173             {
174                openingTag = true;
175                insideTag = true;
176                tagLen = 0;
177             }
178          }
179          lastCh = ch;
180       }
181       if(xmlDepth > 1 || insideTag || commented)
182       {
183          xmlDepth = oldDepth;
184          return false;
185       }
186
187       xmlDepth = oldDepth;
188       commented = false;
189       lastCh = ' ';
190       charLen = 0;
191       insideTag = false;
192       closingTag = false;
193       openingTag = false;
194       tag[0] = 0;
195
196       // Parse entire file
197       for(stringPos = 0; stringPos < count; stringPos++)
198       {
199          char ch = inputString[stringPos];
200
201          if(commented)
202          {
203             if((ch == '-' && tagLen < 2) || (ch == '>' && tagLen == 2))
204             {
205                tag[tagLen++] = ch;
206                tag[tagLen] = '\0';
207                if(!strcmp(tag,  "-->"))
208                {
209                   commented = false;
210                }
211             }
212             else
213                tagLen = 0;
214          }
215          else if(insideTag)
216          {
217             if(ch == '/' && lastCh == '<')
218                closingTag = true;
219             if(ch == '<')
220             {
221                insideTag++;
222                openingTag = true;
223             }
224             else if(ch == '>')
225             {
226                if(closingTag)
227                   xmlDepth--;
228                else if(lastCh != '?' && lastCh != '/' && tag[0] != '!')
229                   xmlDepth++;
230                else
231                {
232                   closingTag = true;
233                   openingTag = true;
234                }
235
236                insideTag--;
237                if(!insideTag)
238                {
239                   tag[tagLen] = '\0';
240                   insideTag = false;
241
242                   string = tag;
243
244                   if(GetKeyWord(&string, keyWord, sizeof(keyWord)))
245                   {
246                      ProcessKeyword(keyWord);
247                   }
248                }
249                else
250                {
251                   tag[tagLen++] = ch;
252                   tag[tagLen] = '\0';
253                }
254                closingTag = false;
255             }
256             else if(ch != '/' || lastCh != '<')
257             {
258                tag[tagLen++] = ch;
259                tag[tagLen] = '\0';
260             }
261             else
262                openingTag = false;
263             if(!strcmp(tag, "!--"))
264             {
265                commented = true;
266                insideTag = false;
267                tagLen = 0;
268                tag[tagLen] = '\0';
269             }
270          }
271          else
272          {
273             if(!characterData)
274                this.characterData = characterData = new byte[charBufSize];
275             if(ch == '<' || charLen == charBufSize - 1)
276             {
277                ProcessCharacterData(characterData);
278                charLen = 0;
279             }
280             if(ch == '<')
281             {
282                openingTag = true;
283                insideTag = true;
284                tagLen = 0;
285             }
286             else
287             {
288                characterData[charLen++] = ch;
289                characterData[charLen] = 0;
290             }
291          }
292          lastCh = ch;
293       }
294       return true;
295    }
296 }