ide: Fixed strings
[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(char * keyWord);
62    virtual void ProcessCharacterData(char * data);
63
64    char keyWord[1024];
65    char * string;
66    int xmlDepth;
67    bool closingTag;
68    bool openingTag;
69
70    bool GetWord()
71    {
72       if(string && string[0])
73       {
74          GetKeyWord(&string, keyWord, sizeof(keyWord));
75          return true;
76       }
77       return false;
78    }
79
80    bool Parse(char * inputString, int count)
81    {
82       bool insideTag = false;
83       char tag[MAX_TAG_LEN];
84       int tagLen;
85       bool commented = false;
86       byte lastCh = ' ';
87       int stringPos;
88       byte characterData[CHARBUFSIZE];
89       int charLen = 0;
90       int oldDepth = xmlDepth;
91       tag[0] = 0;
92
93       closingTag = false;
94
95       // Preparse to check for completeness
96       for(stringPos = 0; stringPos < count; stringPos++)
97       {
98          byte ch = inputString[stringPos];
99
100          if(commented)
101          {
102             if((ch == '-' && tagLen < 2) || (ch == '>' && tagLen == 2))
103             {
104                tag[tagLen++] = ch;
105                tag[tagLen] = '\0';
106                if(!strcmp(tag,  "-->"))
107                {
108                   commented = false;
109                }
110             }
111             else
112                tagLen = 0;
113          }
114          else if(insideTag)
115          {
116             if(ch == '/' && lastCh == '<')
117                closingTag = true;
118
119             if(ch == '<')
120             {
121                insideTag++;
122                openingTag = true;
123             }
124             else if(ch == '>')
125             {
126                if(closingTag)
127                   xmlDepth--;
128                else if(lastCh != '?' && lastCh != '/' && tag[0] != '!')
129                   xmlDepth++;
130                else
131                {
132                   closingTag = true;
133                   openingTag = true;
134                }
135
136                insideTag--;
137                if(!insideTag)
138                   tag[tagLen] = '\0';
139                else
140                {
141                   tag[tagLen++] = ch;
142                   tag[tagLen] = '\0';
143                }
144                closingTag = false;
145             }
146             else if(ch != '/' || lastCh != '<')
147             {
148                tag[tagLen++] = ch;
149                tag[tagLen] = '\0';
150             }
151             else
152                openingTag = false;
153             if(!strcmp(tag, "!--"))
154             {
155                commented = true;
156                insideTag = false;
157                tagLen = 0;
158                tag[tagLen] = '\0';
159             }
160          }
161          else
162          {
163             if(ch == '<')
164             {
165                openingTag = true;
166                insideTag = true;
167                tagLen = 0;
168             }
169          }
170          lastCh = ch;
171       }
172       if(xmlDepth > 1 || insideTag || commented)
173       {
174          xmlDepth = oldDepth;
175          return false;
176       }
177
178       xmlDepth = oldDepth;
179       commented = false;
180       lastCh = ' ';
181       charLen = 0;
182       insideTag = false;
183       closingTag = false;
184       openingTag = false;
185       tag[0] = 0;
186
187       // Parse entire file
188       for(stringPos = 0; stringPos < count; stringPos++)
189       {
190          byte ch = inputString[stringPos];
191
192          if(commented)
193          {
194             if((ch == '-' && tagLen < 2) || (ch == '>' && tagLen == 2))
195             {
196                tag[tagLen++] = ch;
197                tag[tagLen] = '\0';
198                if(!strcmp(tag,  "-->"))
199                {
200                   commented = false;
201                }
202             }
203             else
204                tagLen = 0;
205          }
206          else if(insideTag)
207          {
208             if(ch == '/' && lastCh == '<')
209                closingTag = true;
210             if(ch == '<')
211             {
212                insideTag++;
213                openingTag = true;
214             }
215             else if(ch == '>')
216             {
217                if(closingTag)
218                   xmlDepth--;
219                else if(lastCh != '?' && lastCh != '/' && tag[0] != '!')
220                   xmlDepth++;
221                else
222                {
223                   closingTag = true;
224                   openingTag = true;
225                }
226
227                insideTag--;
228                if(!insideTag)
229                {
230                   tag[tagLen] = '\0';
231                   insideTag = false;
232
233                   string = tag;
234
235                   if(GetKeyWord(&string, keyWord, sizeof(keyWord)))
236                   {
237                      ProcessKeyword(keyWord);
238                   }
239                }
240                else
241                {
242                   tag[tagLen++] = ch;
243                   tag[tagLen] = '\0';
244                }
245                closingTag = false;
246             }
247             else if(ch != '/' || lastCh != '<')
248             {
249                tag[tagLen++] = ch;
250                tag[tagLen] = '\0';
251             }
252             else
253                openingTag = false;
254             if(!strcmp(tag, "!--"))
255             {
256                commented = true;
257                insideTag = false;
258                tagLen = 0;
259                tag[tagLen] = '\0';
260             }
261          }
262          else
263          {
264             if(ch == '<' || charLen == CHARBUFSIZE - 1)
265             {
266                ProcessCharacterData(characterData);
267                charLen = 0;
268             }
269             if(ch == '<')
270             {
271                openingTag = true;
272                insideTag = true;
273                tagLen = 0;
274             }
275             else
276             {
277                characterData[charLen++] = ch;
278                characterData[charLen] = 0;
279             }
280          }
281          lastCh = ch;
282       }
283       return true;
284    }
285 }