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