liblcf
Loading...
Searching...
No Matches
reader_flags.cpp
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#include "reader_struct.h"
11
12namespace lcf {
13// Templates
14
15template <class S>
18 int bitidx = 0;
19 int byteidx = 0;
20 stream.Read(byte);
21 for (size_t i = 0; i < num_flags; ++i) {
22 if (bitidx == 8) {
23 ++byteidx;
24 if (byteidx >= int(length)) {
25 break;
26 }
27 stream.Read(byte);
28 bitidx = 0;
29 }
30 obj.flags[i] = (byte >> bitidx) & 1;
31 ++bitidx;
32 }
33#ifdef LCF_DEBUG_TRACE
34 unsigned long x = 0;
35 for (size_t i = 0; i < obj.flags.size(); ++i) {
36 x |= (obj.flags[i] << i);
37 }
38 fprintf(stderr, "0x%lx\n", x);
39#endif
40}
41
42template <class S>
44 const bool db_is2k3 = stream.Is2k3();
45
46 uint8_t byte = 0;
47 int bitidx = 0;
48 for (size_t i = 0; i < num_flags; ++i) {
49 const auto flag_is2k3 = flags_is2k3[i];
50 if (!db_is2k3 && flag_is2k3) {
51 continue;
52 }
53 byte |= (obj.flags[i] << bitidx);
54
55 ++bitidx;
56 if (bitidx == 8) {
57 stream.Write(byte);
58 bitidx = 0;
59 byte = 0;
60 }
61 }
62
63 if (bitidx != 0) {
64 stream.Write(byte);
65 }
66}
67
68template <class S>
69int Flags<S>::LcfSize(const S& /* obj */, LcfWriter& stream) {
70 const bool db_is2k3 = stream.Is2k3();
71 int num_bits = 0;
72 for (size_t i = 0; i < num_flags; ++i) {
73 const auto flag_is2k3 = flags_is2k3[i];
74 if (!db_is2k3 && flag_is2k3) {
75 continue;
76 }
77 ++num_bits;
78 }
79 auto num_bytes = (num_bits + 7) / 8;
80 return num_bytes;
81}
82
83template <class S>
85 const bool db_is2k3 = stream.Is2k3();
86 stream.BeginElement(name);
87 for (size_t i = 0; i < num_flags; ++i) {
88 const auto flag_is2k3 = flags_is2k3[i];
89 if (!db_is2k3 && flag_is2k3) {
90 continue;
91 }
92 const auto* flag_name = flag_names[i];
93 stream.WriteNode<bool>(flag_name, obj.flags[i]);
94 }
95 stream.EndElement(name);
96}
97
98template <class S>
99class FlagsXmlHandler : public XmlHandler {
100private:
102 bool* field;
103public:
106
107 void StartElement(XmlReader& /* stream */, const char* name, const char** /* atts */) {
108 const auto idx = Flags<S>::idx(name);
109 if (idx < 0) {
110 Log::Error("XML: Unrecognized field '%s'", name);
111 field = NULL;
112 return;
113 }
114 field = &obj.flags[idx];
115 }
116 void EndElement(XmlReader& /* stream */, const char* /* name */) {
117 field = NULL;
118 }
119 void CharacterData(XmlReader& /* stream */, const std::string& data) {
120 if (field != NULL)
121 XmlReader::Read<bool>(*field, data);
122 }
123};
124
125template <class S>
127 stream.SetHandler(new WrapperXmlHandler(name, new FlagsXmlHandler<S>(obj)));
128}
129
130// Instantiate templates
131#ifdef _MSC_VER
132#pragma warning (disable : 4661)
133#endif
134
135} //namespace lcf
136
137#include "fwd_flags_instance.h"
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 void WriteLcf(const S &obj, LcfWriter &stream)
static const char *const name
void StartElement(XmlReader &, const char *name, const char **)
void CharacterData(XmlReader &, const std::string &data)
void EndElement(XmlReader &, const char *)
void Error(const char *fmt,...) LIKE_PRINTF