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
40namespace lcf {
41
42// Forward declarations
43
44template <class T>
45class Struct;
46
47// Type categories
48
49struct Category {
50 enum Index {
55 Void
56 };
57};
58
59template <class T>
62};
63
64template <> struct TypeCategory<rpg::TroopPageCondition::Flags> { static const Category::Index value = Category::Flags; };
65template <> struct TypeCategory<rpg::EventPageCondition::Flags> { static const Category::Index value = Category::Flags; };
66template <> struct TypeCategory<rpg::Terrain::Flags> { static const Category::Index value = Category::Flags; };
67template <> struct TypeCategory<rpg::SavePicture::Flags> { static const Category::Index value = Category::Flags; };
68
69template <> struct TypeCategory<rpg::Equipment> { static const Category::Index value = Category::RawStruct; };
70template <> struct TypeCategory<rpg::EventCommand> { static const Category::Index value = Category::RawStruct; };
71template <> struct TypeCategory<rpg::MoveCommand> { static const Category::Index value = Category::RawStruct; };
72template <> struct TypeCategory<rpg::Parameters> { static const Category::Index value = Category::RawStruct; };
73template <> struct TypeCategory<rpg::TreeMap> { static const Category::Index value = Category::RawStruct; };
74template <> struct TypeCategory<rpg::Rect> { static const Category::Index value = Category::RawStruct; };
75
76template <> struct TypeCategory<int8_t> { static const Category::Index value = Category::Primitive; };
77template <> struct TypeCategory<uint8_t> { static const Category::Index value = Category::Primitive; };
78template <> struct TypeCategory<int16_t> { static const Category::Index value = Category::Primitive; };
79template <> struct TypeCategory<uint32_t> { static const Category::Index value = Category::Primitive; };
80template <> struct TypeCategory<int32_t> { static const Category::Index value = Category::Primitive; };
81template <> struct TypeCategory<bool> { static const Category::Index value = Category::Primitive; };
82template <> struct TypeCategory<double> { static const Category::Index value = Category::Primitive; };
83template <> struct TypeCategory<std::string> { static const Category::Index value = Category::Primitive; };
84template <> struct TypeCategory<DBString> { static const Category::Index value = Category::Primitive; };
85template <> struct TypeCategory<DBBitArray> { static const Category::Index value = Category::Primitive; };
86
87template <class T>
88struct TypeCategory<std::vector<T>> {
90};
91
95template <class T, Category::Index cat = TypeCategory<T>::value>
96struct TypeReader {};
97
98
103template <class T>
104struct 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
125template <class T>
126struct 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
134template <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
159template <class T>
160struct LcfSizeT {
161 static const uint32_t value = sizeof(T);
162};
163
167template <>
168struct LcfSizeT<bool> {
169 static const uint32_t value = 1;
170};
171
175template <class T>
176struct 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
229template <class T>
230struct 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
259template <>
260struct 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
293template <>
294struct 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
318template <>
319struct 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
343template <>
344struct 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
375template <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
400template <class S>
401struct 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
433template <class S, class T>
434struct 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
469template <typename S, typename T>
470struct DatabaseVersionField : public TypedField<S,T> {
471
472 using TypedField<S,T>::TypedField;
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
495template <typename S>
496struct 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
521template <class S, class T>
522struct 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
558template <class S, class T>
559struct CountField : public SizeField<S,T> {
560
561 using SizeField<S,T>::SizeField;
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
576template <class T>
577struct 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
592template <class S, bool T>
593struct IDReaderT {
594};
595
596template <class S>
597struct 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
618template <class S>
619struct 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
637template <class S>
638class Struct {
639private:
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
655public:
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
669template <class S>
670std::map<int, const Field<S>* > Struct<S>::field_map;
671
672template <class S>
673std::map<const char* const, const Field<S>*, StringComparator> Struct<S>::tag_map;
674
678template <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
700template <class T>
701struct 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
727template <class S>
728class Flags {
729private:
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
735public:
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
746template <class S>
747inline const char* Flags<S>::tag(int idx) {
748 return Flags<S>::flag_names[idx];
749}
750
751template <class S>
752inline 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
764template <class T>
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
789class WrapperXmlHandler : public XmlHandler {
790public:
791 WrapperXmlHandler(const char* const name, XmlHandler* 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
800private:
801 const char* const name;
802 XmlHandler* handler;
803};
804
808template <class S>
809class RootXmlHandler : public XmlHandler {
810
811public:
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);
818 }
819
820private:
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