liblcf
reader_struct.h
Go to the documentation of this file.
1 /*
2  * This file is part of liblcf. Copyright (c) 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 #include "lcf/rpg/saveeasyrpgtext.h"
40 #include "lcf/rpg/saveeasyrpgwindow.h"
41 
42 namespace lcf {
43 
44 // Forward declarations
45 
46 template <class T>
47 class Struct;
48 
49 // Type categories
50 
51 struct Category {
52  enum Index {
57  Void
58  };
59 };
60 
61 template <class T>
62 struct TypeCategory {
64 };
65 
66 // Do not forget to add new Flags here
67 template <> struct TypeCategory<rpg::TroopPageCondition::Flags> { static const Category::Index value = Category::Flags; };
68 template <> struct TypeCategory<rpg::EventPageCondition::Flags> { static const Category::Index value = Category::Flags; };
69 template <> struct TypeCategory<rpg::Terrain::Flags> { static const Category::Index value = Category::Flags; };
70 template <> struct TypeCategory<rpg::SavePicture::Flags> { static const Category::Index value = Category::Flags; };
71 template <> struct TypeCategory<rpg::SaveEasyRpgText::Flags> { static const Category::Index value = Category::Flags; };
72 template <> struct TypeCategory<rpg::SaveEasyRpgWindow::Flags> { static const Category::Index value = Category::Flags; };
73 
74 template <> struct TypeCategory<rpg::Equipment> { static const Category::Index value = Category::RawStruct; };
75 template <> struct TypeCategory<rpg::EventCommand> { static const Category::Index value = Category::RawStruct; };
76 template <> struct TypeCategory<rpg::MoveCommand> { static const Category::Index value = Category::RawStruct; };
77 template <> struct TypeCategory<rpg::Parameters> { static const Category::Index value = Category::RawStruct; };
78 template <> struct TypeCategory<rpg::TreeMap> { static const Category::Index value = Category::RawStruct; };
79 template <> struct TypeCategory<rpg::Rect> { static const Category::Index value = Category::RawStruct; };
80 template <> struct TypeCategory<DBString> { static const Category::Index value = Category::RawStruct; };
81 
82 template <> struct TypeCategory<int8_t> { static const Category::Index value = Category::Primitive; };
83 template <> struct TypeCategory<uint8_t> { static const Category::Index value = Category::Primitive; };
84 template <> struct TypeCategory<int16_t> { static const Category::Index value = Category::Primitive; };
85 template <> struct TypeCategory<uint32_t> { static const Category::Index value = Category::Primitive; };
86 template <> struct TypeCategory<int32_t> { static const Category::Index value = Category::Primitive; };
87 template <> struct TypeCategory<bool> { static const Category::Index value = Category::Primitive; };
88 template <> struct TypeCategory<double> { static const Category::Index value = Category::Primitive; };
89 template <> struct TypeCategory<std::string> { static const Category::Index value = Category::Primitive; };
90 template <> struct TypeCategory<DBBitArray> { static const Category::Index value = Category::Primitive; };
91 
92 template <class T>
93 struct TypeCategory<std::vector<T>> {
95 };
96 
100 template <class T, Category::Index cat = TypeCategory<T>::value>
101 struct TypeReader {};
102 
103 
108 template <class T>
109 struct TypeReader<T, Category::Void> {
110  static void ReadLcf(T&, LcfReader& stream, uint32_t length) {
111  stream.Seek(length, LcfReader::FromCurrent);
112  }
113  static void WriteLcf(const T&, LcfWriter&) {
114  }
115  static int LcfSize(const T&, LcfWriter&) {
116  return 0;
117  }
118  static void WriteXml(const T&, XmlWriter&) {
119  }
120  static void BeginXml(T&, XmlReader&) {
121  }
122  static void ParseXml(T& /* ref */, const std::string& /* data */) {
123  //no-op
124  }
125 };
126 
130 template <class T>
131 struct RawStruct {
132  static void ReadLcf(T& ref, LcfReader& stream, uint32_t length);
133  static void WriteLcf(const T& ref, LcfWriter& stream);
134  static int LcfSize(const T& ref, LcfWriter& stream);
135  static void WriteXml(const T& ref, XmlWriter& stream);
136  static void BeginXml(T& ref, XmlReader& stream);
137 };
138 
139 template <class T>
141  static void ReadLcf(T& ref, LcfReader& stream, uint32_t length) {
142  RawStruct<T>::ReadLcf(ref, stream, length);
143  }
144  static void WriteLcf(const T& ref, LcfWriter& stream) {
145  RawStruct<T>::WriteLcf(ref, stream);
146  }
147  static int LcfSize(const T& ref, LcfWriter& stream) {
148  return RawStruct<T>::LcfSize(ref, stream);
149  }
150  static void WriteXml(const T& ref, XmlWriter& stream) {
151  RawStruct<T>::WriteXml(ref, stream);
152  }
153  static void BeginXml(T& ref, XmlReader& stream) {
154  RawStruct<T>::BeginXml(ref, stream);
155  }
156  static void ParseXml(T& /* ref */, const std::string& /* data */) {
157  //no-op
158  }
159 };
160 
164 template <class T>
165 struct LcfSizeT {
166  static const uint32_t value = sizeof(T);
167 };
168 
172 template <>
173 struct LcfSizeT<bool> {
174  static const uint32_t value = 1;
175 };
176 
180 template <class T>
181 struct Primitive {
182  static void ReadLcf(T& ref, LcfReader& stream, uint32_t length) {
183  int dif = 0;
184  // FIXME: Bug #174
185  if (length != LcfSizeT<T>::value) {
186  dif = length - LcfSizeT<T>::value;
187  fprintf(stderr, "Reading Primitive of incorrect size %" PRIu32 " (expected %" PRIu32 ") at %" PRIX32 "\n",
188  length, LcfSizeT<T>::value, stream.Tell());
189  }
190 
191  stream.Read(ref);
192 #ifdef LCF_DEBUG_TRACE
193  DebugPrint(ref);
194 #endif
195 
196  if (dif != 0) {
197  // Fix incorrect read pointer position
198 #ifdef LCF_DEBUG_TRACE
199  printf("Invalid %s at %X\n", typeid(T).name(), stream.Tell());
200 #endif
201  stream.Seek(dif, LcfReader::FromCurrent);
202  }
203  }
204  static void WriteLcf(const T& ref, LcfWriter& stream) {
205  stream.Write(ref);
206  }
207  static int LcfSize(const T& /* ref */, LcfWriter& /* stream */) {
208  return LcfSizeT<T>::value;
209  }
210  static void WriteXml(const T& ref, XmlWriter& stream) {
211  stream.Write(ref);
212  }
213  static void ParseXml(T& ref, const std::string& data) {
214  XmlReader::Read(ref, data);
215  }
216  private:
217 #ifdef LCF_DEBUG_TRACE
218  template <typename U>
219  static void DebugPrint(U& ref) {
220  std::cout << ref << '\n';
221  }
222  static void DebugPrint(int8_t ref) {
223  std::cout << (int)ref << '\n';
224  }
225  static void DebugPrint(uint8_t ref) {
226  std::cout << (int)ref << '\n';
227  }
228 #endif
229 };
230 
234 template <class T>
235 struct Primitive<std::vector<T>> {
236  static void ReadLcf(std::vector<T>& ref, LcfReader& stream, uint32_t length) {
237  stream.Read(ref, length);
238 #ifdef LCF_DEBUG_TRACE
239  typename std::vector<T>::iterator it;
240  printf(" ");
241  for (it = ref.begin(); it != ref.end(); ++it) {
242  printf("%d, ", static_cast<int>(*it));
243  }
244  printf("\n");
245 #endif
246  }
247  static void WriteLcf(const std::vector<T>& ref, LcfWriter& stream) {
248  stream.Write(ref);
249  }
250  static int LcfSize(const std::vector<T>& ref, LcfWriter& /* stream */) {
251  return LcfSizeT<T>::value * ref.size();
252  }
253  static void WriteXml(const std::vector<T>& ref, XmlWriter& stream) {
254  stream.Write(ref);
255  }
256  static void ParseXml(std::vector<T>& ref, const std::string& data) {
257  XmlReader::Read(ref, data);
258  }
259 };
260 
264 template <>
265 struct Primitive<int32_t> {
266  static void ReadLcf(int32_t& ref, LcfReader& stream, uint32_t length) {
267  if (length >= 1 && length <= 5) {
268  ref = stream.ReadInt();
269 #ifdef LCF_DEBUG_TRACE
270  printf(" %d\n", ref);
271 #endif
272  } else {
273  ref = 0;
274 #ifdef LCF_DEBUG_TRACE
275  printf("Invalid integer at %X\n", stream.Tell());
276 #endif
277  stream.Seek(length, LcfReader::FromCurrent);
278  }
279 
280  }
281  static void WriteLcf(const int32_t& ref, LcfWriter& stream) {
282  stream.WriteInt(ref);
283  }
284  static int LcfSize(const int32_t& ref, LcfWriter& /* stream */) {
285  return LcfReader::IntSize(ref);
286  }
287  static void WriteXml(const int32_t& ref, XmlWriter& stream) {
288  stream.WriteInt(ref);
289  }
290  static void ParseXml(int32_t& ref, const std::string& data) {
291  XmlReader::Read(ref, data);
292  }
293 };
294 
298 template <>
299 struct Primitive<std::string> {
300  static void ReadLcf(std::string& ref, LcfReader& stream, uint32_t length) {
301  stream.ReadString(ref, length);
302 #ifdef LCF_DEBUG_TRACE
303  printf(" %s\n", ref.c_str());
304 #endif
305  }
306  static void WriteLcf(const std::string& ref, LcfWriter& stream) {
307  stream.Write(ref);
308  }
309  static int LcfSize(const std::string& ref, LcfWriter& stream) {
310  return stream.Decode(ref).size();
311  }
312  static void WriteXml(const std::string& ref, XmlWriter& stream) {
313  stream.Write(ref);
314  }
315  static void ParseXml(std::string& ref, const std::string& data) {
316  XmlReader::Read(ref, data);
317  }
318 };
319 
323 template <>
324 struct Primitive<DBBitArray> {
325  static void ReadLcf(DBBitArray& ref, LcfReader& stream, uint32_t length) {
326  stream.ReadBits(ref, length);
327 #ifdef LCF_DEBUG_TRACE
328  printf(" ");
329  for (auto& b: ref) {
330  print("%d", static_cast<int>(b));
331  }
332  printf("\n");
333 #endif
334  }
335  static void WriteLcf(const DBBitArray& ref, LcfWriter& stream) {
336  stream.Write(ref);
337  }
338  static int LcfSize(const DBBitArray& ref, LcfWriter& stream) {
339  (void)stream;
340  return ref.size();
341  }
342  static void WriteXml(const DBBitArray& ref, XmlWriter& stream) {
343  stream.Write(ref);
344  }
345  static void ParseXml(DBBitArray& ref, const std::string& data) {
346  XmlReader::Read(ref, data);
347  }
348 };
349 
350 
351 
355 template <class T>
357  static void ReadLcf(T& ref, LcfReader& stream, uint32_t length) {
358  Primitive<T>::ReadLcf(ref, stream, length);
359  }
360  static void WriteLcf(const T& ref, LcfWriter& stream) {
361  Primitive<T>::WriteLcf(ref, stream);
362  }
363  static int LcfSize(const T& ref, LcfWriter& stream) {
364  return Primitive<T>::LcfSize(ref, stream);
365  }
366  static void WriteXml(const T& ref, XmlWriter& stream) {
367  Primitive<T>::WriteXml(ref, stream);
368  }
369  static void BeginXml(T& /* ref */, XmlReader& /* stream */) {
370  // no-op
371  }
372  static void ParseXml(T& ref, const std::string& data) {
373  Primitive<T>::ParseXml(ref, data);
374  }
375 };
376 
380 template <class S>
381 struct Field {
382  typedef S struct_type;
383 
384  const char* const name;
385  int id;
387  bool is2k3;
388 
389  virtual void ReadLcf(S& obj, LcfReader& stream, uint32_t length) const = 0;
390  virtual void WriteLcf(const S& obj, LcfWriter& stream) const = 0;
391  virtual int LcfSize(const S& obj, LcfWriter& stream) const = 0;
392  virtual bool IsDefault(const S& obj, const S& ref, bool is2k3) const = 0;
393  virtual void WriteXml(const S& obj, XmlWriter& stream) const = 0;
394  virtual void BeginXml(S& obj, XmlReader& stream) const = 0;
395  virtual void ParseXml(S& obj, const std::string& data) const = 0;
396 
397  bool isPresentIfDefault(bool db_is2k3) const {
398  if (std::is_same<S,rpg::Terms>::value && db_is2k3 && (id == 0x3 || id == 0x1)) {
399  //Special case - only known fields that are 2k specific and not
400  //written to a 2k3 db if defaulted.
401  return false;
402  }
403  return present_if_default;
404  }
405 
406  Field(int id, const char* name, bool present_if_default, bool is2k3) :
408 };
409 
413 template <class S, class T>
414 struct TypedField : public Field<S> {
415  T S::*ref;
416 
417  void ReadLcf(S& obj, LcfReader& stream, uint32_t length) const {
418  TypeReader<T>::ReadLcf(obj.*ref, stream, length);
419  }
420  void WriteLcf(const S& obj, LcfWriter& stream) const {
421  TypeReader<T>::WriteLcf(obj.*ref, stream);
422  }
423  int LcfSize(const S& obj, LcfWriter& stream) const {
424  return TypeReader<T>::LcfSize(obj.*ref, stream);
425  }
426  void WriteXml(const S& obj, XmlWriter& stream) const {
427  stream.BeginElement(this->name);
428  TypeReader<T>::WriteXml(obj.*ref, stream);
429  stream.EndElement(this->name);
430  }
431  void BeginXml(S& obj, XmlReader& stream) const {
432  TypeReader<T>::BeginXml(obj.*ref, stream);
433  }
434  void ParseXml(S& obj, const std::string& data) const {
435  TypeReader<T>::ParseXml(obj.*ref, data);
436  }
437  bool IsDefault(const S& a, const S& b, bool) const {
438  return a.*ref == b.*ref;
439  }
440 
441  TypedField(T S::*ref, int id, const char* name, bool present_if_default, bool is2k3) :
443 };
444 
449 template <typename S, typename T>
450 struct DatabaseVersionField : public TypedField<S,T> {
451 
453 
454  int LcfSize(const S& obj, LcfWriter& stream) const {
455  //If db version is 0, it's like a "version block" is not present.
456  if ((obj.*(this->ref)) == 0) {
457  return 0;
458  }
459  return TypedField<S,T>::LcfSize(obj, stream);
460  }
461  bool IsDefault(const S& a, const S& b, bool is2k3) const {
462  if (is2k3) {
463  //DB Version always present in 2k3 db
464  return false;
465  }
466  //Only present if not 0 in 2k db.
467  return TypedField<S,T>::IsDefault(a, b, is2k3);
468  }
469 };
470 
475 template <typename S>
476 struct EmptyField : public Field<S> {
477 
478  using Field<S>::Field;
479 
480  void ReadLcf(S& /* obj */, LcfReader& /* stream */, uint32_t /* length */) const { }
481  void WriteLcf(const S& /* obj */, LcfWriter& /* stream */) const { }
482  int LcfSize(const S& /* obj */, LcfWriter& /* stream */) const {
483  //This is always an "empty block"
484  return 0;
485  }
486  void WriteXml(const S& /* obj */, XmlWriter& /* stream */) const { }
487  void BeginXml(S& /* obj */, XmlReader& /* stream */) const { }
488  void ParseXml(S& /* obj */, const std::string& /* data */) const { }
489 
490  bool IsDefault(const S& /* a */, const S& /* b */, bool) const {
491  return true;
492  }
493 
494 };
495 
496 
497 
501 template <class S, class T>
502 struct SizeField : public Field<S> {
503  const T S::*ref;
504 
505  void ReadLcf(S& /* obj */, LcfReader& stream, uint32_t length) const {
506  int32_t dummy;
507  TypeReader<int32_t>::ReadLcf(dummy, stream, length);
508  }
509  void WriteLcf(const S& obj, LcfWriter& stream) const {
510  int size = TypeReader<T>::LcfSize(obj.*ref, stream);
511  TypeReader<int32_t>::WriteLcf(size, stream);
512  }
513  int LcfSize(const S& obj, LcfWriter& stream) const {
514  int size = TypeReader<T>::LcfSize(obj.*ref, stream);
515  return LcfReader::IntSize(size);
516  }
517  void WriteXml(const S& /* obj */, XmlWriter& /* stream */) const {
518  // no-op
519  }
520  void BeginXml(S& /* obj */, XmlReader& /* stream */) const {
521  // no-op
522  }
523  void ParseXml(S& /* obj */, const std::string& /* data */) const {
524  // no-op
525  }
526  bool IsDefault(const S& a, const S& b, bool) const {
527  return (a.*ref).size() == (b.*ref).size();
528  }
529 
530  SizeField(const T S::*ref, int id, bool present_if_default, bool is2k3) :
531  Field<S>(id, "", present_if_default, is2k3), ref(ref) {}
532 };
533 
534 
538 template <class S, class T>
539 struct CountField : public SizeField<S,T> {
540 
542 
543  void WriteLcf(const S& obj, LcfWriter& stream) const {
544  int size = (obj.*(this->ref)).size();
545  TypeReader<int32_t>::WriteLcf(size, stream);
546  }
547  int LcfSize(const S& obj, LcfWriter& /* stream */) const {
548  int size = (obj.*(this->ref)).size();
549  return LcfReader::IntSize(size);
550  }
551 };
552 
556 template <class T>
557 struct IDChecker {
558  typedef char no;
559  typedef int yes;
560 
561  template <typename U, U> struct type_check;
562  template <class C>
564  template <class C>
565  static no check(...);
566 
567  static const bool value = sizeof(check<T>(0)) == sizeof(yes);
568 };
569 
570 // ID reader for Struct class
571 
572 template <class S, bool T>
573 struct IDReaderT {
574 };
575 
576 template <class S>
577 struct IDReaderT<S, true> {
578  static void ReadID(S& obj, LcfReader& stream) {
579  obj.ID = stream.ReadInt();
580  }
581  static void WriteID(const S& obj, LcfWriter& stream) {
582  stream.WriteInt(obj.ID);
583  }
584  static int IDSize(const S& obj) {
585  return LcfReader::IntSize(obj.ID);
586  }
587  static void WriteXmlTag(const S& obj, const std::string& name, XmlWriter& stream) {
588  stream.BeginElement(name, obj.ID);
589  }
590  static void ReadIDXml(S& obj, const char** atts) {
591  for (int i = 0; atts[i] != NULL && atts[i + 1] != NULL; i += 2) {
592  if (strcmp(atts[i], "id") == 0)
593  obj.ID = atoi(atts[i + 1]);
594  }
595  }
596 };
597 
598 template <class S>
599 struct IDReaderT<S, false> {
600  static void ReadID(S& /* obj */, LcfReader& /* stream */) {}
601  static void WriteID(const S& /* obj */, LcfWriter& /* stream */) {}
602  static int IDSize(const S& /* obj */) { return 0; }
603  static void WriteXmlTag(const S& /* obj */, const std::string& name, XmlWriter& stream) {
604  stream.BeginElement(name);
605  }
606  static void ReadIDXml(S& /* obj */, const char** /* atts */) {}
607 };
608 
610  bool operator() (const char* const& lhs, const char* const& rhs) const {
611  return strcmp(lhs, rhs) < 0;
612  }
613 };
614 
615 // Struct class template
616 
617 template <class S>
618 class Struct {
619 private:
620  typedef std::map<int, const Field<S>* > field_map_type;
621  typedef std::map<const char* const, const Field<S>*, StringComparator> tag_map_type;
623  static const Field<S>* fields[];
626  static const char* const name;
627 
628  static void MakeFieldMap();
629  static void MakeTagMap();
630 
631  template <class T> friend class StructXmlHandler;
632  template <class T> friend class StructVectorXmlHandler;
633  template <class T> friend class StructFieldXmlHandler;
634 
635 public:
636  static void ReadLcf(S& obj, LcfReader& stream);
637  static void WriteLcf(const S& obj, LcfWriter& stream);
638  static int LcfSize(const S& obj, LcfWriter& stream);
639  static void WriteXml(const S& obj, XmlWriter& stream);
640  static void BeginXml(S& obj, XmlReader& stream);
641 
642  static void ReadLcf(std::vector<S>& obj, LcfReader& stream);
643  static void WriteLcf(const std::vector<S>& obj, LcfWriter& stream);
644  static int LcfSize(const std::vector<S>& obj, LcfWriter& stream);
645  static void WriteXml(const std::vector<S>& obj, XmlWriter& stream);
646  static void BeginXml(std::vector<S>& obj, XmlReader& stream);
647 };
648 
649 template <class S>
650 std::map<int, const Field<S>* > Struct<S>::field_map;
651 
652 template <class S>
653 std::map<const char* const, const Field<S>*, StringComparator> Struct<S>::tag_map;
654 
658 template <class T>
660  static void ReadLcf(T& ref, LcfReader& stream, uint32_t /* length */) {
661  Struct<T>::ReadLcf(ref, stream);
662  }
663  static void WriteLcf(const T& ref, LcfWriter& stream) {
664  Struct<T>::WriteLcf(ref, stream);
665  }
666  static int LcfSize(const T& ref, LcfWriter& stream) {
667  return Struct<T>::LcfSize(ref, stream);
668  }
669  static void WriteXml(const T& ref, XmlWriter& stream) {
670  Struct<T>::WriteXml(ref, stream);
671  }
672  static void BeginXml(T& ref, XmlReader& stream) {
673  Struct<T>::BeginXml(ref, stream);
674  }
675  static void ParseXml(T& /* ref */, const std::string& /* data */) {
676  // no-op
677  }
678 };
679 
680 template <class T>
681 struct TypeReader<std::vector<T>, Category::Struct> {
682  static void ReadLcf(std::vector<T>& ref, LcfReader& stream, uint32_t /* length */) {
683  Struct<T>::ReadLcf(ref, stream);
684  }
685  static void WriteLcf(const std::vector<T>& ref, LcfWriter& stream) {
686  Struct<T>::WriteLcf(ref, stream);
687  }
688  static int LcfSize(const std::vector<T>& ref, LcfWriter& stream) {
689  return Struct<T>::LcfSize(ref, stream);
690  }
691  static void WriteXml(const std::vector<T>& ref, XmlWriter& stream) {
692  Struct<T>::WriteXml(ref, stream);
693  }
694  static void BeginXml(std::vector<T>& ref, XmlReader& stream) {
695  Struct<T>::BeginXml(ref, stream);
696  }
697  static void ParseXml(std::vector<T>& /* ref */, const std::string& /* data */) {
698  // no-op
699  }
700 };
701 
702 
703 
707 template <class S>
708 class Flags {
709 private:
710  static const char* const name;
711  static constexpr size_t num_flags = std::tuple_size<decltype(S::flags)>::value;
712  static const std::array<const char* const, num_flags> flag_names;
713  static const std::array<bool, num_flags> flags_is2k3;
714 
715 public:
716  static const char* tag(int idx);
717  static int idx(const char* tag);
718 
719  static void ReadLcf(S& obj, LcfReader& stream, uint32_t length);
720  static void WriteLcf(const S& obj, LcfWriter& stream);
721  static int LcfSize(const S& obj, LcfWriter& stream);
722  static void WriteXml(const S& obj, XmlWriter& stream);
723  static void BeginXml(S& obj, XmlReader& stream);
724 };
725 
726 template <class S>
727 inline const char* Flags<S>::tag(int idx) {
728  return Flags<S>::flag_names[idx];
729 }
730 
731 template <class S>
732 inline int Flags<S>::idx(const char* tag) {
733  for (size_t i = 0; i < flag_names.size(); ++i) {
734  if (std::strcmp(flag_names[i], tag) == 0) {
735  return i;
736  }
737  }
738  return -1;
739 }
740 
744 template <class T>
745 struct TypeReader<T, Category::Flags> {
746  static void ReadLcf(T& ref, LcfReader& stream, uint32_t length) {
747  Flags<T>::ReadLcf(ref, stream, length);
748  }
749  static void WriteLcf(const T& ref, LcfWriter& stream) {
750  Flags<T>::WriteLcf(ref, stream);
751  }
752  static int LcfSize(const T& ref, LcfWriter& stream) {
753  return Flags<T>::LcfSize(ref, stream);
754  }
755  static void WriteXml(const T& ref, XmlWriter& stream) {
756  Flags<T>::WriteXml(ref, stream);
757  }
758  static void BeginXml(T& ref, XmlReader& stream) {
759  Flags<T>::BeginXml(ref, stream);
760  }
761  static void ParseXml(T& /* ref */, const std::string& /* data */) {
762  // no-op
763  }
764 };
765 
769 class WrapperXmlHandler : public XmlHandler {
770 public:
771  WrapperXmlHandler(const char* const name, XmlHandler* handler) :
772  name(name), handler(handler) {}
773 
774  void StartElement(XmlReader& stream, const char* name, const char** /* atts */) {
775  if (strcmp(name, this->name) != 0)
776  stream.Error("Expecting %s but got %s", this->name, name);
777  stream.SetHandler(handler);
778  }
779 
780 private:
781  const char* const name;
782  XmlHandler* handler;
783 };
784 
788 template <class S>
789 class RootXmlHandler : public XmlHandler {
790 
791 public:
792  RootXmlHandler(S& ref, const char* const name) : ref(ref), name(name) {}
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  TypeReader<S>::BeginXml(ref, stream);
798  }
799 
800 private:
801  S& ref;
802  const char* const name;
803 
804 };
805 
806 } //namespace lcf
807 
808 #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 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:63
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