1 #include "gen_xml_sax_read.h"
2 
3 #include <iostream>
4 
artSaxParser()5 artSaxParser::artSaxParser() :
6     xmlpp::SaxParser() {
7 }
8 
~artSaxParser()9 artSaxParser::~artSaxParser() {
10 }
11 
on_start_document()12 void artSaxParser::on_start_document() {
13     //std::cout << "on_start_document()" << std::endl;
14     xml_metachunk chunk;
15 
16     chunk.event = onDocStart;
17 
18     chunks.push_back(chunk);
19 }
20 
on_end_document()21 void artSaxParser::on_end_document() {
22     //std::cout << "on_end_document()" << std::endl;
23     xml_metachunk chunk;
24 
25     chunk.event = onDocEnd;
26 
27     chunks.push_back(chunk);
28 }
29 
on_start_element(const Glib::ustring & name,const AttributeList & attributes)30 void artSaxParser::on_start_element(const Glib::ustring& name,
31                                     const AttributeList& attributes)
32 {
33     //std::cout << "node name=" << name << std::endl;
34     xml_metachunk chunk;
35 
36     chunk.event = onElementStart;
37 
38     chunk.element.name = name;
39 
40     // Print attributes:
41     for(xmlpp::SaxParser::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) {
42         //std::cout << "  Attribute " << iter->name << " = " << iter->value << std::endl;
43         Tuple tuple;
44         tuple.name = iter->name;
45         tuple.value = iter->value;
46         chunk.element.pairs.push_back(tuple);
47     }
48 
49     chunks.push_back(chunk);
50 }
51 
on_end_element(const Glib::ustring & name)52 void artSaxParser::on_end_element(const Glib::ustring& name) {
53     //std::cout << "on_end_element()" << std::endl;
54     xml_metachunk chunk;
55 
56     (void)name; // тут не используется
57     // предполагается что мы знаем кому принадлежит закрывающий элемент
58 
59     chunk.event = onElementEnd;
60 
61     chunks.push_back(chunk);
62 }
63 
on_characters(const Glib::ustring & text)64 void artSaxParser::on_characters(const Glib::ustring& text) {
65     //std::cout << "on_characters(): " << text << std::endl;
66 
67     size_t nulz = 0;
68     for(size_t i = 0, l = text.length(); i < l; i++) {
69         //printf("0x%02x\n", text.at(i));
70         if(' ' == text.at(i) || '\n' == text.at(i)) nulz++;
71     }
72     if(nulz == text.length()) {
73         // cout << "EMPTY CHARS" << endl;
74         // просто игнорируем
75     }
76     else {
77         // std::cout << "on_characters(): '" << text << "'" << std::endl;
78         xml_metachunk chunk;
79 
80         chunk.event = onChars;
81         chunk.str = text;
82 
83         chunks.push_back(chunk);
84     }
85 }
86 
on_comment(const Glib::ustring & text)87 void artSaxParser::on_comment(const Glib::ustring& text) {
88     //std::cout << "on_comment(): " << text << std::endl;
89     xml_metachunk chunk;
90 
91     chunk.event = onChars;
92     chunk.str = text;
93 
94     chunks.push_back(chunk);
95 }
96 
on_warning(const Glib::ustring & text)97 void artSaxParser::on_warning(const Glib::ustring& text)
98 {
99     std::cout << "on_warning(): " << text << std::endl;
100 }
101 
on_error(const Glib::ustring & text)102 void artSaxParser::on_error(const Glib::ustring& text)
103 {
104     std::cout << "on_error(): " << text << std::endl;
105 }
106 
on_fatal_error(const Glib::ustring & text)107 void artSaxParser::on_fatal_error(const Glib::ustring& text)
108 {
109     std::cout << "on_fatal_error(): " << text << std::endl;
110 }
111 
112 /////////////////////////////////////////////////////
113 
fetchValue(string name)114 string Element::fetchValue(string name) {
115     // TODO: вообще-то тут надо заменить vector на map и не париться с перебором
116     size_t i, l;
117     for(i = 0, l = pairs.size(); i < l; i++)
118         if(pairs[i].name == name) return pairs[i].value;
119 
120     return "<MISSING FIELD>";
121 }
122 
123 /////////////////////////////////////////////////////
124 
125 #include <assert.h>
126 
127 #ifdef ART_DEBUG
dump(void)128 void xml_metachunk::dump(void) {
129     if (onDocStart == event) {
130         cout << "onStartDoc" << endl;
131     } else if (onDocEnd == event) {
132         cout << "onEndDoc" << endl;
133     } else if (onElementStart == event) {
134         cout << "Element '" << element.name << "' in" << endl;
135         size_t i, l;
136         for (i = 0, l = element.pairs.size(); i < l; i++)
137             cout << element.pairs[i].name << " = " << element.pairs[i].value
138                  << endl;
139     } else if (onElementEnd == event)
140         cout << "Element out" << endl;
141     else if (onChars == event) {
142         cout << "CHARS '" << str << "'" << endl;
143     } else if (onComment == event) {
144         cout << "COMMENT '" << str << "'" << endl;
145     } else
146         assert(false);
147 }
148 #endif
149 
150 /////////////////////////////////////////////////////
151 
chunkGetter()152 chunkGetter::chunkGetter() {}
~chunkGetter()153 chunkGetter::~chunkGetter() {}
154 
copyChunks(vector<xml_metachunk> & chunks)155 void chunkGetter::copyChunks(vector <xml_metachunk> &chunks) {
156     this->chunks = chunks;
157     i = 0;
158     l = this->chunks.size();
159 }
160 
getChunk(void)161 xml_metachunk chunkGetter::getChunk(void) {
162     assert(i < l);
163 
164     xml_metachunk chunk = chunks[i];
165     i++;
166     return chunk;
167 }
168 
getNonCharsChunk(void)169 xml_metachunk chunkGetter::getNonCharsChunk(void) {
170     xml_metachunk chunk;
171 
172     do { chunk = getChunk(); } while (onChars == chunk.event);
173 
174     return chunk;
175 }
176 
peekPrev(void)177 xml_metachunk chunkGetter::peekPrev(void) {
178     assert(i > 0);
179 
180     return chunks[i - 1];
181 }
182 
peekNext(void)183 xml_metachunk chunkGetter::peekNext(void) {
184     //	assert(i > 0 && ((i - 1) < l));
185     //	return chunks[i + 1];
186     // этот ^^^ код на самом деле смотрит на следующий за следующим
187 
188     return chunks[i];
189 }
190 
putChunkBack(void)191 void chunkGetter::putChunkBack(void) {
192     assert(i > 0);
193 
194     i--;
195 }
196 
seekUntilNonCharsChunk(void)197 void chunkGetter::seekUntilNonCharsChunk(void) {
198     xml_metachunk chunk;
199 
200     do { chunk = getChunk(); } while (onChars == chunk.event);
201 
202     putChunkBack();
203 }
204 
205 /////////////////////////////////////////////////////
206 
207 #include "ccloader.h"
208 
209 #include <stdlib.h> // exit()
210 
stringLoader(vector<string> & strings,chunkGetter & getter)211 int stringLoader(vector <string> &strings, chunkGetter &getter) {
212     xml_metachunk chunk = getter.getChunk();
213 
214     assert(onElementStart == chunk.event);
215 
216     chunk = getter.getChunk();
217 
218     if(onChars == chunk.event) {
219         // Тут onChars - как раз нужное содержимое элемента
220         strings.push_back(chunk.str);
221 
222         chunk = getter.getChunk();
223 
224         assert(onElementEnd == chunk.event);
225 
226         return 0;
227     }
228     else if(onElementEnd) {
229         // А тут нет значения, ничего не делаем вообще
230         return 0;
231     }
232 }
233 
exprLoader(CExpr & expr,chunkGetter & getter)234 int exprLoader(CExpr &expr, chunkGetter &getter) {
235     xml_metachunk chunk = getter.getChunk();
236 
237 #ifdef ART_DEBUG
238     if("expr" != chunk.element.name) chunk.dump();
239 #endif
240     assert("expr" == chunk.element.name);
241 
242     local_record_t records[] = {
243         {&expr.oper, "oper", CCSTR}
244         ,{&expr.type, "type", CCSTR}
245         ,{&expr.value, "value", CCSTR}
246     };
247 
248     size_t nRecords = sizeof(records) / sizeof(local_record_t);
249     ccload(chunk, records, nRecords);
250 
251     chunk = getter.getChunk();
252     assert(onElementEnd == chunk.event);
253 
254     return 0;
255 }
256 
argsLoader(CArg & arg,chunkGetter & getter)257 int argsLoader(CArg &arg, chunkGetter &getter) {
258     xml_metachunk chunk = getter.getChunk();
259 
260 #ifdef ART_DEBUG
261     if("args" != chunk.element.name) chunk.dump();
262 #endif
263     assert("args" == chunk.element.name);
264 
265     local_record_t records[] = {
266         {&arg.type, "type", CCSTR}
267         ,{&arg.name, "name", CCSTR}
268     };
269 
270     size_t nRecords = sizeof(records) / sizeof(local_record_t);
271     ccload(chunk, records, nRecords);
272 
273     chunk = getter.getChunk();
274     assert(onElementEnd == chunk.event);
275 
276     return 0;
277 }
278 
torLoader(CTor & tor,chunkGetter & getter)279 int torLoader(CTor &tor, chunkGetter &getter) {
280     xml_metachunk chunk = getter.getChunk();
281 
282 #ifdef ART_DEBUG
283     if("tor" != chunk.element.name) chunk.dump();
284 #endif
285     assert("tor" == chunk.element.name);
286 
287     local_record_t records[] = {
288         {&tor.name, "name", CCSTR}
289         ,{&tor.float_arg_n1, "float_arg_n1", SIZET}
290         ,{&tor.float_arg_n2, "float_arg_n2", SIZET}
291         ,{&tor.is_handle_arg_out, "is_handle_arg_out", CCBOOL}
292         ,{&tor.handle_arg_out, "handle_arg_out", SIZET}
293         ,{&tor.cpp_alias, "cpp_alias", CCSTR}
294     };
295 
296     size_t nRecords = sizeof(records) / sizeof(local_record_t);
297     ccload(chunk, records, nRecords);
298 
299     bool inValidateDom_before = true;
300     while(inValidateDom_before) {
301         getter.seekUntilNonCharsChunk(); // игнорируем все комментарии
302         stringLoader(tor.validateDom_before, getter);
303 
304         chunk = getter.getNonCharsChunk();
305         if(chunk.event != onElementStart || chunk.element.name != "validateDom_before")
306             inValidateDom_before = false;
307 
308         getter.putChunkBack();
309     }
310 
311     // TODO: вставить дополнительную проверку если пропущен элемент validateDom_before
312 
313     bool inArgs = true;
314     while(inArgs) {
315         getter.seekUntilNonCharsChunk(); // игнорируем все комментарии
316 
317         CArg arg;
318 
319         argsLoader(arg, getter);
320 
321         tor.args.push_back(arg);
322 
323         //#ifdef ART_DEBUG
324         //		cout << "TOR NAME: " << tor.name << endl;
325         //		cout << "ADDED ARG:" << endl;
326         //		arg.dump(4);
327         //#endif
328 
329         chunk = getter.getNonCharsChunk();
330         if(chunk.event != onElementStart || chunk.element.name != "args")
331             inArgs = false;
332 
333         getter.putChunkBack();
334     }
335 
336     CExpr expr;
337     exprLoader(expr, getter);
338     tor.badRetCode = expr;
339 
340     chunk = getter.getChunk();
341     assert(onElementEnd == chunk.event); // конец tor'а
342 
343     return 0;
344 }
345 
346 // 0 домен загружен
347 // 1 следующий блок не домен (блок возвращается в коробку)
domainLoader(CDomain & dom,chunkGetter & getter)348 int domainLoader(CDomain &dom, chunkGetter &getter) {
349     xml_metachunk chunk;
350 
351     chunk = getter.getChunk();
352 
353 #ifdef ART_DEBUG
354     if("domain" != chunk.element.name) {
355         cerr << "Expected element: domain, founded: '" << chunk.element.name
356              << "'" << endl;
357         chunk.dump();
358         exit(-2);
359     }
360 #endif
361     assert("domain" == chunk.element.name);
362 
363     local_record_t records[] = {
364         {&dom.name, "name", CCSTR}
365         ,{&dom.float_handle, "float_handle", CCBOOL}
366         ,{&dom.handle, "handle", CCSTR}
367         ,{&dom.includesGlobal, "includesGlobal", CCBOOL}
368     };
369 
370     size_t nRecords = sizeof(records) / sizeof(local_record_t);
371     ccload(chunk, records, nRecords);
372 
373     getter.seekUntilNonCharsChunk(); // игнорируем все комментарии
374 
375     CExpr expr;
376     exprLoader(expr, getter);
377     dom.bad_handle = expr;
378 
379     bool inIncludes = true;
380     while(inIncludes) {
381         getter.seekUntilNonCharsChunk(); // игнорируем все комментарии
382         stringLoader(dom.includes, getter);
383 
384         chunk = getter.getNonCharsChunk();
385         if(chunk.event != onElementStart || chunk.element.name != "includes")
386             inIncludes = false;
387 
388         getter.putChunkBack();
389     }
390 
391     // TODO: принадлежность CTor'а вынести из названия его переменной внутрь его
392     // например, в перечисляемое поле torType
393 
394     bool inTors = true;
395     while(inTors) {
396         getter.seekUntilNonCharsChunk(); // игнорируем все комментарии
397 
398         chunk = getter.peekNext();
399         assert(onElementStart == chunk.event);
400 
401         CTor tor;
402 
403         if("allocator" == chunk.element.fetchValue("__type__")) {
404             torLoader(tor, getter);
405             dom.allocators.push_back(tor);
406         } else if("deallocator" == chunk.element.fetchValue("__type__")) {
407             torLoader(tor, getter);
408             dom.deallocators.push_back(tor);
409         } else if("reallocator" == chunk.element.fetchValue("__type__")) {
410             torLoader(tor, getter);
411             dom.reallocators.push_back(tor);
412         } else if("operator" == chunk.element.fetchValue("__type__")) {
413             torLoader(tor, getter);
414             dom.operators.push_back(tor);
415         } else {
416             cerr << "Unexpected element '" << chunk.element.fetchValue("__type__")
417                  << "' !" << endl;
418 #ifdef ART_DEBUG
419             chunk.dump();
420 #endif
421             assert(false);
422         }
423 
424         chunk = getter.getNonCharsChunk();
425 
426         if(chunk.event != onElementStart || chunk.element.name != "tor")
427             inTors = false;
428 
429         getter.putChunkBack();
430     }
431 
432     chunk = getter.getChunk();
433     assert(onElementEnd == chunk.event); // конец domain'а
434 
435     return 0;
436 }
437 
saxparser_templateLoader(CTemplate & tpl,const char * filepath)438 int saxparser_templateLoader(CTemplate &tpl, const char* filepath) {
439     chunkGetter getter;
440 
441     try {
442         artSaxParser parser;
443         parser.set_substitute_entities(true); //
444         parser.parse_file(filepath);
445 
446         getter.copyChunks(parser.chunks);
447     } catch (const xmlpp::exception& ex) {
448         std::cout << "libxml++ exception: " << ex.what() << std::endl;
449         return -1;
450     }
451 
452     xml_metachunk chunk;
453     chunk = getter.getChunk();
454     assert(onDocStart == chunk.event);
455 
456     chunk = getter.getChunk();
457     //#ifdef ART_DEBUG
458     //        chunk.dump();
459     //#endif
460 
461     local_record_t records[] = {
462         {&tpl.name, "name", CCSTR}
463         ,{&tpl.prefix, "prefix", CCSTR}
464         ,{&tpl.errlogmode, "errlogmode", CCSTR}
465         ,{&tpl.trap_on_io_err, "trap_on_io_err", CCBOOL}
466         ,{&tpl.remote_mode, "remote_mode", CCBOOL}
467         ,{&tpl.force_flush, "force_flush", CCBOOL}
468         ,{&tpl.fork_enabled, "fork_enabled", CCBOOL}
469         ,{&tpl.multithreaded, "multithreaded", CCBOOL}
470         ,{&tpl.threading, "threading", CCSTR}
471         ,{&tpl.compiler_type, "compiler_type", CCSTR}
472         ,{&tpl.trace_target, "trace_target", CCSTR}
473     };
474 
475     size_t nRecords = sizeof(records) / sizeof(local_record_t);
476     ccload(chunk, records, nRecords);
477 
478     bool inDomain = true;
479     while(inDomain) {
480         CDomain dom;
481 
482         getter.seekUntilNonCharsChunk(); // игнорируем все комментарии
483         domainLoader(dom, getter);
484 
485         tpl.domains.push_back(dom);
486 
487         chunk = getter.getNonCharsChunk();
488         if(chunk.event != onElementStart || chunk.element.name != "domain")
489             inDomain = false;
490 
491         getter.putChunkBack();
492     }
493 
494     chunk = getter.getChunk();
495 
496     assert(onElementEnd == chunk.event); // конец template'а
497 
498     // TODO: реализовать загрузку vector <CTor> specialTors;
499 
500 #ifdef NOTHING
501     // Demonstrate incremental parsing, sometimes useful for network connections:
502     {
503         //std::cout << "Incremental SAX Parser:" << std:endl;
504 
505         std::ifstream is(filepath.c_str());
506         char buffer[64];
507 
508         artSaxParser parser;
509         do {
510             is.read(buffer, 63);
511             Glib::ustring input(buffer, is.gcount());
512 
513             parser.parse_chunk(input);
514         }
515         while(is);
516 
517         parser.finish_chunk_parsing();
518     }
519 #endif
520 
521     return 0;
522 }
523 
524 #ifdef NOTHING_YET
525 #include "utils_linefetch.h"
526 
saxparser_templateLoader(CTemplate & tpl,CVLineFetcher * fetcher)527 int saxparser_templateLoader(CTemplate &tpl, CVLineFetcher *fetcher) {
528     // TODO: NYI
529     // В этот момент мне не тратить время на разбирание с последовательным
530     // разбором (incremental parsing) XML, хотя это верный путь.
531     // Обходной путь через подмену artSaxParser возможно, я реализую потом.
532     // А сейчас я просто скину файл на диск и оттуда его разберу как файл :)
533 }
534 #endif
535