liblcf
reader_struct.h
Go to the documentation of this file.
1 /*
2  * This file is part of liblcf. Copyright (c) 2021 liblcf authors.
3  * https://github.com/EasyRPG/liblcf - https://easyrpg.org
4  *
5  * liblcf is Free/Libre Open Source Software, released under the MIT License.
6  * For the full copyright and license information, please view the COPYING
7  * file that was distributed with this source code.
8  */
9 
10 #ifndef LCF_READER_STRUCT_H
11 #define LCF_READER_STRUCT_H
12 
13 #ifdef LCF_DEBUG_TRACE
14 #include <iostream>
15 #endif
16 #include <string>
17 #include <vector>
18 #include <map>
19 #include <memory>
20 #include <cstring>
21 #include <cstdlib>
22 #include <cinttypes>
23 #include "lcf/dbstring.h"
24 #include "lcf/reader_lcf.h"
25 #include "lcf/writer_lcf.h"
26 #include "lcf/reader_xml.h"
27 #include "lcf/writer_xml.h"
28 #include "lcf/rpg/eventpagecondition.h"
29 #include "lcf/rpg/trooppagecondition.h"
30 #include "lcf/rpg/terrain.h"
31 #include "lcf/rpg/equipment.h"
32 #include "lcf/rpg/parameters.h"
33 #include "lcf/rpg/eventcommand.h"
34 #include "lcf/rpg/movecommand.h"
35 #include "lcf/rpg/treemap.h"
36 #include "lcf/rpg/rect.h"
37 #include "lcf/rpg/savepicture.h"
38 #include "lcf/rpg/terms.h"
39 
40 namespace lcf {
41 
42 // Forward declarations
43 
44 template <class T>
45 class Struct;
46 
47 // Type categories
48 
49 struct Category {
50  enum Index {
55  Void
56  };
57 };
58 
59 template <class T>
60 struct TypeCategory {
62 };
63 
64 template <> struct TypeCategory<rpg::TroopPageCondition::Flags> { static const Category::Index value = Category::Flags; };
65 template <> struct TypeCategory<rpg::EventPageCondition::Flags> { static const Category::Index value = Category::Flags; };
66 template <> struct TypeCategory<rpg::Terrain::Flags> { static const Category::Index value = Category::Flags; };
67 template <> struct TypeCategory<rpg::SavePicture::Flags> { static const Category::Index value = Category::Flags; };
68 
69 template <> struct TypeCategory<rpg::Equipment> { static const Category::Index value = Category::RawStruct; };
70 template <> struct TypeCategory<rpg::EventCommand> { static const Category::Index value = Category::RawStruct; };
71 template <> struct TypeCategory<rpg::MoveCommand> { static const Category::Index value = Category::RawStruct; };
72 template <> struct TypeCategory<rpg::Parameters> { static const Category::Index value = Category::RawStruct; };
73 template <> struct TypeCategory<rpg::TreeMap> { static const Category::Index value = Category::RawStruct; };
74 template <> struct TypeCategory<rpg::Rect> { static const Category::Index value = Category::RawStruct; };
75 
76 template <> struct TypeCategory<int8_t> { static const Category::Index value = Category::Primitive; };
77 template <> struct TypeCategory<uint8_t> { static const Category::Index value = Category::Primitive; };
78 template <> struct TypeCategory<int16_t> { static const Category::Index value = Category::Primitive; };
79 template <> struct TypeCategory<uint32_t> { static const Category::Index value = Category::Primitive; };
80 template <> struct TypeCategory<int32_t> { static const Category::Index value = Category::Primitive; };
81 template <> struct TypeCategory<bool> { static const Category::Index value = Category::Primitive; };
82 template <> struct TypeCategory<double> { static const Category::Index value = Category::Primitive; };
83 template <> struct TypeCategory<std::string> { static const Category::Index value = Category::Primitive; };
84 template <> struct TypeCategory<DBString> { static const Category::Index value = Category::Primitive; };
85 template <> struct TypeCategory<DBBitArray> { static const Category::Index value = Category::Primitive; };
86 
87 template <class T>
88 struct TypeCategory<std::vector<T>> {
90 };
91 
95 template <class T, Category::Index cat = TypeCategory<T>::value>
96 struct TypeReader {};
97 
98 
103 template <class T>
104 struct TypeReader<T, Category::Void> {
105  static void ReadLcf(T&, LcfReader& stream, uint32_t length) {
106  stream.Seek(length, LcfReader::FromCurrent);
107  }
108  static void WriteLcf(const T&, LcfWriter&) {
109  }
110  static int LcfSize(const T&, LcfWriter&) {
111  return 0;
112  }
113  static void WriteXml(const T&, XmlWriter&) {
114  }
115  static void BeginXml(T&, XmlReader&) {
116  }
117  static void ParseXml(T& /* ref */, const std::string& /* data */) {
118  //no-op
119  }
120 };
121 
125 template <class T>
126 struct RawStruct {
127  static void ReadLcf(T& ref, LcfReader& stream, uint32_t length);
128  static void WriteLcf(const T& ref, LcfWriter& stream);
129  static int LcfSize(const T& ref, LcfWriter& stream);
130  static void WriteXml(const T& ref, XmlWriter& stream);
131  static void BeginXml(T& ref, XmlReader& stream);
132 };
133 
134 template <class T>
136  static void ReadLcf(T& ref, LcfReader& stream, uint32_t length) {
137  RawStruct<T>::ReadLcf(ref, stream, length);
138  }
139  static void WriteLcf(const T& ref, LcfWriter& stream) {
140  RawStruct<T>::WriteLcf(ref, stream);
141  }
142  static int LcfSize(const T& ref, LcfWriter& stream) {
143  return RawStruct<T>::LcfSize(ref, stream);
144  }
145  static void WriteXml(const T& ref, XmlWriter& stream) {
146  RawStruct<T>::WriteXml(ref, stream);
147  }
148  static void BeginXml(T& ref, XmlReader& stream) {
149  RawStruct<T>::BeginXml(ref, stream);
150  }
151  static void ParseXml(T& /* ref */, const std::string& /* data */) {
152  //no-op
153  }
154 };
155 
159 template <class T>
160 struct LcfSizeT {
161  static const uint32_t value = sizeof(T);
162 };
163 
167 template <>
168 struct LcfSizeT<bool> {
169  static const uint32_t value = 1;
170 };
171 
175 template <class T>
176 struct Primitive {
177  static void ReadLcf(T& ref, LcfReader& stream, uint32_t length) {
178  int dif = 0;
179  // FIXME: Bug #174
180  if (length != LcfSizeT<T>::value) {
181  dif = length - LcfSizeT<T>::value;
182  fprintf(stderr, "Reading Primitive of incorrect size %" PRIu32 " (expected %" PRIu32 ") at %" PRIX32 "\n",
183  length, LcfSizeT<T>::value, stream.Tell());
184  }
185 
186  stream.Read(ref);
187 #ifdef LCF_DEBUG_TRACE
188  DebugPrint(ref);
189 #endif
190 
191  if (dif != 0) {
192  // Fix incorrect read pointer position
193 #ifdef LCF_DEBUG_TRACE
194  printf("Invalid %s at %X\n", typeid(T).name(), stream.Tell());
195 #endif
196  stream.Seek(dif, LcfReader::FromCurrent);
197  }
198  }
199  static void WriteLcf(const T& ref, LcfWriter& stream) {
200  stream.Write(ref);
201  }
202  static int LcfSize(const T& /* ref */, LcfWriter& /* stream */) {
203  return LcfSizeT<T>::value;
204  }
205  static void WriteXml(const T& ref, XmlWriter& stream) {
206  stream.Write(ref);
207  }
208  static void ParseXml(T& ref, const std::string& data) {
209  XmlReader::Read(ref, data);
210  }
211  private:
212 #ifdef LCF_DEBUG_TRACE
213  template <typename U>
214  static void DebugPrint(U& ref) {
215  std::cout << ref << '\n';
216  }
217  static void DebugPrint(int8_t ref) {
218  std::cout << (int)ref << '\n';
219  }
220  static void DebugPrint(uint8_t ref) {
221  std::cout << (int)ref << '\n';
222  }
223 #endif
224 };
225 
229 template <class T>
230 struct Primitive<std::vector<T>> {
231  static void ReadLcf(std::vector<T>& ref, LcfReader& stream, uint32_t length) {
232  stream.Read(ref, length);
233 #ifdef LCF_DEBUG_TRACE
234  typename std::vector<T>::iterator it;
235  printf(" ");
236  for (it = ref.begin(); it != ref.end(); ++it) {
237  printf("%d, ", static_cast<int>(*it));
238  }
239  printf("\n");
240 #endif
241  }
242  static void WriteLcf(const std::vector<T>& ref, LcfWriter& stream) {
243  stream.Write(ref);
244  }
245  static int LcfSize(const std::vector<T>& ref, LcfWriter& /* stream */) {
246  return LcfSizeT<T>::value * ref.size();
247  }
248  static void WriteXml(const std::vector<T>& ref, XmlWriter& stream) {
249  stream.Write(ref);
250  }
251  static void ParseXml(std::vector<T>& ref, const std::string& data) {
252  XmlReader::Read(ref, data);
253  }
254 };
255 
259 template <>
260 struct Primitive<int32_t> {
261  static void ReadLcf(int32_t& ref, LcfReader& stream, uint32_t length) {
262  if (length >= 1 && length <= 5) {
263  ref = stream.ReadInt();
264 #ifdef LCF_DEBUG_TRACE
265  printf(" %d\n", ref);
266 #endif
267  } else {
268  ref = 0;
269 #ifdef LCF_DEBUG_TRACE
270  printf("Invalid integer at %X\n", stream.Tell());
271 #endif
272  stream.Seek(length, LcfReader::FromCurrent);
273  }
274 
275  }
276  static void WriteLcf(const int32_t& ref, LcfWriter& stream) {
277  stream.WriteInt(ref);
278  }
279  static int LcfSize(const int32_t& ref, LcfWriter& /* stream */) {
280  return LcfReader::IntSize(ref);
281  }
282  static void WriteXml(const int32_t& ref, XmlWriter& stream) {
283  stream.WriteInt(ref);
284  }
285  static void ParseXml(int32_t& ref, const std::string& data) {
286  XmlReader::Read(ref, data);
287  }
288 };
289 
293 template <>
294 struct Primitive<std::string> {
295  static void ReadLcf(std::string& ref, LcfReader& stream, uint32_t length) {
296  stream.ReadString(ref, length);
297 #ifdef LCF_DEBUG_TRACE
298  printf(" %s\n", ref.c_str());
299 #endif
300  }
301  static void WriteLcf(const std::string& ref, LcfWriter& stream) {
302  stream.Write(ref);
303  }
304  static int LcfSize(const std::string& ref, LcfWriter& stream) {
305  return stream.Decode(ref).size();
306  }
307  static void WriteXml(const std::string& ref, XmlWriter& stream) {
308  stream.Write(ref);
309  }
310  static void ParseXml(std::string& ref, const std::string& data) {
311  XmlReader::Read(ref, data);
312  }
313 };
314 
318 template <>
319 struct Primitive<DBString> {
320  static void ReadLcf(DBString& ref, LcfReader& stream, uint32_t length) {
321  stream.ReadString(ref, length);
322 #ifdef LCF_DEBUG_TRACE
323  printf(" %s\n", ref.c_str());
324 #endif
325  }
326  static void WriteLcf(const DBString& ref, LcfWriter& stream) {
327  stream.Write(ref);
328  }
329  static int LcfSize(const DBString& ref, LcfWriter& stream) {
330  return stream.Decode(ref).size();
331  }
332  static void WriteXml(const DBString& ref, XmlWriter& stream) {
333  stream.Write(ref);
334  }
335  static void ParseXml(DBString& ref, const std::string& data) {
336  XmlReader::Read(ref, data);
337  }
338 };
339 
343 template <>
344 struct Primitive<DBBitArray> {
345  static void ReadLcf(DBBitArray& ref, LcfReader& stream, uint32_t length) {
346  stream.ReadBits(ref, length);
347 #ifdef LCF_DEBUG_TRACE
348  printf(" ");
349  for (auto& b: ref) {
350  print("%d", static_cast<int>(b));
351  }
352  printf("\n");
353 #endif
354  }
355  static void WriteLcf(const DBBitArray& ref, LcfWriter& stream) {
356  stream.Write(ref);
357  }
358  static int LcfSize(const DBBitArray& ref, LcfWriter& stream) {
359  (void)stream;
360  return ref.size();
361  }
362  static void WriteXml(const DBBitArray& ref, XmlWriter& stream) {
363  stream.Write(ref);
364  }
365  static void ParseXml(DBBitArray& ref, const std::string& data) {
366  XmlReader::Read(ref, data);
367  }
368 };
369 
370 
371 
375 template <class T>
377  static void ReadLcf(T& ref, LcfReader& stream, uint32_t length) {
378  Primitive<T>::ReadLcf(ref, stream, length);
379  }
380  static void WriteLcf(const T& ref, LcfWriter& stream) {
381  Primitive<T>::WriteLcf(ref, stream);
382  }
383  static int LcfSize(const T& ref, LcfWriter& stream) {
384  return Primitive<T>::LcfSize(ref, stream);
385  }
386  static void WriteXml(const T& ref, XmlWriter& stream) {
387  Primitive<T>::WriteXml(ref, stream);
388  }
389  static void BeginXml(T& /* ref */, XmlReader& /* stream */) {
390  // no-op
391  }
392  static void ParseXml(T& ref, const std::string& data) {
393  Primitive<T>::ParseXml(ref, data);
394  }
395 };
396 
400 template <class S>
401 struct Field {
402  typedef S struct_type;
403 
404  const char* const name;
405  int id;
407  bool is2k3;
408 
409  virtual void ReadLcf(S& obj, LcfReader& stream, uint32_t length) const = 0;
410  virtual void WriteLcf(const S& obj, LcfWriter& stream) const = 0;
411  virtual int LcfSize(const S& obj, LcfWriter& stream) const = 0;
412  virtual bool IsDefault(const S& obj, const S& ref, bool is2k3) const = 0;
413  virtual void WriteXml(const S& obj, XmlWriter& stream) const = 0;
414  virtual void BeginXml(S& obj, XmlReader& stream) const = 0;
415  virtual void ParseXml(S& obj, const std::string& data) const = 0;
416 
417  bool isPresentIfDefault(bool db_is2k3) const {
418  if (std::is_same<S,rpg::Terms>::value && db_is2k3 && (id == 0x3 || id == 0x1)) {
419  //Special case - only known fields that are 2k specific and not
420  //written to a 2k3 db if defaulted.
421  return false;
422  }
423  return present_if_default;
424  }
425 
426  Field(int id, const char* name, bool present_if_default, bool is2k3) :
428 };
429 
433 template <class S, class T>
434 struct TypedField : public Field<S> {
435  T S::*ref;
436 
437  void ReadLcf(S& obj, LcfReader& stream, uint32_t length) const {
438  TypeReader<T>::ReadLcf(obj.*ref, stream, length);
439  }
440  void WriteLcf(const S& obj, LcfWriter& stream) const {
441  TypeReader<T>::WriteLcf(obj.*ref, stream);
442  }
443  int LcfSize(const S& obj, LcfWriter& stream) const {
444  return TypeReader<T>::LcfSize(obj.*ref, stream);
445  }
446  void WriteXml(const S& obj, XmlWriter& stream) const {
447  stream.BeginElement(this->name);
448  TypeReader<T>::WriteXml(obj.*ref, stream);
449  stream.EndElement(this->name);
450  }
451  void BeginXml(S& obj, XmlReader& stream) const {
452  TypeReader<T>::BeginXml(obj.*ref, stream);
453  }
454  void ParseXml(S& obj, const std::string& data) const {
455  TypeReader<T>::ParseXml(obj.*ref, data);
456  }
457  bool IsDefault(const S& a, const S& b, bool) const {
458  return a.*ref == b.*ref;
459  }
460 
461  TypedField(T S::*ref, int id, const char* name, bool present_if_default, bool is2k3) :
463 };
464 
469 template <typename S, typename T>
470 struct DatabaseVersionField : public TypedField<S,T> {
471 
473 
474  int LcfSize(const S& obj, LcfWriter& stream) const {
475  //If db version is 0, it's like a "version block" is not present.
476  if ((obj.*(this->ref)) == 0) {
477  return 0;
478  }
479  return TypedField<S,T>::LcfSize(obj, stream);
480  }
481  bool IsDefault(const S& a, const S& b, bool is2k3) const {
482  if (is2k3) {
483  //DB Version always present in 2k3 db
484  return false;
485  }
486  //Only present if not 0 in 2k db.
487  return TypedField<S,T>::IsDefault(a, b, is2k3);
488  }
489 };
490 
495 template <typename S>
496 struct EmptyField : public Field<S> {
497 
498  using Field<S>::Field;
499 
500  void ReadLcf(S& /* obj */, LcfReader& /* stream */, uint32_t /* length */) const { }
501  void WriteLcf(const S& /* obj */, LcfWriter& /* stream */) const { }
502  int LcfSize(const S& /* obj */, LcfWriter& /* stream */) const {
503  //This is always an "empty block"
504  return 0;
505  }
506  void WriteXml(const S& /* obj */, XmlWriter& /* stream */) const { }
507  void BeginXml(S& /* obj */, XmlReader& /* stream */) const { }
508  void ParseXml(S& /* obj */, const std::string& /* data */) const { }
509 
510  bool IsDefault(const S& /* a */, const S& /* b */, bool) const {
511  return true;
512  }
513 
514 };
515 
516 
517 
521 template <class S, class T>
522 struct SizeField : public Field<S> {
523  const T S::*ref;
524 
525  void ReadLcf(S& /* obj */, LcfReader& stream, uint32_t length) const {
526  int32_t dummy;
527  TypeReader<int32_t>::ReadLcf(dummy, stream, length);
528  }
529  void WriteLcf(const S& obj, LcfWriter& stream) const {
530  int size = TypeReader<T>::LcfSize(obj.*ref, stream);
531  TypeReader<int32_t>::WriteLcf(size, stream);
532  }
533  int LcfSize(const S& obj, LcfWriter& stream) const {
534  int size = TypeReader<T>::LcfSize(obj.*ref, stream);
535  return LcfReader::IntSize(size);
536  }
537  void WriteXml(const S& /* obj */, XmlWriter& /* stream */) const {
538  // no-op
539  }
540  void BeginXml(S& /* obj */, XmlReader& /* stream */) const {
541  // no-op
542  }
543  void ParseXml(S& /* obj */, const std::string& /* data */) const {
544  // no-op
545  }
546  bool IsDefault(const S& a, const S& b, bool) const {
547  return (a.*ref).size() == (b.*ref).size();
548  }
549 
550  SizeField(const T S::*ref, int id, bool present_if_default, bool is2k3) :
551  Field<S>(id, "", present_if_default, is2k3), ref(ref) {}
552 };
553 
554 
558 template <class S, class T>
559 struct CountField : public SizeField<S,T> {
560 
562 
563  void WriteLcf(const S& obj, LcfWriter& stream) const {
564  int size = (obj.*(this->ref)).size();
565  TypeReader<int32_t>::WriteLcf(size, stream);
566  }
567  int LcfSize(const S& obj, LcfWriter& /* stream */) const {
568  int size = (obj.*(this->ref)).size();
569  return LcfReader::IntSize(size);
570  }
571 };
572 
576 template <class T>
577 struct IDChecker {
578  typedef char no;
579  typedef int yes;
580 
581  template <typename U, U> struct type_check;
582  template <class C>
584  template <class C>
585  static no check(...);
586 
587  static const bool value = sizeof(check<T>(0)) == sizeof(yes);
588 };
589 
590 // ID reader for Struct class
591 
592 template <class S, bool T>
593 struct IDReaderT {
594 };
595 
596 template <class S>
597 struct IDReaderT<S, true> {
598  static void ReadID(S& obj, LcfReader& stream) {
599  obj.ID = stream.ReadInt();
600  }
601  static void WriteID(const S& obj, LcfWriter& stream) {
602  stream.WriteInt(obj.ID);
603  }
604  static int IDSize(const S& obj) {
605  return LcfReader::IntSize(obj.ID);
606  }
607  static void WriteXmlTag(const S& obj, const std::string& name, XmlWriter& stream) {
608  stream.BeginElement(name, obj.ID);
609  }
610  static void ReadIDXml(S& obj, const char** atts) {
611  for (int i = 0; atts[i] != NULL && atts[i + 1] != NULL; i += 2) {
612  if (strcmp(atts[i], "id") == 0)
613  obj.ID = atoi(atts[i + 1]);
614  }
615  }
616 };
617 
618 template <class S>
619 struct IDReaderT<S, false> {
620  static void ReadID(S& /* obj */, LcfReader& /* stream */) {}
621  static void WriteID(const S& /* obj */, LcfWriter& /* stream */) {}
622  static int IDSize(const S& /* obj */) { return 0; }
623  static void WriteXmlTag(const S& /* obj */, const std::string& name, XmlWriter& stream) {
624  stream.BeginElement(name);
625  }
626  static void ReadIDXml(S& /* obj */, const char** /* atts */) {}
627 };
628 
630  bool operator() (const char* const& lhs, const char* const& rhs) const {
631  return strcmp(lhs, rhs) < 0;
632  }
633 };
634 
635 // Struct class template
636 
637 template <class S>
638 class Struct {
639 private:
640  typedef std::map<int, const Field<S>* > field_map_type;
641  typedef std::map<const char* const, const Field<S>*, StringComparator> tag_map_type;
643  static const Field<S>* fields[];
646  static const char* const name;
647 
648  static void MakeFieldMap();
649  static void MakeTagMap();
650 
651  template <class T> friend class StructXmlHandler;
652  template <class T> friend class StructVectorXmlHandler;
653  template <class T> friend class StructFieldXmlHandler;
654 
655 public:
656  static void ReadLcf(S& obj, LcfReader& stream);
657  static void WriteLcf(const S& obj, LcfWriter& stream);
658  static int LcfSize(const S& obj, LcfWriter& stream);
659  static void WriteXml(const S& obj, XmlWriter& stream);
660  static void BeginXml(S& obj, XmlReader& stream);
661 
662  static void ReadLcf(std::vector<S>& obj, LcfReader& stream);
663  static void WriteLcf(const std::vector<S>& obj, LcfWriter& stream);
664  static int LcfSize(const std::vector<S>& obj, LcfWriter& stream);
665  static void WriteXml(const std::vector<S>& obj, XmlWriter& stream);
666  static void BeginXml(std::vector<S>& obj, XmlReader& stream);
667 };
668 
669 template <class S>
670 std::map<int, const Field<S>* > Struct<S>::field_map;
671 
672 template <class S>
673 std::map<const char* const, const Field<S>*, StringComparator> Struct<S>::tag_map;
674 
678 template <class T>
680  static void ReadLcf(T& ref, LcfReader& stream, uint32_t /* length */) {
681  Struct<T>::ReadLcf(ref, stream);
682  }
683  static void WriteLcf(const T& ref, LcfWriter& stream) {
684  Struct<T>::WriteLcf(ref, stream);
685  }
686  static int LcfSize(const T& ref, LcfWriter& stream) {
687  return Struct<T>::LcfSize(ref, stream);
688  }
689  static void WriteXml(const T& ref, XmlWriter& stream) {
690  Struct<T>::WriteXml(ref, stream);
691  }
692  static void BeginXml(T& ref, XmlReader& stream) {
693  Struct<T>::BeginXml(ref, stream);
694  }
695  static void ParseXml(T& /* ref */, const std::string& /* data */) {
696  // no-op
697  }
698 };
699 
700 template <class T>
701 struct TypeReader<std::vector<T>, Category::Struct> {
702  static void ReadLcf(std::vector<T>& ref, LcfReader& stream, uint32_t /* length */) {
703  Struct<T>::ReadLcf(ref, stream);
704  }
705  static void WriteLcf(const std::vector<T>& ref, LcfWriter& stream) {
706  Struct<T>::WriteLcf(ref, stream);
707  }
708  static int LcfSize(const std::vector<T>& ref, LcfWriter& stream) {
709  return Struct<T>::LcfSize(ref, stream);
710  }
711  static void WriteXml(const std::vector<T>& ref, XmlWriter& stream) {
712  Struct<T>::WriteXml(ref, stream);
713  }
714  static void BeginXml(std::vector<T>& ref, XmlReader& stream) {
715  Struct<T>::BeginXml(ref, stream);
716  }
717  static void ParseXml(std::vector<T>& /* ref */, const std::string& /* data */) {
718  // no-op
719  }
720 };
721 
722 
723 
727 template <class S>
728 class Flags {
729 private:
730  static const char* const name;
731  static constexpr size_t num_flags = std::tuple_size<decltype(S::flags)>::value;
732  static const std::array<const char* const, num_flags> flag_names;
733  static const std::array<bool, num_flags> flags_is2k3;
734 
735 public:
736  static const char* tag(int idx);
737  static int idx(const char* tag);
738 
739  static void ReadLcf(S& obj, LcfReader& stream, uint32_t length);
740  static void WriteLcf(const S& obj, LcfWriter& stream);
741  static int LcfSize(const S& obj, LcfWriter& stream);
742  static void WriteXml(const S& obj, XmlWriter& stream);
743  static void BeginXml(S& obj, XmlReader& stream);
744 };
745 
746 template <class S>
747 inline const char* Flags<S>::tag(int idx) {
748  return Flags<S>::flag_names[idx];
749 }
750 
751 template <class S>
752 inline int Flags<S>::idx(const char* tag) {
753  for (size_t i = 0; i < flag_names.size(); ++i) {
754  if (std::strcmp(flag_names[i], tag) == 0) {
755  return i;
756  }
757  }
758  return -1;
759 }
760 
764 template <class T>
765 struct TypeReader<T, Category::Flags> {
766  static void ReadLcf(T& ref, LcfReader& stream, uint32_t length) {
767  Flags<T>::ReadLcf(ref, stream, length);
768  }
769  static void WriteLcf(const T& ref, LcfWriter& stream) {
770  Flags<T>::WriteLcf(ref, stream);
771  }
772  static int LcfSize(const T& ref, LcfWriter& stream) {
773  return Flags<T>::LcfSize(ref, stream);
774  }
775  static void WriteXml(const T& ref, XmlWriter& stream) {
776  Flags<T>::WriteXml(ref, stream);
777  }
778  static void BeginXml(T& ref, XmlReader& stream) {
779  Flags<T>::BeginXml(ref, stream);
780  }
781  static void ParseXml(T& /* ref */, const std::string& /* data */) {
782  // no-op
783  }
784 };
785 
789 class WrapperXmlHandler : public XmlHandler {
790 public:
791  WrapperXmlHandler(const char* const name, XmlHandler* handler) :
792  name(name), handler(handler) {}
793 
794  void StartElement(XmlReader& stream, const char* name, const char** /* atts */) {
795  if (strcmp(name, this->name) != 0)
796  stream.Error("Expecting %s but got %s", this->name, name);
797  stream.SetHandler(handler);
798  }
799 
800 private:
801  const char* const name;
802  XmlHandler* handler;
803 };
804 
808 template <class S>
809 class RootXmlHandler : public XmlHandler {
810 
811 public:
812  RootXmlHandler(S& ref, const char* const name) : ref(ref), name(name) {}
813 
814  void StartElement(XmlReader& stream, const char* name, const char** /* atts */) {
815  if (strcmp(name, this->name) != 0)
816  stream.Error("Expecting %s but got %s", this->name, name);
817  TypeReader<S>::BeginXml(ref, stream);
818  }
819 
820 private:
821  S& ref;
822  const char* const name;
823 
824 };
825 
826 } //namespace lcf
827 
828 #endif
static void BeginXml(S &obj, XmlReader &stream)
static const std::array< const char *const, num_flags > flag_names
static const std::array< bool, num_flags > flags_is2k3
static void ReadLcf(S &obj, LcfReader &stream, uint32_t length)
static void WriteXml(const S &obj, XmlWriter &stream)
static int idx(const char *tag)
static constexpr size_t num_flags
static int LcfSize(const S &obj, LcfWriter &stream)
static const char * tag(int idx)
static void WriteLcf(const S &obj, LcfWriter &stream)
static const char *const name
void StartElement(XmlReader &stream, const char *name, const char **)
RootXmlHandler(S &ref, const char *const name)
const char *const name
static void BeginXml(S &obj, XmlReader &stream)
static int LcfSize(const S &obj, LcfWriter &stream)
static void MakeFieldMap()
static const Field< S > * fields[]
static void WriteXml(const S &obj, XmlWriter &stream)
IDReaderT< S, IDChecker< S >::value > IDReader
std::map< const char *const, const Field< S > *, StringComparator > tag_map_type
static tag_map_type tag_map
static void MakeTagMap()
static field_map_type field_map
static void WriteLcf(const S &obj, LcfWriter &stream)
std::map< int, const Field< S > * > field_map_type
static void ReadLcf(S &obj, LcfReader &stream)
static const char *const name
WrapperXmlHandler(const char *const name, XmlHandler *handler)
void StartElement(XmlReader &stream, const char *name, const char **)
const char *const name
Definition: dbarray.cpp:13
int LcfSize(const S &obj, LcfWriter &) const
void WriteLcf(const S &obj, LcfWriter &stream) const
int LcfSize(const S &obj, LcfWriter &stream) const
bool IsDefault(const S &a, const S &b, bool is2k3) const
int LcfSize(const S &, LcfWriter &) const
void WriteXml(const S &, XmlWriter &) const
void ParseXml(S &, const std::string &) const
void ReadLcf(S &, LcfReader &, uint32_t) const
void BeginXml(S &, XmlReader &) const
void WriteLcf(const S &, LcfWriter &) const
bool IsDefault(const S &, const S &, bool) const
virtual void ParseXml(S &obj, const std::string &data) const =0
bool isPresentIfDefault(bool db_is2k3) const
Field(int id, const char *name, bool present_if_default, bool is2k3)
virtual void WriteLcf(const S &obj, LcfWriter &stream) const =0
virtual void BeginXml(S &obj, XmlReader &stream) const =0
virtual bool IsDefault(const S &obj, const S &ref, bool is2k3) const =0
virtual void WriteXml(const S &obj, XmlWriter &stream) const =0
virtual void ReadLcf(S &obj, LcfReader &stream, uint32_t length) const =0
virtual int LcfSize(const S &obj, LcfWriter &stream) const =0
const char *const name
bool present_if_default
static yes check(type_check< int C::*, &C::ID > *)
static const bool value
static no check(...)
static void WriteID(const S &, LcfWriter &)
static void ReadIDXml(S &, const char **)
static void WriteXmlTag(const S &, const std::string &name, XmlWriter &stream)
static int IDSize(const S &)
static void ReadID(S &, LcfReader &)
static void WriteID(const S &obj, LcfWriter &stream)
static void ReadID(S &obj, LcfReader &stream)
static void WriteXmlTag(const S &obj, const std::string &name, XmlWriter &stream)
static int IDSize(const S &obj)
static void ReadIDXml(S &obj, const char **atts)
static const uint32_t value
static void ReadLcf(DBBitArray &ref, LcfReader &stream, uint32_t length)
static void ParseXml(DBBitArray &ref, const std::string &data)
static void WriteLcf(const DBBitArray &ref, LcfWriter &stream)
static int LcfSize(const DBBitArray &ref, LcfWriter &stream)
static void WriteXml(const DBBitArray &ref, XmlWriter &stream)
static void ParseXml(DBString &ref, const std::string &data)
static void WriteXml(const DBString &ref, XmlWriter &stream)
static void WriteLcf(const DBString &ref, LcfWriter &stream)
static int LcfSize(const DBString &ref, LcfWriter &stream)
static void ReadLcf(DBString &ref, LcfReader &stream, uint32_t length)
static int LcfSize(const int32_t &ref, LcfWriter &)
static void WriteLcf(const int32_t &ref, LcfWriter &stream)
static void ParseXml(int32_t &ref, const std::string &data)
static void ReadLcf(int32_t &ref, LcfReader &stream, uint32_t length)
static void WriteXml(const int32_t &ref, XmlWriter &stream)
static void WriteXml(const std::string &ref, XmlWriter &stream)
static void ReadLcf(std::string &ref, LcfReader &stream, uint32_t length)
static int LcfSize(const std::string &ref, LcfWriter &stream)
static void WriteLcf(const std::string &ref, LcfWriter &stream)
static void ParseXml(std::string &ref, const std::string &data)
static int LcfSize(const std::vector< T > &ref, LcfWriter &)
static void ParseXml(std::vector< T > &ref, const std::string &data)
static void WriteLcf(const std::vector< T > &ref, LcfWriter &stream)
static void WriteXml(const std::vector< T > &ref, XmlWriter &stream)
static void ReadLcf(std::vector< T > &ref, LcfReader &stream, uint32_t length)
static void ReadLcf(T &ref, LcfReader &stream, uint32_t length)
static void WriteLcf(const T &ref, LcfWriter &stream)
static int LcfSize(const T &, LcfWriter &)
static void ParseXml(T &ref, const std::string &data)
static void WriteXml(const T &ref, XmlWriter &stream)
static void WriteXml(const T &ref, XmlWriter &stream)
static void BeginXml(T &ref, XmlReader &stream)
static void ReadLcf(T &ref, LcfReader &stream, uint32_t length)
static void WriteLcf(const T &ref, LcfWriter &stream)
static int LcfSize(const T &ref, LcfWriter &stream)
void BeginXml(S &, XmlReader &) const
SizeField(const T S::*ref, int id, bool present_if_default, bool is2k3)
void WriteXml(const S &, XmlWriter &) const
bool IsDefault(const S &a, const S &b, bool) const
void ReadLcf(S &, LcfReader &stream, uint32_t length) const
void ParseXml(S &, const std::string &) const
void WriteLcf(const S &obj, LcfWriter &stream) const
const T S::* ref
int LcfSize(const S &obj, LcfWriter &stream) const
bool operator()(const char *const &lhs, const char *const &rhs) const
static const Category::Index value
Definition: reader_struct.h:61
static void WriteLcf(const T &ref, LcfWriter &stream)
static int LcfSize(const T &ref, LcfWriter &stream)
static void ParseXml(T &, const std::string &)
static void ReadLcf(T &ref, LcfReader &stream, uint32_t length)
static void BeginXml(T &ref, XmlReader &stream)
static void WriteXml(const T &ref, XmlWriter &stream)
static int LcfSize(const T &ref, LcfWriter &stream)
static void BeginXml(T &, XmlReader &)
static void WriteXml(const T &ref, XmlWriter &stream)
static void WriteLcf(const T &ref, LcfWriter &stream)
static void ReadLcf(T &ref, LcfReader &stream, uint32_t length)
static void ParseXml(T &ref, const std::string &data)
static void WriteXml(const T &ref, XmlWriter &stream)
static void ParseXml(T &, const std::string &)
static int LcfSize(const T &ref, LcfWriter &stream)
static void WriteLcf(const T &ref, LcfWriter &stream)
static void BeginXml(T &ref, XmlReader &stream)
static void ReadLcf(T &ref, LcfReader &stream, uint32_t length)
static void ParseXml(T &, const std::string &)
static void WriteXml(const T &ref, XmlWriter &stream)
static void WriteLcf(const T &ref, LcfWriter &stream)
static void BeginXml(T &ref, XmlReader &stream)
static int LcfSize(const T &ref, LcfWriter &stream)
static void ReadLcf(T &ref, LcfReader &stream, uint32_t)
static void BeginXml(T &, XmlReader &)
static int LcfSize(const T &, LcfWriter &)
static void WriteLcf(const T &, LcfWriter &)
static void ReadLcf(T &, LcfReader &stream, uint32_t length)
static void ParseXml(T &, const std::string &)
static void WriteXml(const T &, XmlWriter &)
static void WriteLcf(const std::vector< T > &ref, LcfWriter &stream)
static void BeginXml(std::vector< T > &ref, XmlReader &stream)
static void WriteXml(const std::vector< T > &ref, XmlWriter &stream)
static void ReadLcf(std::vector< T > &ref, LcfReader &stream, uint32_t)
static int LcfSize(const std::vector< T > &ref, LcfWriter &stream)
static void ParseXml(std::vector< T > &, const std::string &)
void BeginXml(S &obj, XmlReader &stream) const
TypedField(T S::*ref, int id, const char *name, bool present_if_default, bool is2k3)
void WriteLcf(const S &obj, LcfWriter &stream) const
void ReadLcf(S &obj, LcfReader &stream, uint32_t length) const
void WriteXml(const S &obj, XmlWriter &stream) const
bool IsDefault(const S &a, const S &b, bool) const
int LcfSize(const S &obj, LcfWriter &stream) const
void ParseXml(S &obj, const std::string &data) const