EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
DecodeGenerator.cpp
Go to the documentation of this file.
1 /*
2  ------------------------------------------------------------------------------------
3  LICENSE:
4  ------------------------------------------------------------------------------------
5  This file is part of EVEmu: EVE Online Server Emulator
6  Copyright 2006 - 2021 The EVEmu Team
7  For the latest information visit https://evemu.dev
8  ------------------------------------------------------------------------------------
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License along with
19  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21  http://www.gnu.org/copyleft/lesser.txt.
22  ------------------------------------------------------------------------------------
23  Author: Zhur
24  Rewrite: Allan
25 */
26 
27 
28 #include "eve-xmlpktgen.h"
29 
30 #include "DecodeGenerator.h"
31 
33 : Generator(outputFile),
34  mName(nullptr),
35  mItemNumber(0)
36 {
38 }
39 
40 bool ClassDecodeGenerator::ProcessElementDef(const TiXmlElement* field)
41 {
42  mName = field->Attribute("name");
43  if (!mName) {
44  _log(COMMON__ERROR, "<element> at line %d is missing the name attribute, skipping.", field->Row());
45  return false;
46  }
47 
48  const TiXmlElement* main = field->FirstChildElement();
49 
50  fprintf(mOutputFile,
51  "bool %s::Decode(PyRep* packet) {\n",
52  mName
53  );
54 
55  mItemNumber = 0;
56 
57  push("packet");
58  if (!ParseElement(main))
59  return false;
60 
61  fprintf(mOutputFile,
62  " return true;\n"
63  "}\n\n"
64  "bool %s::Decode(PyRep** packet) {\n"
65  " bool res = Decode(*packet);\n"
66  " PyDecRef(*packet);\n"
67  " *packet = nullptr;\n"
68  " return res;\n"
69  "}\n\n"
70  "bool %s::Decode(%s** packet) {\n"
71  " //quick forwarder to avoid making the user cast it if they have a properly typed object\n"
72  " return Decode((PyRep**)packet);\n"
73  "}\n\n",
74  mName,
75  mName, GetEncodeType(main)
76  );
77 
78  return true;
79 }
80 
81 bool ClassDecodeGenerator::ProcessElement(const TiXmlElement* field)
82 {
83  const char* name = field->Attribute("name");
84  if (name == nullptr) {
85  std::cout << std::endl << "ClassDecodeGenerator::ProcessElement field at line " << field->Row() << " is missing the name attribute, skipping.";
86  return false;
87  }
88 
89  const char* v = top();
90  fprintf(mOutputFile,
91  " if (!%s.Decode(%s)) {\n"
92  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: unable to decode element %s\");\n"
93  " return false;\n"
94  " }\n\n",
95  name, v,
96  mName, name
97  );
98 
99  pop();
100  return true;
101 }
102 
103 bool ClassDecodeGenerator::ProcessElementPtr(const TiXmlElement* field)
104 {
105  const char* name = field->Attribute("name");
106  if (name == nullptr) {
107  std::cout << std::endl << "ClassDecodeGenerator::ProcessElementPtr field at line " << field->Row() << " is missing the name attribute, skipping.";
108  return false;
109  }
110 
111  const char* type = field->Attribute("type");
112  if (!type) {
113  _log(COMMON__ERROR, "field at line %d is missing the type attribute, skipping.", field->Row());
114  return false;
115  }
116 
117  const char* v = top();
118  fprintf(mOutputFile,
119  " SafeDelete(%s);\n"
120  " %s = new %s;\n\n"
121  " if (!%s->Decode(%s)) {\n"
122  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: unable to decode element %s\");\n"
123  " return false;\n"
124  " }\n\n",
125  name,
126  name, type,
127 
128  name, v,
129  mName, name
130  );
131 
132  pop();
133  return true;
134 }
135 
136 bool ClassDecodeGenerator::ProcessRaw(const TiXmlElement* field)
137 {
138  const char* name = field->Attribute("name");
139  if (name == nullptr) {
140  std::cout << std::endl << "ClassDecodeGenerator::ProcessRaw field at line " << field->Row() << " is missing the name attribute, skipping.";
141  return false;
142  }
143 
144  const char* unusual = field->Attribute("unusual");
145  const char* v = top();
146 /*
147  if (unusual != nullptr) {
148  fprintf(mOutputFile,
149  " if (%s->IsFloat()) {\n"
150  " _log(XMLP__DECODE_WARNING, \" unusual is enabled. %s was decoded as PyFloat\");\n"
151  " %s = %s->AsFloat()->value();\n"
152  " } else if (%s->IsLong()) {\n"
153  " _log(XMLP__DECODE_WARNING, \" unusual is enabled. %s was decoded as PyLong\");\n"
154  " %s = %s->AsLong()->value();\n"
155  " } else if (%s->IsBool()) {\n"
156  " _log(XMLP__DECODE_WARNING, \" unusual is enabled. %s was decoded as PyBool\");\n"
157  " %s = %s->AsBool()->value();\n"
158  " } else if (%s->IsString()) {\n"
159  " _log(XMLP__DECODE_WARNING, \" unusual is enabled. %s was decoded as PyString\");\n"
160  " %s = %s->AsString()->content();\n"
161  " } else if (%s->IsWString()) {\n"
162  " _log(XMLP__DECODE_WARNING, \" unusual is enabled. %s was decoded as PyWString\");\n"
163  " %s = %s->AsWString()->content();\n"
164  " } else {\n",
165  " _log(XMLP__DECODE_WARNING, \" unusual is enabled. %s was decoded as PyRep\");\n"
166  " PySafeDecRef(%s);\n"
167  " %s = %s;\n"
168  " PyIncRef(%s);\n"
169  " }\n\n",
170  v,name,
171  name, v,
172  v,name,
173  name, v,
174  v,name,
175  name, v,
176  v,name,
177  name, v,
178  v,name,
179  name, v,
180  name,
181  name,
182  name, v,
183  name
184  );
185  } else {
186  */
187  fprintf(mOutputFile,
188  " PySafeDecRef(%s);\n"
189  " %s = %s;\n"
190  " PyIncRef(%s);\n\n",
191  name,
192  name, v,
193  name
194  );
195  //}
196 
197  pop();
198  return true;
199 }
200 
201 bool ClassDecodeGenerator::ProcessInt(const TiXmlElement* field)
202 {
203  const char* name = field->Attribute("name");
204  if (name == nullptr) {
205  std::cout << std::endl << "ClassDecodeGenerator::ProcessInt field at line " << field->Row() << " is missing the name attribute, skipping.";
206  return false;
207  }
210  //const char* safe = field->Attribute("safe");
211  const char* none_marker = field->Attribute("none_marker");
212 
213  const char* v = top();
214  if (none_marker != nullptr)
215  fprintf(mOutputFile,
216  " if (%s->IsNone())\n"
217  " %s = %s;\n"
218  " else\n",
219  v,
220  name, none_marker
221  );
222 
223  fprintf(mOutputFile, " %s = PyRep::IntegerValue(%s);\n", name, v);
224 
225  /*
226  fprintf(mOutputFile,
227  " if (%s->IsInt())\n"
228  " %s = PyRep::IntegerValue(%s);\n"
229  " else\n",
230  v,
231  name, v
232  );
233 
234  if (safe != nullptr)
235  fprintf(mOutputFile,
236  " if (%s->IsFloat()) {\n"
237  " _log(XMLP__DECODE_WARNING, \" Safe is enabled. %s was decoded as PyFloat\");\n"
238  " %s = %s->AsFloat()->value();\n"
239  " } else if (%s->IsLong()) {\n"
240  " _log(XMLP__DECODE_WARNING, \" Safe is enabled. %s was decoded as PyLong\");\n"
241  " %s = %s->AsLong()->value();\n"
242  " } else if (%s->IsBool()) {\n"
243  " _log(XMLP__DECODE_WARNING, \" Safe is enabled. %s was decoded as PyBool\");\n"
244  " %s = %s->AsBool()->value();\n"
245  " } else\n",
246  v,name,
247  name, v,
248  v,name,
249  name, v,
250  v,name,
251  name, v
252  );
253 
254  fprintf(mOutputFile,
255  " {\n"
256  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not an Integer: %%s\", %s->TypeString());\n"
257  " return false;\n"
258  " }\n"
259  "\n",
260  mName, name, v
261  );
262 */
263 
264  pop();
265  return true;
266 }
267 
268 bool ClassDecodeGenerator::ProcessLong(const TiXmlElement* field)
269 {
270  const char* name = field->Attribute("name");
271  if (name == nullptr) {
272  std::cout << std::endl << "ClassDecodeGenerator::ProcessLong field at line " << field->Row() << " is missing the name attribute, skipping.";
273  return false;
274  }
275 
276  const char* v = top();
277  fprintf(mOutputFile, " %s = PyRep::IntegerValue(%s);\n", name, v);
278 
279  pop();
280  return true;
281 }
282 
283 bool ClassDecodeGenerator::ProcessReal(const TiXmlElement* field)
284 {
285  const char* name = field->Attribute("name");
286  if (name == nullptr) {
287  std::cout << std::endl << "ClassDecodeGenerator::ProcessReal field at line " << field->Row() << " is missing the name attribute, skipping.";
288  return false;
289  }
290 
291  const char* safe = field->Attribute("safe");
292  const char* none_marker = field->Attribute("none_marker");
293 
294  const char* v = top();
295  if (none_marker != nullptr)
296  fprintf(mOutputFile,
297  " if (%s->IsNone())\n"
298  " %s = %s;\n"
299  " else ",
300  v,
301  name, none_marker
302  );
303 
304  fprintf(mOutputFile,
305  " if (%s->IsFloat())\n"
306  " %s = %s->AsFloat()->value();\n"
307  " else ",
308  v,
309  name, v
310  );
311 
312  if (safe != nullptr) {
313  fprintf(mOutputFile, "\n %s = PyRep::IntegerValue(%s);\n", name, v);
314  } else {
315  fprintf(mOutputFile,
316  "{\n"
317  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a Double: %%s\", %s->TypeString());\n"
318  " return false;\n"
319  " }\n\n",
320  mName, name, v
321  );
322  }
323 
324  pop();
325  return true;
326 }
327 
328 bool ClassDecodeGenerator::ProcessBool(const TiXmlElement* field)
329 {
330  const char* name = field->Attribute("name");
331  if (name == nullptr) {
332  std::cout << std::endl << "ClassDecodeGenerator::ProcessBool field at line " << field->Row() << " is missing the name attribute, skipping.";
333  return false;
334  }
335 
336  const char* v = top();
337  fprintf(mOutputFile, " %s = PyRep::IntegerValue(%s);\n", name, v);
338 
339  pop();
340  return true;
341 }
342 
343 bool ClassDecodeGenerator::ProcessNone(const TiXmlElement* field)
344 {
345  const char* v = top();
346  fprintf(mOutputFile,
347  " if (!%s->IsNone()) {\n"
348  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a None: %%s\", %s->TypeString());\n"
349  " return false;\n"
350  " }\n\n",
351  v, mName, v, v
352  );
353 
354  pop();
355  return true;
356 }
357 
358 bool ClassDecodeGenerator::ProcessBuffer(const TiXmlElement* field)
359 {
360  const char* name = field->Attribute("name");
361  if (name == nullptr) {
362  std::cout << std::endl << "ClassDecodeGenerator::ProcessBuffer field at line " << field->Row() << " is missing the name attribute, skipping.";
363  return false;
364  }
365 
366  const char* v = top();
367  fprintf(mOutputFile,
368  " PySafeDecRef(%s);\n"
369  " if (%s->IsBuffer()) {\n"
370  " %s = %s->AsBuffer();\n"
371  " PyIncRef(%s);\n"
372  " } else if (%s->IsString()) {\n"
373  " %s = new PyBuffer(*%s->AsString());\n"
374  " } else {\n"
375  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a buffer: %%s\", %s->TypeString());\n"
376  " return false;\n"
377  " }\n\n",
378  name,
379  v,
380  name, v,
381  name,
382  v,
383  name, v,
384  mName, name, v
385  );
386 
387  pop();
388  return true;
389 }
390 
391 bool ClassDecodeGenerator::ProcessString(const TiXmlElement* field)
392 {
393  const char* name = field->Attribute("name");
394  if (name == nullptr) {
395  std::cout << std::endl << "ClassDecodeGenerator::ProcessString field at line " << field->Row() << " is missing the name attribute, skipping.";
396  return false;
397  }
398 
399  const char* safe = field->Attribute("safe");
400  const char* none_marker = field->Attribute("none_marker");
401  const char* v = top();
402  if (none_marker != nullptr)
403  fprintf(mOutputFile,
404  " if (%s->IsNone())\n"
405  " %s = \"%s\";\n"
406  " else ",
407  v,
408  name, none_marker
409  );
410 
411  fprintf(mOutputFile,
412  " if (%s->IsString())\n"
413  " %s = %s->AsString()->content();\n"
414  " else ",
415  v,
416  name, v
417  );
418 
419  if (safe != nullptr)
420  fprintf(mOutputFile,
421  " if (%s->IsWString()) {\n"
422  " _log(XMLP__DECODE_WARNING, \" Safe is enabled. %s was decoded as PyWString\");\n"
423  " %s = %s->AsWString()->content();\n"
424  " } else\n",
425  v,name,
426  name, v
427  );
428 
429  fprintf(mOutputFile,
430  " {\n"
431  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a string: %%s\", %s->TypeString());\n"
432  " return false;\n"
433  " }\n"
434  "\n",
435  mName, name, v
436  );
437 
438  pop();
439  return true;
440 }
441 
442 bool ClassDecodeGenerator::ProcessStringInline(const TiXmlElement* field)
443 {
444  const char* value = field->Attribute("value");
445  if (!value) {
446  _log(COMMON__ERROR, "String element at line %d has no value attribute.", field->Row());
447  return false;
448  }
449 
450  char iname[16];
451  snprintf(iname, sizeof(iname), "string_%u", ++mItemNumber);
452 
453  const char* v = top();
454  fprintf(mOutputFile,
455  " if (!%s->IsString()) {\n"
456  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a string: %%s\", %s->TypeString());\n"
457  " return false;\n"
458  " }\n\n"
459  " PyString* %s(%s->AsString());\n"
460  " if (\"%s\" != %s->content()) {\n"
461  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: expected %s to be '%s', but it's '%%s'\", %s->content().c_str());\n"
462  " return false;\n"
463  " }\n\n",
464  v,
465  mName, iname, v,
466  iname, v,
467 
468  value, iname,
469  mName, iname, value, iname
470  );
471 
472  pop();
473  return true;
474 }
475 
476 bool ClassDecodeGenerator::ProcessWString(const TiXmlElement* field)
477 {
478  const char* name = field->Attribute("name");
479  if (name == nullptr) {
480  std::cout << std::endl << "ClassDecodeGenerator::ProcessWString field at line " << field->Row() << " is missing the name attribute, skipping.";
481  return false;
482  }
483 
484  const char* safe = field->Attribute("safe");
485  const char* none_marker = field->Attribute("none_marker");
486  const char* v = top();
487  if (none_marker != nullptr)
488  fprintf(mOutputFile,
489  " if (%s->IsNone())\n"
490  " %s = \"%s\";\n"
491  " else ",
492  v,
493  name, none_marker
494  );
495 
497  fprintf(mOutputFile,
498  " if (%s->IsWString())\n"
499  " %s = %s->AsWString()->content();\n"
500  " else ",
501  v,
502  name, v
503  );
504 
505  if (safe != nullptr)
506  fprintf(mOutputFile,
507  " if (%s->IsString()) {\n"
508  " _log(XMLP__DECODE_WARNING, \" Safe is enabled. %s was decoded as PyString\");\n"
509  " %s = %s->AsString()->content();\n"
510  " } else ",
511  v,name,
512  name, v
513  );
514 
515  fprintf(mOutputFile,
516  " {\n"
517  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a string: %%s\", %s->TypeString());\n"
518  " return false;\n"
519  " }\n\n",
520  mName, name, v
521  );
522 
523  pop();
524  return true;
525 }
526 
527 bool ClassDecodeGenerator::ProcessWStringInline(const TiXmlElement* field)
528 {
529  const char* value = field->Attribute("value");
530  if (!value) {
531  _log(COMMON__ERROR, "WString element at line %d has no value attribute.", field->Row());
532  return false;
533  }
534 
535  char iname[16];
536  snprintf(iname, sizeof(iname), "wstring_%u", ++mItemNumber);
537 
538  const char* v = top();
539  fprintf(mOutputFile,
540  " if (!%s->IsWString()) {\n"
541  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a wstring: %%s\", %s->TypeString());\n"
542  " return false;\n"
543  " }\n\n"
544  " PyWString* %s(%s->AsWString());\n"
545  " if (\"%s\" != %s->content()) {\n"
546  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: expected %s to be '%s', but it's '%%s'\", %s->content().c_str());\n"
547  " return false;\n"
548  " }\n\n",
549  v,
550  mName, iname, v,
551  iname, v,
552 
553  value, iname,
554  mName, iname, value, iname
555  );
556 
557  pop();
558  return true;
559 }
560 
561 bool ClassDecodeGenerator::ProcessToken(const TiXmlElement* field)
562 {
563  const char* name = field->Attribute("name");
564  if (name == nullptr) {
565  std::cout << std::endl << "ClassDecodeGenerator::ProcessToken field at line " << field->Row() << " is missing the name attribute, skipping.";
566  return false;
567  }
568 
569  bool optional = false;
570  const char* optional_str = field->Attribute("optional");
571  if (optional_str != nullptr)
572  optional = str2<bool>(optional_str);
573 
574  fprintf(mOutputFile,
575  " PySafeDecRef(%s);\n",
576  name
577  );
578 
579  const char* v = top();
580  if (optional)
581  fprintf(mOutputFile,
582  " if (%s->IsNone())\n"
583  " %s = nullptr;\n"
584  " else ",
585  v,
586  name
587  );
588 
589  fprintf(mOutputFile,
590  " if (%s->IsToken()) {\n"
591  " %s = %s->AsToken();\n"
592  " //PyIncRef(%s);\n"
593  " } else {\n"
594  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a token: %%s\", %s->TypeString());\n"
595  " return false;\n"
596  " }\n\n",
597  v,
598  name, v,
599  name,
600 
601  mName, name, v
602  );
603 
604  pop();
605  return true;
606 }
607 
608 bool ClassDecodeGenerator::ProcessTokenInline(const TiXmlElement* field)
609 {
610  const char* value = field->Attribute("value");
611  if (!value) {
612  _log(COMMON__ERROR, "Token element at line %d has no value attribute.", field->Row());
613  return false;
614  }
615 
616  char iname[16];
617  snprintf(iname, sizeof(iname), "token_%u", ++mItemNumber);
618 
619  const char* v = top();
620  fprintf(mOutputFile,
621  " if (!%s->IsToken()) {\n"
622  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a token: %%s\", %s->TypeString());\n"
623  " return false;\n"
624  " }\n\n"
625  " PyToken* %s(%s->AsToken());\n"
626  " if (%s->content() != \"%s\") {\n"
627  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: expected %s to be '%s', but it's '%%s'\", %s->content().c_str());\n"
628  " return false;\n"
629  " }\n\n",
630  v,
631  mName, iname, v,
632  iname, v,
633 
634  iname, value,
635  mName, iname, value, iname
636  );
637 
638  pop();
639  return true;
640 }
641 
642 bool ClassDecodeGenerator::ProcessObject(const TiXmlElement* field)
643 {
644  const char* name = field->Attribute("name");
645  if (name == nullptr) {
646  std::cout << std::endl << "ClassDecodeGenerator::ProcessObject field at line " << field->Row() << " is missing the name attribute, skipping.";
647  return false;
648  }
649 
650  bool optional = false;
651  const char* optional_str = field->Attribute("optional");
652  if (nullptr != optional_str)
653  optional = str2<bool>(optional_str);
654 
655  fprintf(mOutputFile,
656  " PySafeDecRef(%s);\n",
657  name
658  );
659 
660  const char* v = top();
661  if (optional) {
662  fprintf(mOutputFile,
663  " if (%s->IsNone())\n"
664  " %s = nullptr;\n"
665  " else ",
666  v,
667  name
668  );
669  }
670 
671  //make sure its an object
672  fprintf(mOutputFile,
673  " if (%s->IsObject()) {\n"
674  " %s = %s->AsObject();\n"
675  " //PyIncRef(%s);\n"
676  " } else {\n"
677  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is the wrong type: %%s\", %s->TypeString());\n"
678  " return false;\n"
679  " }\n\n",
680  v,
681  name, v,
682  name,
683 
684  mName, name, v
685  );
686 
687  pop();
688  return true;
689 }
690 
691 bool ClassDecodeGenerator::ProcessObjectInline(const TiXmlElement* field)
692 {
693  char iname[16];
694  snprintf(iname, sizeof(iname), "obj_%u", ++mItemNumber);
695 
696  //make sure its an object
697  const char* v = top();
698  fprintf(mOutputFile,
699  " if (!%s->IsObject()) {\n"
700  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is the wrong type: %%s\", %s->TypeString());\n"
701  " return false;\n"
702  " }\n\n"
703  " PyObject* %s(%s->AsObject());\n\n",
704  v,
705  mName, iname, v,
706  iname, v
707  );
708 
709  char aname[32];
710  snprintf(aname, sizeof(aname), "%s->arguments()", iname);
711  push(aname);
712 
713  char tname[32];
714  snprintf(tname, sizeof(tname), "%s->type()", iname);
715  push(tname);
716 
717  if (!ParseElementChildren(field, 2))
718  return false;
719 
720  pop();
721  return true;
722 }
723 
724 bool ClassDecodeGenerator::ProcessObjectEx(const TiXmlElement* field)
725 {
726  const char* name = field->Attribute("name");
727  if (name == nullptr) {
728  std::cout << std::endl << "ClassDecodeGenerator::ProcessObjectEx field at line " << field->Row() << " is missing the name attribute, skipping.";
729  return false;
730  }
731  const char* type = field->Attribute("type");
732  if (type == nullptr) {
733  std::cout << std::endl << "ClassDecodeGenerator::ProcessObjectEx field at line " << field->Row() << " is missing the type attribute, skipping.";
734  return false;
735  }
736 
737  bool optional = false;
738  const char* optional_str = field->Attribute("optional");
739  if (optional_str != nullptr)
740  optional = str2<bool>(optional_str);
741 
742  fprintf(mOutputFile,
743  " PySafeDecRef(%s);\n",
744  name
745  );
746 
747  const char* v = top();
748  if (optional) {
749  fprintf(mOutputFile,
750  " if (%s->IsNone())\n"
751  " %s = nullptr;\n"
752  " else",
753  v,
754  name
755  );
756  }
757 
758  fprintf(mOutputFile,
759  " if (%s->IsObjectEx()) {\n"
760  " %s = (%s*)%s->AsObjectEx();\n"
761  " //PyIncRef(%s);\n"
762  " } else {\n"
763  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is the wrong type: %%s\", %s->TypeString());\n"
764  " return false;\n"
765  " }\n\n",
766  v,
767  name, type, v,
768  name,
769 
770  mName, name, v
771  );
772 
773  pop();
774  return true;
775 }
776 
777 bool ClassDecodeGenerator::ProcessTuple(const TiXmlElement* field)
778 {
779  const char* name = field->Attribute("name");
780  if (name == nullptr) {
781  std::cout << std::endl << "ClassDecodeGenerator::ProcessTuple field at line " << field->Row() << " is missing the name attribute, skipping.";
782  return false;
783  }
784 
785  bool optional = false;
786  const char* optional_str = field->Attribute("optional");
787  if (optional_str != nullptr)
788  optional = str2<bool>(optional_str);
789 
790  fprintf(mOutputFile,
791  " PySafeDecRef(%s);\n",
792  name
793  );
794 
795  const char* v = top();
796  if (optional)
797  fprintf(mOutputFile,
798  " if (%s->IsNone())\n"
799  " %s = nullptr;\n"
800  " else",
801  v,
802  name
803  );
804 
805  fprintf(mOutputFile,
806  " if (%s->IsTuple()) {\n"
807  " %s = %s->AsTuple();\n"
808  " //PyIncRef(%s);\n"
809  " } else {\n"
810  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a tuple: %%s\", %s->TypeString());\n"
811  " return false;\n"
812  " }\n\n",
813  v,
814  name, v,
815  name,
816 
817  mName, name, v
818  );
819 
820  pop();
821  return true;
822 }
823 
824 bool ClassDecodeGenerator::ProcessTupleInline(const TiXmlElement* field)
825 {
826  //first, we need to know how many elements this tuple has:
827  const TiXmlNode* i(nullptr);
828 
829  uint8 count = 0;
830  while ((i = field->IterateChildren(i))) {
831  if (i->Type() == TiXmlNode::TINYXML_ELEMENT)
832  ++count;
833  }
834 
835  char iname[16];
836  snprintf(iname, sizeof(iname), "tuple%u", ++mItemNumber);
837 
838  const char* v = top();
839  //now we can generate the tuple decl
840  fprintf(mOutputFile,
841  " if (!%s->IsTuple()) {\n"
842  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is the wrong type: %%s\", %s->TypeString());\n"
843  " return false;\n"
844  " }\n\n"
845  " PyTuple* %s(%s->AsTuple());\n"
846  " if (%s->size() != %u) {\n"
847  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is the wrong size: expected %d, but got %%lu\", %s->size());\n"
848  " return false;\n"
849  " }\n\n",
850  v,
851  mName, iname, v,
852 
853  iname, v,
854  iname, count,
855  mName, iname, count, iname
856  );
857 
858  //now we need to queue up all the storage locations for the fields
859  //need to be backward
860  char varname[64];
861  while(count-- > 0) {
862  snprintf(varname, sizeof(varname), "%s->GetItem(%u)", iname, count);
863  push(varname);
864  }
865 
866  if (!ParseElementChildren(field))
867  return false;
868 
869  pop();
870  return true;
871 }
872 
873 bool ClassDecodeGenerator::ProcessList(const TiXmlElement* field)
874 {
875  const char* name = field->Attribute("name");
876  if (name == nullptr) {
877  std::cout << std::endl << "ClassDecodeGenerator::ProcessList field at line " << field->Row() << " is missing the name attribute, skipping.";
878  return false;
879  }
880 
881  //this should be done better:
882  bool optional = false;
883  const char* optional_str = field->Attribute("optional");
884  if (optional_str != nullptr)
885  optional = str2<bool>(optional_str);
886 
887  fprintf(mOutputFile,
888  " PySafeDecRef(%s);\n",
889  name
890  );
891 
892  const char* v = top();
893  if (optional)
894  fprintf(mOutputFile,
895  " if (%s->IsNone())\n"
896  " %s = nullptr;\n"
897  " else",
898  v,
899  name
900  );
901 
902  fprintf(mOutputFile,
903  " if (%s->IsList()) {\n"
904  " %s = %s->AsList();\n"
905  " //PyIncRef(%s);\n"
906  " } else {\n"
907  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a list: %%s\", %s->TypeString());\n"
908  " return false;\n"
909  " }\n\n",
910  v,
911  name, v,
912  name,
913 
914  mName, name, v
915  );
916 
917  pop();
918  return true;
919 }
920 
921 bool ClassDecodeGenerator::ProcessListInline(const TiXmlElement* field)
922 {
923  //first, we need to know how many elements this tuple has:
924  const TiXmlNode* i(nullptr);
925 
926  uint8 count = 0;
927  while ((i = field->IterateChildren(i))) {
928  if (i->Type() == TiXmlNode::TINYXML_ELEMENT)
929  ++count;
930  }
931 
932  char iname[16];
933  snprintf(iname, sizeof(iname), "list%u", ++mItemNumber);
934 
935  const char* v = top();
936  //now we can generate the tuple decl
937  fprintf(mOutputFile,
938  " if (!%s->IsList()) {\n"
939  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a list: %%s\", %s->TypeString());\n"
940  " return false;\n"
941  " }\n\n"
942  " PyList* %s(%s->AsList());\n"
943  " if (%s->size() != %u) {\n"
944  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is the wrong size: expected %d, but got %%lu\", %s->size());\n"
945  " return false;\n"
946  " }\n\n",
947  v,
948  mName, iname, v,
949  iname, v,
950  iname, count,
951  mName, iname, count, iname
952  );
953 
954  //now we need to queue up all the storage locations for the fields
955  //need to be backward
956  char varname[64];
957  while(count-- > 0) {
958  snprintf(varname, sizeof(varname), "%s->GetItem(%u)", iname, count);
959  push(varname);
960  }
961 
962  if (!ParseElementChildren(field))
963  return false;
964 
965  pop();
966  return true;
967 }
968 
969 bool ClassDecodeGenerator::ProcessListInt(const TiXmlElement* field)
970 {
971  const char* name = field->Attribute("name");
972  if (name == nullptr) {
973  std::cout << std::endl << "ClassDecodeGenerator::ProcessListInt field at line " << field->Row() << " is missing the name attribute, skipping.";
974  return false;
975  }
976 
977  char iname[16];
978  snprintf(iname, sizeof(iname), "list_%u", ++mItemNumber);
979 
980  const char* v = top();
981  //make sure its a list
982  fprintf(mOutputFile,
983  " if (!%s->IsList()) {\n"
984  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a list: %%s\", %s->TypeString());\n"
985  " return false;\n"
986  " }\n\n"
987  " PyList* %s(%s->AsList());\n"
988  " %s.clear();\n\n"
989  " PyList::const_iterator %s_cur = %s->begin();\n"
990  " for (size_t %s_index(0); %s_cur != %s->end(); ++%s_cur, ++%s_index) {\n"
991  " if (!(*%s_cur)->IsInt()) {\n"
992  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: Element %%u in list %s is not an integer: %%s\", %s_index, (*%s_cur)->TypeString());\n"
993  " return false;\n"
994  " }\n\n"
995  " const PyInt* t = (*%s_cur)->AsInt();\n"
996  " %s.push_back(t->value());\n"
997  " }\n\n",
998  v,
999  mName, name, v,
1000 
1001  iname, v,
1002  name,
1003 
1004  iname, iname,
1005  iname, iname, iname, iname, iname,
1006  iname,
1007  mName, iname, iname, iname,
1008 
1009  iname,
1010  name
1011  );
1012 
1013  pop();
1014  return true;
1015 }
1016 
1017 bool ClassDecodeGenerator::ProcessListLong(const TiXmlElement* field)
1018 {
1019  const char* name = field->Attribute("name");
1020  if (name == nullptr) {
1021  std::cout << std::endl << "ClassDecodeGenerator::ProcessListLong field at line " << field->Row() << " is missing the name attribute, skipping.";
1022  return false;
1023  }
1024 
1025  char iname[16];
1026  snprintf(iname, sizeof(iname), "list_%u", ++mItemNumber);
1027 
1028  const char* v = top();
1029  //make sure its a list
1030  fprintf(mOutputFile,
1031  " if (!%s->IsList()) {\n"
1032  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a list: %%s\", %s->TypeString());\n"
1033  " return false;\n"
1034  " }\n\n"
1035  " PyList* %s(%s->AsList());\n"
1036  " %s.clear();\n\n"
1037  " PyList::const_iterator %s_cur = %s->begin();\n"
1038  " for (size_t %s_index(0); %s_cur != %s->end(); ++%s_cur, ++%s_index) {\n"
1039  " if ((*%s_cur)->IsLong()) {\n"
1040  " PyLong* t = (*%s_cur)->AsLong();\n"
1041  " %s.push_back(t->value());\n"
1042  " } else if ((*%s_cur)->IsInt()) {\n"
1043  " PyInt* t = (*%s_cur)->AsInt();\n"
1044  " %s.push_back(t->value());\n"
1045  " } else {\n"
1046  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: Element %%u in list %s is not a long integer: %%s\", %s_index, (*%s_cur)->TypeString());\n"
1047  " return false;\n"
1048  " }\n"
1049  " }\n\n",
1050  v,
1051  mName, name, v,
1052 
1053  iname, v,
1054  name,
1055 
1056  iname, iname,
1057  iname, iname, iname, iname, iname,
1058  iname,
1059  iname,
1060  name,
1061  iname,
1062  iname,
1063  name,
1064 
1065  mName, iname, iname, iname
1066  );
1067 
1068  pop();
1069  return true;
1070 }
1071 
1072 bool ClassDecodeGenerator::ProcessListStr(const TiXmlElement* field)
1073 {
1074  const char* name = field->Attribute("name");
1075  if (name == nullptr) {
1076  std::cout << std::endl << "ClassDecodeGenerator::ProcessListStr field at line " << field->Row() << " is missing the name attribute, skipping.";
1077  return false;
1078  }
1079 
1080  char iname[16];
1081  snprintf(iname, sizeof(iname), "list_%u", ++mItemNumber);
1082 
1083  const char* v = top();
1084  //make sure its a list
1085  fprintf(mOutputFile,
1086  " if (!%s->IsList()) {\n"
1087  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a list: %%s\", %s->TypeString());\n"
1088  " return false;\n"
1089  " }\n\n"
1090  " PyList* %s(%s->AsList());\n"
1091  " %s.clear();\n\n"
1092  " PyList::const_iterator %s_cur = %s->begin();\n"
1093  " for (uint32 %s_index(0); %s_cur != %s->end(); ++%s_cur, ++%s_index) {\n"
1094  " if (!(*%s_cur)->IsString()) {\n"
1095  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: Element %%u in list %s is not a string: %%s\", %s_index, (*%s_cur)->TypeString());\n"
1096  " return false;\n"
1097  " }\n\n"
1098  " const PyString* t = (*%s_cur)->AsString();\n"
1099  " %s.push_back(t->content());\n"
1100  " }\n\n",
1101  v,
1102  mName, name, v,
1103 
1104  iname, v,
1105  name,
1106 
1107  iname, iname,
1108  iname, iname, iname, iname, iname,
1109  iname,
1110  mName, iname, iname, iname,
1111 
1112  iname,
1113  name
1114  );
1115 
1116  pop();
1117  return true;
1118 }
1119 
1120 bool ClassDecodeGenerator::ProcessDict(const TiXmlElement* field)
1121 {
1122  const char* name = field->Attribute("name");
1123  if (name == nullptr)
1124  {
1125  std::cout << std::endl << "ClassDecodeGenerator::ProcessDict field at line " << field->Row() << " is missing the name attribute, skipping.";
1126  return false;
1127  }
1128 
1129  //this should be done better:
1130  bool optional = false;
1131  const char* optional_str = field->Attribute("optional");
1132  if (optional_str != nullptr)
1133  optional = str2<bool>(optional_str);
1134 
1135  fprintf(mOutputFile,
1136  " PySafeDecRef(%s);\n",
1137  name
1138  );
1139 
1140  const char* v = top();
1141  if (optional)
1142  fprintf(mOutputFile,
1143  " if (%s->IsNone())\n"
1144  " %s = nullptr;\n"
1145  " else",
1146  v,
1147  name
1148  );
1149 
1150  fprintf(mOutputFile,
1151  " if (%s->IsDict()) {\n"
1152  " %s = %s->AsDict();\n"
1153  " //PyIncRef(%s);\n"
1154  " } else {\n"
1155  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a dict: %%s\", %s->TypeString());\n"
1156  " return false;\n"
1157  " }\n\n",
1158  v,
1159  name, v,
1160  name,
1161 
1162  mName, name, v
1163  );
1164 
1165  pop();
1166  return true;
1167 }
1168 
1169 /*
1170  * this function could be improved quite a bit by not parsing and checking the
1171  * dictInlineEntry elements over and over again
1172  */
1173 bool ClassDecodeGenerator::ProcessDictInline(const TiXmlElement* field)
1174 {
1175  char iname[16];
1176  snprintf(iname, sizeof(iname), "dict%u", ++mItemNumber);
1177 
1178  bool soft = false;
1179  const char* soft_str = field->Attribute("soft");
1180  if (soft_str)
1181  soft = str2<bool>(soft_str);
1182 
1183  const char* v = top();
1184  //make sure its a dict
1185  fprintf(mOutputFile,
1186  " if (!%s->IsDict()) {\n"
1187  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is the wrong type: %%s\", %s->TypeString());\n"
1188  " return false;\n"
1189  " }\n\n"
1190  " PyDict* %s(%s->AsDict());\n\n",
1191  v,
1192  mName, iname, v,
1193  iname, v
1194  );
1195 
1196  //now generate the "found" flags for each expected element.
1197  const TiXmlNode* i(nullptr);
1198 
1199  bool empty = true;
1200  uint8 count = 0;
1201  while ((i = field->IterateChildren(i))) {
1202  if (i->Type() == TiXmlNode::TINYXML_ELEMENT) {
1203  const TiXmlElement* ele = i->ToElement();
1204 
1205  //we only handle dictInlineEntry elements
1206  if (strcmp(ele->Value(), "dictInlineEntry") != 0) {
1207  std::cout << std::endl << "ClassDecodeGenerator::ProcessDictInline non-dictInlineEntry in <dictInline> at line " << ele->Row() << ", ignoring.";
1208  continue;
1209  }
1210 
1211  fprintf(mOutputFile,
1212  " bool %s_%u = false;\n",
1213  iname, count
1214  );
1215  ++count;
1216 
1217  empty = false;
1218  }
1219  }
1220 
1221  fprintf(mOutputFile,
1222  "\n"
1223  );
1224 
1225  if (empty)
1226  fprintf(mOutputFile,
1227  " // %s is empty from our perspective, not enforcing though.\n",
1228  iname
1229  );
1230  else {
1231  //setup the loop...
1232  fprintf(mOutputFile,
1233  " PyDict::const_iterator %s_cur = %s->begin();\n"
1234  " for (; %s_cur != %s->end(); ++%s_cur) {\n"
1235  " if (!%s_cur->first->IsString()) {\n"
1236  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: a key in %s is the wrong type: %%s\", %s_cur->first->TypeString());\n"
1237  " return false;\n"
1238  " }\n\n"
1239  " const PyString* key_string__ = %s_cur->first->AsString();\n\n",
1240  iname, iname,
1241  iname, iname, iname,
1242  iname,
1243  mName, iname, iname,
1244 
1245  iname
1246  );
1247 
1248  count = 0;
1249  while ((i = field->IterateChildren(i))) {
1250  if (i->Type() == TiXmlNode::TINYXML_ELEMENT) {
1251  const TiXmlElement* ele = i->ToElement();
1252 
1253  //we only handle dictInlineEntry elements
1254  if (strcmp(ele->Value(), "dictInlineEntry") != 0) {
1255  std::cout << std::endl << "ClassDecodeGenerator::ProcessDictInline non-dictInlineEntry in <dictInline> at line " << ele->Row() << ", ignoring.";
1256  continue;
1257  }
1258  const char* key = ele->Attribute("key");
1259  if (key == nullptr) {
1260  std::cout << std::endl << "ClassDecodeGenerator::ProcessDictInline <dictInlineEntry> at line " << ele->Row() << " is missing the key attribute, skipping.";
1261  return false;
1262  }
1263 
1264  //conditional prefix...
1265  fprintf(mOutputFile,
1266  " if (key_string__->content() == \"%s\") {\n"
1267  " %s_%u = true;\n",
1268  key,
1269  iname, count
1270  );
1271  ++count;
1272 
1273  //now process the data part, putting the value into `varname`
1274  //TODO: figure out a reasonable way to fix the indention here...
1275  char vname[64];
1276  snprintf(vname, sizeof(vname), "%s_cur->second", iname);
1277  push(vname);
1278 
1279  if (!ParseElementChildren(ele, 1))
1280  return false;
1281 
1282  //fixed suffix...
1283  fprintf(mOutputFile,
1284  " } else\n"
1285  );
1286  }
1287  }
1288 
1289  if (soft)
1290  fprintf(mOutputFile,
1291  " {\n"
1292  " /* do nothing, soft dict */\n"
1293  " }\n"
1294  " }\n\n"
1295  );
1296  else
1297  fprintf(mOutputFile,
1298  " {\n"
1299  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: Unknown key string '%%s' in %s\", key_string__->content().c_str());\n"
1300  " return false;\n"
1301  " }\n"
1302  " }\n\n",
1303  mName, iname
1304  );
1305 
1306  //finally, check the "found" flags for each expected element.
1307  count = 0;
1308  while ((i = field->IterateChildren(i))) {
1309  if(i->Type() == TiXmlNode::TINYXML_ELEMENT) {
1310  const TiXmlElement* ele = i->ToElement();
1311 
1312  //we only handle dictInlineEntry elements
1313  if (strcmp(ele->Value(), "dictInlineEntry") != 0) {
1314  std::cout << std::endl << "ClassDecodeGenerator::ProcessDictInline non-dictInlineEntry in <dictInline> at line " << ele->Row() << ", ignoring.";
1315  continue;
1316  }
1317  const char* key = ele->Attribute("key");
1318  if (key == nullptr) {
1319  std::cout << std::endl << "ClassDecodeGenerator::ProcessDictInline <dictInlineEntry> at line " << ele->Row() << " is missing the key attribute, skipping.";
1320  return false;
1321  }
1322 
1323  fprintf(mOutputFile,
1324  " if (!%s_%u) {\n"
1325  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: Missing dict entry '%s' in %s\");\n"
1326  " return false;\n"
1327  " }\n\n",
1328  iname, count,
1329  mName, key, iname
1330  );
1331  ++count;
1332  }
1333  }
1334  }
1335 
1336  pop();
1337  return true;
1338 }
1339 
1340 bool ClassDecodeGenerator::ProcessDictRaw(const TiXmlElement* field)
1341 {
1342  const char* name = field->Attribute("name");
1343  if (name == nullptr) {
1344  std::cout << std::endl << "ClassDecodeGenerator::ProcessDictRaw field at line " << field->Row() << " is missing the name attribute, skipping.";
1345  return false;
1346  }
1347 
1348  const char* key = field->Attribute("key");
1349  if (key == nullptr) {
1350  std::cout << std::endl << "ClassDecodeGenerator::ProcessDictRaw field at line " << field->Row() << " is missing the key attribute, skipping.";
1351  return false;
1352  }
1353  const char* value = field->Attribute("value");
1354  if (value == nullptr) {
1355  std::cout << std::endl << "ClassDecodeGenerator::ProcessDictRaw field at line " << field->Row() << " is missing the value attribute, skipping.";
1356  return false;
1357  }
1358  const char* pykey = field->Attribute("pykey");
1359  if (pykey == nullptr) {
1360  std::cout << std::endl << "ClassDecodeGenerator::ProcessDictRaw field at line " << field->Row() << " is missing the pykey attribute, skipping.";
1361  return false;
1362  }
1363  const char* pyvalue = field->Attribute("pyvalue");
1364  if (pyvalue == nullptr) {
1365  std::cout << std::endl << "ClassDecodeGenerator::ProcessDictRaw field at line " << field->Row() << " is missing the pyvalue attribute, skipping.";
1366  return false;
1367  }
1368 
1369  char iname[16];
1370  snprintf(iname, sizeof(iname), "dict_%u", ++mItemNumber);
1371 
1372  const char* v = top();
1373  fprintf(mOutputFile,
1374  " if (!%s->IsDict()) {\n"
1375  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a dict: %%s\", %s->TypeString());\n"
1376  " return false;\n"
1377  " }\n\n"
1378  " PyDict* %s(%s->AsDict());\n"
1379  " %s.clear();\n\n"
1380  " PyDict::const_iterator %s_cur = %s->begin();\n"
1381  " for (size_t %s_index(0); %s_cur != %s->end(); ++%s_cur, ++%s_index) {\n"
1382  " if (!%s_cur->first->Is%s()) {\n"
1383  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: Key %%u in dict %s is not %s: %%s\", %s_index, %s_cur->first->TypeString());\n"
1384  " return false;\n"
1385  " }\n\n"
1386  " const Py%s* k = %s_cur->first->As%s();\n"
1387  " if (!%s_cur->second->Is%s()) {\n"
1388  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: Value %%d in dict %s is not %s: %%s\", %s_index, %s_cur->second->TypeString());\n"
1389  " return false;\n"
1390  " }\n\n"
1391  " const Py%s *v = %s_cur->second->As%s();\n"
1392  " %s[ k->value() ] = v->value();\n"
1393  " }\n\n",
1394  v,
1395  mName, name, v,
1396 
1397  iname, v,
1398  name,
1399 
1400  iname, iname,
1401  iname, iname, iname, iname, iname,
1402  iname, pykey,
1403  mName, iname, pykey, iname, iname,
1404 
1405  pykey, iname, pykey,
1406  iname, pyvalue,
1407  mName, iname, pyvalue, iname, iname,
1408 
1409  pyvalue, iname, pyvalue,
1410  name
1411  );
1412 
1413  pop();
1414  return true;
1415 }
1416 
1417 bool ClassDecodeGenerator::ProcessDictInt(const TiXmlElement* field)
1418 {
1419  const char* name = field->Attribute("name");
1420  if (name == nullptr) {
1421  std::cout << std::endl << "ClassDecodeGenerator::ProcessDictInt field at line " << field->Row() << " is missing the name attribute, skipping.";
1422  return false;
1423  }
1424 
1425  char iname[16];
1426  snprintf(iname, sizeof(iname), "dict_%u", ++mItemNumber);
1427 
1428  const char* v = top();
1429  fprintf(mOutputFile,
1430  " if (!%s->IsDict()) {\n"
1431  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a dict: %%s\", %s->TypeString());\n"
1432  " return false;\n"
1433  " }\n\n"
1434  " PyDict* %s(%s->AsDict());\n"
1435  " %s.clear();\n\n"
1436  " PyDict::const_iterator %s_cur = %s->begin();\n"
1437  " for (size_t %s_index(0); %s_cur != %s->end(); ++%s_cur, ++%s_index) {\n"
1438  " if (!%s_cur->first->IsInt()) {\n"
1439  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: Key %%u in dict %s is not an integer: %%s\", %s_index, %s_cur->first->TypeString());\n"
1440  " return false;\n"
1441  " }\n\n"
1442  " const PyInt* k = %s_cur->first->AsInt();\n"
1443  " %s[ k->value() ] = %s_cur->second->Clone();\n"
1444  " }\n\n",
1445  v,
1446  mName, name, v,
1447 
1448  iname, v,
1449  name,
1450 
1451  iname, iname,
1452  iname, iname, iname, iname, iname,
1453  iname,
1454  mName, iname, iname, iname,
1455  iname,
1456  name, iname
1457  );
1458 
1459  pop();
1460  return true;
1461 }
1462 
1463 bool ClassDecodeGenerator::ProcessDictStr(const TiXmlElement* field)
1464 {
1465  const char* name = field->Attribute("name");
1466  if (name == nullptr) {
1467  std::cout << std::endl << "ClassDecodeGenerator::ProcessDictStr field at line " << field->Row() << " is missing the name attribute, skipping.";
1468  return false;
1469  }
1470 
1471  char iname[16];
1472  snprintf(iname, sizeof(iname), "dict_%u", ++mItemNumber);
1473 
1474  const char* v = top();
1475  fprintf(mOutputFile,
1476  " if (!%s->IsDict()) {\n"
1477  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a dict: %%s\", %s->TypeString());\n"
1478  " return false;\n"
1479  " }\n\n"
1480  " PyDict* %s(%s->AsDict());\n"
1481  " %s.clear();\n\n"
1482  " PyDict::const_iterator %s_cur = %s->begin();\n"
1483  " for (size_t %s_index(0); %s_cur != %s->end(); ++%s_cur, ++%s_index) {\n"
1484  " if (!%s_cur->first->IsString()) {\n"
1485  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: Key %%u in dict %s is not a string: %%s\", %s_index, %s_cur->first->TypeString());\n"
1486  " return false;\n"
1487  " }\n\n"
1488  " const PyString* k = %s_cur->first->AsString();\n"
1489  " %s[ k->content() ] = %s_cur->second->Clone();\n"
1490  " }\n\n",
1491  v,
1492  mName, name, v,
1493 
1494  iname, v,
1495  name,
1496 
1497  iname, iname,
1498  iname, iname, iname, iname, iname,
1499  iname,
1500  mName, iname, iname, iname,
1501  iname,
1502  name, iname
1503  );
1504 
1505  pop();
1506  return true;
1507 }
1508 
1509 bool ClassDecodeGenerator::ProcessSubStreamInline(const TiXmlElement* field)
1510 {
1511  char iname[16];
1512  snprintf(iname, sizeof(iname), "ss_%u", ++mItemNumber);
1513 
1514  //make sure its a substream
1515  const char* v = top();
1516  fprintf(mOutputFile,
1517  " if (!%s->IsSubStream()) {\n"
1518  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a substream: %%s\", %s->TypeString());\n"
1519  " return false;\n"
1520  " }\n\n"
1521  " PySubStream* %s(%s->AsSubStream());\n"
1522  " //make sure its decoded\n"
1523  " %s->DecodeData();\n"
1524  " if (!%s->decoded()) {\n"
1525  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: Unable to decode %s\");\n"
1526  " return false;\n"
1527  " }\n\n",
1528  v,
1529  mName, iname, v,
1530  iname, v,
1531  iname,
1532  iname,
1533  mName, iname
1534  );
1535 
1536  char ssname[32];
1537  snprintf(ssname, sizeof(ssname), "%s->decoded()", iname);
1538  push(ssname);
1539 
1540  //Decode the sub-element
1541  if (!ParseElementChildren(field, 1))
1542  return false;
1543 
1544  pop();
1545  return true;
1546 }
1547 
1548 bool ClassDecodeGenerator::ProcessSubStructInline(const TiXmlElement* field)
1549 {
1550  char iname[16];
1551  snprintf(iname, sizeof(iname), "ss_%u", ++mItemNumber);
1552 
1553  //make sure its a substruct
1554  const char* v = top();
1555  fprintf(mOutputFile,
1556  " if (!%s->IsSubStruct()) {\n"
1557  " _log(XMLP__DECODE_ERROR, \"Decode %s failed: %s is not a substruct: %%s\", %s->TypeString());\n"
1558  " return false;\n"
1559  " }\n\n"
1560  " PySubStruct* %s(%s->AsSubStruct());\n\n",
1561  v,
1562  mName, iname, v,
1563  iname, v
1564  );
1565 
1566  char ssname[32];
1567  snprintf(ssname, sizeof(ssname), "%s->sub()", iname);
1568  push(ssname);
1569 
1570  //Decode the sub-element
1571  if (!ParseElementChildren(field, 1))
1572  return false;
1573 
1574  pop();
1575  return true;
1576 }
bool ProcessElementDef(const TiXmlElement *field)
unsigned __int8 uint8
Definition: eve-compat.h:46
bool ProcessObjectEx(const TiXmlElement *field)
bool ProcessSubStreamInline(const TiXmlElement *field)
bool ProcessRaw(const TiXmlElement *field)
bool ParseElement(const TiXmlElement *element) const
Parses element using registered parsers.
Definition: XMLParser.cpp:61
#define _log(type, fmt,...)
Definition: logsys.h:124
bool ProcessDictRaw(const TiXmlElement *field)
bool ProcessListStr(const TiXmlElement *field)
bool ProcessBuffer(const TiXmlElement *field)
bool ProcessReal(const TiXmlElement *field)
void RegisterProcessors()
Definition: Generator.cpp:44
void push(const char *v)
bool ProcessObjectInline(const TiXmlElement *field)
bool ProcessListInt(const TiXmlElement *field)
ClassDecodeGenerator(FILE *outputFile=NULL)
bool ProcessWStringInline(const TiXmlElement *field)
bool ProcessDict(const TiXmlElement *field)
FILE * mOutputFile
Definition: Generator.h:108
#define snprintf
Definition: eve-compat.h:184
bool ProcessListInline(const TiXmlElement *field)
bool ProcessLong(const TiXmlElement *field)
bool str2< bool >(const char *str)
Converts string to boolean.
Definition: str2conv.cpp:31
bool ProcessDictInline(const TiXmlElement *field)
bool ProcessNone(const TiXmlElement *field)
bool ProcessElementPtr(const TiXmlElement *field)
bool ProcessElement(const TiXmlElement *field)
bool ProcessString(const TiXmlElement *field)
bool ProcessListLong(const TiXmlElement *field)
bool ProcessTuple(const TiXmlElement *field)
static const char * GetEncodeType(const TiXmlElement *element)
Obtains encode type of given element.
Definition: Generator.cpp:86
bool ProcessInt(const TiXmlElement *field)
const char * top() const
bool ProcessBool(const TiXmlElement *field)
int main(int argc, char *argv[])
bool ProcessDictInt(const TiXmlElement *field)
bool ProcessTokenInline(const TiXmlElement *field)
Generic class for eve-xmlpktgen's generators.
Definition: Generator.h:37
bool ProcessList(const TiXmlElement *field)
bool ParseElementChildren(const TiXmlElement *element, size_t max=0) const
Parses element's children using registered parsers.
Definition: XMLParser.cpp:72
bool ProcessStringInline(const TiXmlElement *field)
bool ProcessWString(const TiXmlElement *field)
bool ProcessSubStructInline(const TiXmlElement *field)
typeID Spawn an NPC with the specified type text Search for items matching the specified query() type() key(value)-Send an OnRemoteMessage" ) COMMAND( setbpattr
bool ProcessTupleInline(const TiXmlElement *field)
bool ProcessObject(const TiXmlElement *field)
bool ProcessDictStr(const TiXmlElement *field)
bool ProcessToken(const TiXmlElement *field)