liblcf
Loading...
Searching...
No Matches
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 <cstring>
20#include <cstdlib>
21#include <cinttypes>
22#include "lcf/dbstring.h"
23#include "lcf/reader_lcf.h"
24#include "lcf/writer_lcf.h"
25#include "lcf/reader_xml.h"
26#include "lcf/writer_xml.h"
27#include "lcf/rpg/equipment.h"
28#include "lcf/rpg/parameters.h"
29#include "lcf/rpg/eventcommand.h"
30#include "lcf/rpg/movecommand.h"
31#include "lcf/rpg/treemap.h"
32#include "lcf/rpg/rect.h"
33#include "lcf/rpg/terms.h"
34#include "log.h"
35
36namespace lcf {
37
38// Forward declarations
39
40template <class T>
41class Struct;
42
43// Type categories
44
54
55template <class T>
59
60template <> struct TypeCategory<rpg::Equipment> { static const Category::Index value = Category::RawStruct; };
61template <> struct TypeCategory<rpg::EventCommand> { static const Category::Index value = Category::RawStruct; };
62template <> struct TypeCategory<rpg::MoveCommand> { static const Category::Index value = Category::RawStruct; };
63template <> struct TypeCategory<rpg::Parameters> { static const Category::Index value = Category::RawStruct; };
64template <> struct TypeCategory<rpg::TreeMap> { static const Category::Index value = Category::RawStruct; };
65template <> struct TypeCategory<rpg::Rect> { static const Category::Index value = Category::RawStruct; };
66template <> struct TypeCategory<DBString> { static const Category::Index value = Category::RawStruct; };
67
68template <> struct TypeCategory<int8_t> { static const Category::Index value = Category::Primitive; };
69template <> struct TypeCategory<uint8_t> { static const Category::Index value = Category::Primitive; };
70template <> struct TypeCategory<int16_t> { static const Category::Index value = Category::Primitive; };
71template <> struct TypeCategory<uint32_t> { static const Category::Index value = Category::Primitive; };
72template <> struct TypeCategory<int32_t> { static const Category::Index value = Category::Primitive; };
73template <> struct TypeCategory<bool> { static const Category::Index value = Category::Primitive; };
74template <> struct TypeCategory<double> { static const Category::Index value = Category::Primitive; };
75template <> struct TypeCategory<std::string> { static const Category::Index value = Category::Primitive; };
76template <> struct TypeCategory<DBBitArray> { static const Category::Index value = Category::Primitive; };
77
78template <class T>
79struct TypeCategory<std::vector<T>> {
81};
82
86template <class T, Category::Index cat = TypeCategory<T>::value>
87struct TypeReader {};
88
89
94template <class T>
95struct TypeReader<T, Category::Void> {
96 static void ReadLcf(T&, LcfReader& stream, uint32_t length) {
97 stream.Seek(length, LcfReader::FromCurrent);
98 }
99 static void WriteLcf(const T&, LcfWriter&) {
100 }
101 static int LcfSize(const T&, LcfWriter&) {
102 return 0;
103 }
104 static void WriteXml(const T&, XmlWriter&) {
105 }
106 static void BeginXml(T&, XmlReader&) {
107 }
108 static void ParseXml(T& /* ref */, const std::string& /* data */) {
109 //no-op
110 }
111};
112
116template <class T>
117struct RawStruct {
118 static void ReadLcf(T& ref, LcfReader& stream, uint32_t length);
119 static void WriteLcf(const T& ref, LcfWriter& stream);
120 static int LcfSize(const T& ref, LcfWriter& stream);
121 static void WriteXml(const T& ref, XmlWriter& stream);
122 static void BeginXml(T& ref, XmlReader& stream);
123};
124
125template <class T>
127 static void ReadLcf(T& ref, LcfReader& stream, uint32_t length) {
128 RawStruct<T>::ReadLcf(ref, stream, length);
129 }
130 static void WriteLcf(const T& ref, LcfWriter& stream) {
131 RawStruct<T>::WriteLcf(ref, stream);
132 }
133 static int LcfSize(const T& ref, LcfWriter& stream) {
134 return RawStruct<T>::LcfSize(ref, stream);
135 }
136 static void WriteXml(const T& ref, XmlWriter& stream) {
137 RawStruct<T>::WriteXml(ref, stream);
138 }
139 static void BeginXml(T& ref, XmlReader& stream) {
140 RawStruct<T>::BeginXml(ref, stream);
141 }
142 static void ParseXml(T& /* ref */, const std::string& /* data */) {
143 //no-op
144 }
145};
146
150template <class T>
151struct LcfSizeT {
152 static const uint32_t value = sizeof(T);
153};
154
158template <>
159struct LcfSizeT<bool> {
160 static const uint32_t value = 1;
161};
162
166template <class T>
167struct Primitive {
168 static void ReadLcf(T& ref, LcfReader& stream, uint32_t length) {
169 int dif = 0;
170 // FIXME: Bug #174
171 if (length != LcfSizeT<T>::value) {
172 dif = length - LcfSizeT<T>::value;
173 Log::Warning("Reading Primitive of incorrect size %" PRIu32 " (expected %" PRIu32 ") at %" PRIX32 "",
174 length, LcfSizeT<T>::value, stream.Tell());
175 }
176
177 stream.Read(ref);
178#ifdef LCF_DEBUG_TRACE
179 DebugPrint(ref);
180#endif
181
182 if (dif != 0) {
183 // Fix incorrect read pointer position
184 Log::Warning("Invalid Primitive at %" PRIX32 "", stream.Tell());
185 stream.Seek(dif, LcfReader::FromCurrent);
186 }
187 }
188 static void WriteLcf(const T& ref, LcfWriter& stream) {
189 stream.Write(ref);
190 }
191 static int LcfSize(const T& /* ref */, LcfWriter& /* stream */) {
192 return LcfSizeT<T>::value;
193 }
194 static void WriteXml(const T& ref, XmlWriter& stream) {
195 stream.Write(ref);
196 }
197 static void ParseXml(T& ref, const std::string& data) {
198 XmlReader::Read(ref, data);
199 }
200 private:
201#ifdef LCF_DEBUG_TRACE
202 template <typename U>
203 static void DebugPrint(U& ref) {
204 std::cout << ref << '\n';
205 }
206 static void DebugPrint(int8_t ref) {
207 std::cout << (int)ref << '\n';
208 }
209 static void DebugPrint(uint8_t ref) {
210 std::cout << (int)ref << '\n';
211 }
212#endif
213};
214
218template <class T>
219struct Primitive<std::vector<T>> {
220 static void ReadLcf(std::vector<T>& ref, LcfReader& stream, uint32_t length) {
221 stream.Read(ref, length);
222#ifdef LCF_DEBUG_TRACE
223 typename std::vector<T>::iterator it;
224 fprintf(stderr, " ");
225 for (it = ref.begin(); it != ref.end(); ++it) {
226 fprintf(stderr, "%d, ", static_cast<int>(*it));
227 }
228 fprintf(stderr, "\n");
229#endif
230 }
231 static void WriteLcf(const std::vector<T>& ref, LcfWriter& stream) {
232 stream.Write(ref);
233 }
234 static int LcfSize(const std::vector<T>& ref, LcfWriter& /* stream */) {
235 return LcfSizeT<T>::value * ref.size();
236 }
237 static void WriteXml(const std::vector<T>& ref, XmlWriter& stream) {
238 stream.Write(ref);
239 }
240 static void ParseXml(std::vector<T>& ref, const std::string& data) {
241 XmlReader::Read(ref, data);
242 }
243};
244
248template <>
249struct Primitive<int32_t> {
250 static void ReadLcf(int32_t& ref, LcfReader& stream, uint32_t length) {
251 if (length >= 1 && length <= 5) {
252 ref = stream.ReadInt();
253#ifdef LCF_DEBUG_TRACE
254 fprintf(stderr, " %d\n", ref);
255#endif
256 } else if (length == 0) {
257 ref = 0;
258#ifdef LCF_DEBUG_TRACE
259 fprintf(stderr, " %d\n", ref);
260#endif
261 } else {
262 ref = 0;
263 Log::Warning("Invalid integer at %X", stream.Tell());
264 stream.Seek(length, LcfReader::FromCurrent);
265 }
266 }
267 static void WriteLcf(const int32_t& ref, LcfWriter& stream) {
268 stream.WriteInt(ref);
269 }
270 static int LcfSize(const int32_t& ref, LcfWriter& /* stream */) {
271 return LcfReader::IntSize(ref);
272 }
273 static void WriteXml(const int32_t& ref, XmlWriter& stream) {
274 stream.WriteInt(ref);
275 }
276 static void ParseXml(int32_t& ref, const std::string& data) {
277 XmlReader::Read(ref, data);
278 }
279};
280
284template <>
285struct Primitive<std::string> {
286 static void ReadLcf(std::string& ref, LcfReader& stream, uint32_t length) {
287 stream.ReadString(ref, length);
288#ifdef LCF_DEBUG_TRACE
289 fprintf(stderr, " %s\n", ref.c_str());
290#endif
291 }
292 static void WriteLcf(const std::string& ref, LcfWriter& stream) {
293 stream.Write(ref);
294 }
295 static int LcfSize(const std::string& ref, LcfWriter& stream) {
296 return stream.Decode(ref).size();
297 }
298 static void WriteXml(const std::string& ref, XmlWriter& stream) {
299 stream.Write(ref);
300 }
301 static void ParseXml(std::string& ref, const std::string& data) {
302 XmlReader::Read(ref, data);
303 }
304};
305
309template <>
310struct Primitive<DBBitArray> {
311 static void ReadLcf(DBBitArray& ref, LcfReader& stream, uint32_t length) {
312 stream.ReadBits(ref, length);
313#ifdef LCF_DEBUG_TRACE
314 fprintf(stderr, " ");
315 for (auto& b: ref) {
316 fprintf(stderr, "%d", static_cast<int>(b));
317 }
318 fprintf(stderr, "\n");
319#endif
320 }
321 static void WriteLcf(const DBBitArray& ref, LcfWriter& stream) {
322 stream.Write(ref);
323 }
324 static int LcfSize(const DBBitArray& ref, LcfWriter& stream) {
325 (void)stream;
326 return ref.size();
327 }
328 static void WriteXml(const DBBitArray& ref, XmlWriter& stream) {
329 stream.Write(ref);
330 }
331 static void ParseXml(DBBitArray& ref, const std::string& data) {
332 XmlReader::Read(ref, data);
333 }
334};
335
336
337
341template <class T>
343 static void ReadLcf(T& ref, LcfReader& stream, uint32_t length) {
344 Primitive<T>::ReadLcf(ref, stream, length);
345 }
346 static void WriteLcf(const T& ref, LcfWriter& stream) {
347 Primitive<T>::WriteLcf(ref, stream);
348 }
349 static int LcfSize(const T& ref, LcfWriter& stream) {
350 return Primitive<T>::LcfSize(ref, stream);
351 }
352 static void WriteXml(const T& ref, XmlWriter& stream) {
353 Primitive<T>::WriteXml(ref, stream);
354 }
355 static void BeginXml(T& /* ref */, XmlReader& /* stream */) {
356 // no-op
357 }
358 static void ParseXml(T& ref, const std::string& data) {
359 Primitive<T>::ParseXml(ref, data);
360 }
361};
362
366template <class S>
367struct Field {
368 typedef S struct_type;
369
370 const char* const name;
371 int id;
373 bool is2k3;
374
375 virtual void ReadLcf(S& obj, LcfReader& stream, uint32_t length) const = 0;
376 virtual void WriteLcf(const S& obj, LcfWriter& stream) const = 0;
377 virtual int LcfSize(const S& obj, LcfWriter& stream) const = 0;
378 virtual bool IsDefault(const S& obj, const S& ref, bool is2k3) const = 0;
379 virtual void WriteXml(const S& obj, XmlWriter& stream) const = 0;
380 virtual void BeginXml(S& obj, XmlReader& stream) const = 0;
381 virtual void ParseXml(S& obj, const std::string& data) const = 0;
382
383 bool isPresentIfDefault(bool db_is2k3) const {
384 if (std::is_same<S,rpg::Terms>::value && db_is2k3 && (id == 0x3 || id == 0x1)) {
385 //Special case - only known fields that are 2k specific and not
386 //written to a 2k3 db if defaulted.
387 return false;
388 }
389 return present_if_default;
390 }
391
394};
395
399template <class S, class T>
400struct TypedField : public Field<S> {
401 T S::*ref;
402
403 void ReadLcf(S& obj, LcfReader& stream, uint32_t length) const {
404 TypeReader<T>::ReadLcf(obj.*ref, stream, length);
405 }
406 void WriteLcf(const S& obj, LcfWriter& stream) const {
407 TypeReader<T>::WriteLcf(obj.*ref, stream);
408 }
409 int LcfSize(const S& obj, LcfWriter& stream) const {
410 return TypeReader<T>::LcfSize(obj.*ref, stream);
411 }
412 void WriteXml(const S& obj, XmlWriter& stream) const {
413 stream.BeginElement(this->name);
414 TypeReader<T>::WriteXml(obj.*ref, stream);
415 stream.EndElement(this->name);
416 }
417 void BeginXml(S& obj, XmlReader& stream) const {
418 TypeReader<T>::BeginXml(obj.*ref, stream);
419 }
420 void ParseXml(S& obj, const std::string& data) const {
421 TypeReader<T>::ParseXml(obj.*ref, data);
422 }
423 bool IsDefault(const S& a, const S& b, bool) const {
424 return a.*ref == b.*ref;
425 }
426
427 TypedField(T S::*ref, int id, const char* name, bool present_if_default, bool is2k3) :
429};
430
435template <typename S, typename T>
436struct DatabaseVersionField : public TypedField<S,T> {
437
438 using TypedField<S,T>::TypedField;
439
440 int LcfSize(const S& obj, LcfWriter& stream) const {
441 //If db version is 0, it's like a "version block" is not present.
442 if ((obj.*(this->ref)) == 0) {
443 return 0;
444 }
445 return TypedField<S,T>::LcfSize(obj, stream);
446 }
447 bool IsDefault(const S& a, const S& b, bool is2k3) const {
448 if (is2k3) {
449 //DB Version always present in 2k3 db
450 return false;
451 }
452 //Only present if not 0 in 2k db.
453 return TypedField<S,T>::IsDefault(a, b, is2k3);
454 }
455};
456
461template <typename S>
462struct EmptyField : public Field<S> {
463
464 using Field<S>::Field;
465
466 void ReadLcf(S& /* obj */, LcfReader& /* stream */, uint32_t /* length */) const { }
467 void WriteLcf(const S& /* obj */, LcfWriter& /* stream */) const { }
468 int LcfSize(const S& /* obj */, LcfWriter& /* stream */) const {
469 //This is always an "empty block"
470 return 0;
471 }
472 void WriteXml(const S& /* obj */, XmlWriter& /* stream */) const { }
473 void BeginXml(S& /* obj */, XmlReader& /* stream */) const { }
474 void ParseXml(S& /* obj */, const std::string& /* data */) const { }
475
476 bool IsDefault(const S& /* a */, const S& /* b */, bool) const {
477 return true;
478 }
479
480};
481
482
483
487template <class S, class T>
488struct SizeField : public Field<S> {
489 const T S::*ref;
490
491 void ReadLcf(S& /* obj */, LcfReader& stream, uint32_t length) const {
492 int32_t dummy;
493 TypeReader<int32_t>::ReadLcf(dummy, stream, length);
494 }
495 void WriteLcf(const S& obj, LcfWriter& stream) const {
496 int size = TypeReader<T>::LcfSize(obj.*ref, stream);
497 TypeReader<int32_t>::WriteLcf(size, stream);
498 }
499 int LcfSize(const S& obj, LcfWriter& stream) const {
500 int size = TypeReader<T>::LcfSize(obj.*ref, stream);
501 return LcfReader::IntSize(size);
502 }
503 void WriteXml(const S& /* obj */, XmlWriter& /* stream */) const {
504 // no-op
505 }
506 void BeginXml(S& /* obj */, XmlReader& /* stream */) const {
507 // no-op
508 }
509 void ParseXml(S& /* obj */, const std::string& /* data */) const {
510 // no-op
511 }
512 bool IsDefault(const S& a, const S& b, bool) const {
513 return (a.*ref).size() == (b.*ref).size();
514 }
515
516 SizeField(const T S::*ref, int id, bool present_if_default, bool is2k3) :
517 Field<S>(id, "", present_if_default, is2k3), ref(ref) {}
518};
519
520
524template <class S, class T>
525struct CountField : public SizeField<S,T> {
526
527 using SizeField<S,T>::SizeField;
528
529 void WriteLcf(const S& obj, LcfWriter& stream) const {
530 int size = (obj.*(this->ref)).size();
531 TypeReader<int32_t>::WriteLcf(size, stream);
532 }
533 int LcfSize(const S& obj, LcfWriter& /* stream */) const {
534 int size = (obj.*(this->ref)).size();
535 return LcfReader::IntSize(size);
536 }
537};
538
542template <class T>
543struct IDChecker {
544 typedef char no;
545 typedef int yes;
546
547 template <typename U, U> struct type_check;
548 template <class C>
550 template <class C>
551 static no check(...);
552
553 static const bool value = sizeof(check<T>(0)) == sizeof(yes);
554};
555
556// ID reader for Struct class
557
558template <class S, bool T>
559struct IDReaderT {
560};
561
562template <class S>
563struct IDReaderT<S, true> {
564 static void ReadID(S& obj, LcfReader& stream) {
565 obj.ID = stream.ReadInt();
566 }
567 static void WriteID(const S& obj, LcfWriter& stream) {
568 stream.WriteInt(obj.ID);
569 }
570 static int IDSize(const S& obj) {
571 return LcfReader::IntSize(obj.ID);
572 }
573 static void WriteXmlTag(const S& obj, const std::string& name, XmlWriter& stream) {
574 stream.BeginElement(name, obj.ID);
575 }
576 static void ReadIDXml(S& obj, const char** atts) {
577 for (int i = 0; atts[i] != NULL && atts[i + 1] != NULL; i += 2) {
578 if (strcmp(atts[i], "id") == 0)
579 obj.ID = atoi(atts[i + 1]);
580 }
581 }
582};
583
584template <class S>
585struct IDReaderT<S, false> {
586 static void ReadID(S& /* obj */, LcfReader& /* stream */) {}
587 static void WriteID(const S& /* obj */, LcfWriter& /* stream */) {}
588 static int IDSize(const S& /* obj */) { return 0; }
589 static void WriteXmlTag(const S& /* obj */, const std::string& name, XmlWriter& stream) {
590 stream.BeginElement(name);
591 }
592 static void ReadIDXml(S& /* obj */, const char** /* atts */) {}
593};
594
596 bool operator() (const char* const& lhs, const char* const& rhs) const {
597 return strcmp(lhs, rhs) < 0;
598 }
599};
600
601// Struct class template
602
603template <class S>
604class Struct {
605private:
606 typedef std::map<int, const Field<S>* > field_map_type;
607 typedef std::map<const char* const, const Field<S>*, StringComparator> tag_map_type;
609 static const Field<S>* fields[];
612 static const char* const name;
613
614 static void MakeFieldMap();
615 static void MakeTagMap();
616
617 template <class T> friend class StructXmlHandler;
618 template <class T> friend class StructVectorXmlHandler;
619 template <class T> friend class StructFieldXmlHandler;
620
621public:
622 static void ReadLcf(S& obj, LcfReader& stream);
623 static void WriteLcf(const S& obj, LcfWriter& stream);
624 static int LcfSize(const S& obj, LcfWriter& stream);
625 static void WriteXml(const S& obj, XmlWriter& stream);
626 static void BeginXml(S& obj, XmlReader& stream);
627
628 static void ReadLcf(std::vector<S>& obj, LcfReader& stream);
629 static void WriteLcf(const std::vector<S>& obj, LcfWriter& stream);
630 static int LcfSize(const std::vector<S>& obj, LcfWriter& stream);
631 static void WriteXml(const std::vector<S>& obj, XmlWriter& stream);
632 static void BeginXml(std::vector<S>& obj, XmlReader& stream);
633};
634
635template <class S>
636std::map<int, const Field<S>* > Struct<S>::field_map;
637
638template <class S>
639std::map<const char* const, const Field<S>*, StringComparator> Struct<S>::tag_map;
640
644template <class T>
646 static void ReadLcf(T& ref, LcfReader& stream, uint32_t /* length */) {
647 Struct<T>::ReadLcf(ref, stream);
648 }
649 static void WriteLcf(const T& ref, LcfWriter& stream) {
650 Struct<T>::WriteLcf(ref, stream);
651 }
652 static int LcfSize(const T& ref, LcfWriter& stream) {
653 return Struct<T>::LcfSize(ref, stream);
654 }
655 static void WriteXml(const T& ref, XmlWriter& stream) {
656 Struct<T>::WriteXml(ref, stream);
657 }
658 static void BeginXml(T& ref, XmlReader& stream) {
659 Struct<T>::BeginXml(ref, stream);
660 }
661 static void ParseXml(T& /* ref */, const std::string& /* data */) {
662 // no-op
663 }
664};
665
666template <class T>
667struct TypeReader<std::vector<T>, Category::Struct> {
668 static void ReadLcf(std::vector<T>& ref, LcfReader& stream, uint32_t /* length */) {
669 Struct<T>::ReadLcf(ref, stream);
670 }
671 static void WriteLcf(const std::vector<T>& ref, LcfWriter& stream) {
672 Struct<T>::WriteLcf(ref, stream);
673 }
674 static int LcfSize(const std::vector<T>& ref, LcfWriter& stream) {
675 return Struct<T>::LcfSize(ref, stream);
676 }
677 static void WriteXml(const std::vector<T>& ref, XmlWriter& stream) {
678 Struct<T>::WriteXml(ref, stream);
679 }
680 static void BeginXml(std::vector<T>& ref, XmlReader& stream) {
681 Struct<T>::BeginXml(ref, stream);
682 }
683 static void ParseXml(std::vector<T>& /* ref */, const std::string& /* data */) {
684 // no-op
685 }
686};
687
688
689
693template <class S>
694class Flags {
695private:
696 static const char* const name;
697 static constexpr size_t num_flags = std::tuple_size<decltype(S::flags)>::value;
698 static const std::array<const char* const, num_flags> flag_names;
699 static const std::array<bool, num_flags> flags_is2k3;
700
701public:
702 static const char* tag(int idx);
703 static int idx(const char* tag);
704
705 static void ReadLcf(S& obj, LcfReader& stream, uint32_t length);
706 static void WriteLcf(const S& obj, LcfWriter& stream);
707 static int LcfSize(const S& obj, LcfWriter& stream);
708 static void WriteXml(const S& obj, XmlWriter& stream);
709 static void BeginXml(S& obj, XmlReader& stream);
710};
711
712template <class S>
713inline const char* Flags<S>::tag(int idx) {
714 return Flags<S>::flag_names[idx];
715}
716
717template <class S>
718inline int Flags<S>::idx(const char* tag) {
719 for (size_t i = 0; i < flag_names.size(); ++i) {
720 if (std::strcmp(flag_names[i], tag) == 0) {
721 return i;
722 }
723 }
724 return -1;
725}
726
730template <class T>
732 static void ReadLcf(T& ref, LcfReader& stream, uint32_t length) {
733 Flags<T>::ReadLcf(ref, stream, length);
734 }
735 static void WriteLcf(const T& ref, LcfWriter& stream) {
736 Flags<T>::WriteLcf(ref, stream);
737 }
738 static int LcfSize(const T& ref, LcfWriter& stream) {
739 return Flags<T>::LcfSize(ref, stream);
740 }
741 static void WriteXml(const T& ref, XmlWriter& stream) {
742 Flags<T>::WriteXml(ref, stream);
743 }
744 static void BeginXml(T& ref, XmlReader& stream) {
745 Flags<T>::BeginXml(ref, stream);
746 }
747 static void ParseXml(T& /* ref */, const std::string& /* data */) {
748 // no-op
749 }
750};
751
755class WrapperXmlHandler : public XmlHandler {
756public:
757 WrapperXmlHandler(const char* const name, XmlHandler* handler) :
759
760 void StartElement(XmlReader& stream, const char* name, const char** /* atts */) {
761 if (strcmp(name, this->name) != 0)
762 Log::Error("XML: Expecting %s but got %s", this->name, name);
763 stream.SetHandler(handler);
764 }
765
766private:
767 const char* const name;
768 XmlHandler* handler;
769};
770
774template <class S>
775class RootXmlHandler : public XmlHandler {
776
777public:
778 RootXmlHandler(S& ref, const char* const name) : ref(ref), name(name) {}
779
780 void StartElement(XmlReader& stream, const char* name, const char** /* atts */) {
781 if (strcmp(name, this->name) != 0)
782 Log::Error("XML: Expecting %s but got %s", this->name, name);
784 }
785
786private:
787 S& ref;
788 const char* const name;
789
790};
791
792} //namespace lcf
793
794#include "fwd_flags_impl.h"
795
796#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)
static tag_map_type tag_map
std::map< int, const Field< S > * > field_map_type
static void MakeTagMap()
static field_map_type field_map
std::map< const char *const, const Field< S > *, StringComparator > tag_map_type
static void WriteLcf(const S &obj, LcfWriter &stream)
static void ReadLcf(S &obj, LcfReader &stream)
static const char *const name
IDReaderT< S, IDChecker< S >::value > IDReader
WrapperXmlHandler(const char *const name, XmlHandler *handler)
void StartElement(XmlReader &stream, const char *name, const char **)
const char *const name
void Warning(const char *fmt,...) LIKE_PRINTF
void Error(const char *fmt,...) LIKE_PRINTF
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 ReadLcf(T &ref, LcfReader &stream, uint32_t length)
static void WriteXml(const T &ref, XmlWriter &stream)
static void BeginXml(T &ref, XmlReader &stream)
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
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