liblcf
Loading...
Searching...
No Matches
ldb_eventcommand.cpp
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#include <string>
11#include <vector>
12#include "reader_struct.h"
13#include "lcf/rpg/eventcommand.h"
14
15namespace lcf {
16
17template <>
18struct RawStruct<rpg::EventCommand> {
19 static void ReadLcf(rpg::EventCommand& ref, LcfReader& stream, uint32_t length);
20 static void WriteLcf(const rpg::EventCommand& ref, LcfWriter& stream);
21 static int LcfSize(const rpg::EventCommand& ref, LcfWriter& stream);
22 static void WriteXml(const rpg::EventCommand& ref, XmlWriter& stream);
23 static void BeginXml(rpg::EventCommand& ref, XmlReader& stream);
24};
25
26template <>
27struct RawStruct<std::vector<rpg::EventCommand> > {
28 static void ReadLcf(std::vector<rpg::EventCommand>& ref, LcfReader& stream, uint32_t length);
29 static void WriteLcf(const std::vector<rpg::EventCommand>& ref, LcfWriter& stream);
30 static int LcfSize(const std::vector<rpg::EventCommand>& ref, LcfWriter& stream);
31 static void WriteXml(const std::vector<rpg::EventCommand>& ref, XmlWriter& stream);
32 static void BeginXml(std::vector<rpg::EventCommand>& ref, XmlReader& stream);
33};
34
38void RawStruct<rpg::EventCommand>::ReadLcf(rpg::EventCommand& event_command, LcfReader& stream, uint32_t /* length */) {
39 stream.Read(event_command.code);
40 if (event_command.code != 0) {
41 stream.Read(event_command.indent);
42 stream.ReadString(event_command.string, stream.ReadInt());
43
44 auto& param_buf = stream.IntBuffer();
45
46 param_buf.clear();
47 for (int i = stream.ReadInt(); i > 0; i--) {
48 param_buf.push_back(stream.ReadInt());
49 }
50 if (!param_buf.empty()) {
51 event_command.parameters = DBArray<int32_t>(param_buf.begin(), param_buf.end());
52 }
53 }
54}
55
56void RawStruct<rpg::EventCommand>::WriteLcf(const rpg::EventCommand& event_command, LcfWriter& stream) {
57 stream.Write(event_command.code);
58 stream.Write(event_command.indent);
59 stream.WriteInt(stream.Decode(event_command.string).size());
60 stream.Write(event_command.string);
61 int32_t count = (int32_t)event_command.parameters.size();
62 stream.Write(count);
63 for (int i = 0; i < count; i++)
64 stream.Write(event_command.parameters[i]);
65}
66
67int RawStruct<rpg::EventCommand>::LcfSize(const rpg::EventCommand& event_command, LcfWriter& stream) {
68 int result = 0;
69 result += LcfReader::IntSize(event_command.code);
70 result += LcfReader::IntSize(event_command.indent);
71 result += LcfReader::IntSize(stream.Decode(event_command.string).size());
72 result += stream.Decode(event_command.string).size();
73 int count = event_command.parameters.size();
74 result += LcfReader::IntSize(count);
75 for (int i = 0; i < count; i++)
76 result += LcfReader::IntSize(event_command.parameters[i]);
77 return result;
78}
79
80void RawStruct<rpg::EventCommand>::WriteXml(const rpg::EventCommand& event_command, XmlWriter& stream) {
81 stream.BeginElement("EventCommand");
82 stream.WriteNode("code", event_command.code);
83 stream.WriteNode("indent", event_command.indent);
84 stream.WriteNode("string", event_command.string);
85 stream.WriteNode("parameters", event_command.parameters);
86 stream.EndElement("EventCommand");
87}
88
89class EventCommandXmlHandler : public XmlHandler {
90private:
91 rpg::EventCommand& ref;
92 enum {
99public:
100 EventCommandXmlHandler(rpg::EventCommand& ref) : ref(ref), field(None) {}
101 void StartElement(XmlReader& stream, const char* name, const char** /* atts */) {
102 if (strcmp(name, "code") == 0)
103 field = Code;
104 else if (strcmp(name, "indent") == 0)
105 field = Indent;
106 else if (strcmp(name, "string") == 0)
107 field = String;
108 else if (strcmp(name, "parameters") == 0)
110 else {
111 stream.Error("Unrecognized field '%s'", name);
112 field = None;
113 }
114 }
115 void EndElement(XmlReader& /* stream */, const char* /* name */) {
116 field = None;
117 }
118 void CharacterData(XmlReader& /* stream */, const std::string& data) {
119 switch (field) {
120 case None:
121 break;
122 case Code:
123 XmlReader::Read(ref.code, data);
124 break;
125 case Indent:
126 XmlReader::Read(ref.indent, data);
127 break;
128 case String:
129 XmlReader::Read(ref.string, data);
130 break;
131 case Parameters:
132 XmlReader::Read(ref.parameters, data);
133 break;
134 }
135 }
136};
137
138void RawStruct<rpg::EventCommand>::BeginXml(rpg::EventCommand& ref, XmlReader& stream) {
139 stream.SetHandler(new WrapperXmlHandler("EventCommand", new EventCommandXmlHandler(ref)));
140}
141
146 std::vector<rpg::EventCommand>& event_commands, LcfReader& stream, uint32_t length) {
147 // Event Commands is a special array
148 // Has no size information. Is terminated by 4 times 0x00.
149 unsigned long startpos = stream.Tell();
150 unsigned long endpos = startpos + length;
151
152 // Since we don't know the number of event parameters without reading, we store
153 // them all in a temporary buffer and then copy it to EventCommand::parameters.
154 // This prevents extra allocations from repeated calls to push_back().
155 for (;;) {
156 uint8_t ch = (uint8_t)stream.Peek();
157 if (ch == 0) {
158 stream.Seek(4, LcfReader::FromCurrent);
159 break;
160 }
161
162 if (stream.Tell() >= endpos) {
163 stream.Seek(endpos, LcfReader::FromStart);
164 fprintf(stderr, "Event command corrupted at %" PRIu32 "\n", stream.Tell());
165 for (;;) {
166 // Try finding the real end of the event command (4 0-bytes)
167 int i = 0;
168 for (; i < 4; ++i) {
169 stream.Read(ch);
170
171 if (ch != 0) {
172 break;
173 }
174 }
175
176 if (i == 4 || stream.Eof()) {
177 break;
178 }
179 }
180
181 break;
182 }
183
184 rpg::EventCommand command;
185 RawStruct<rpg::EventCommand>::ReadLcf(command, stream, 0);
186 event_commands.push_back(command);
187 }
188}
189
190void RawStruct<std::vector<rpg::EventCommand> >::WriteLcf(const std::vector<rpg::EventCommand>& event_commands, LcfWriter& stream) {
191 int count = event_commands.size();
192 for (int i = 0; i < count; i++)
193 RawStruct<rpg::EventCommand>::WriteLcf(event_commands[i], stream);
194 for (int i = 0; i < 4; i++)
195 stream.WriteInt(0);
196}
197
198int RawStruct<std::vector<rpg::EventCommand> >::LcfSize(const std::vector<rpg::EventCommand>& event_commands, LcfWriter& stream) {
199 int result = 0;
200 int count = event_commands.size();
201 for (int i = 0; i < count; i++)
202 result += RawStruct<rpg::EventCommand>::LcfSize(event_commands[i], stream);
203 result += 4;
204 return result;
205}
206
207void RawStruct<std::vector<rpg::EventCommand> >::WriteXml(const std::vector<rpg::EventCommand>& event_commands, XmlWriter& stream) {
208 std::vector<rpg::EventCommand>::const_iterator it;
209 for (it = event_commands.begin(); it != event_commands.end(); it++)
211}
212
213class EventCommandVectorXmlHandler : public XmlHandler {
214public:
215 EventCommandVectorXmlHandler(std::vector<rpg::EventCommand>& ref) : ref(ref) {}
216
217 void StartElement(XmlReader& stream, const char* name, const char** /* atts */) {
218 if (strcmp(name, "EventCommand") != 0)
219 stream.Error("Expecting %s but got %s", "EventCommand", name);
220 ref.resize(ref.size() + 1);
221 rpg::EventCommand& obj = ref.back();
222 stream.SetHandler(new EventCommandXmlHandler(obj));
223 }
224private:
225 std::vector<rpg::EventCommand>& ref;
226};
227
228void RawStruct<std::vector<rpg::EventCommand> >::BeginXml(std::vector<rpg::EventCommand>& obj, XmlReader& stream) {
229 stream.SetHandler(new EventCommandVectorXmlHandler(obj));
230}
231
232} //namespace lcf
std::vector< rpg::EventCommand > & ref
void StartElement(XmlReader &stream, const char *name, const char **)
EventCommandVectorXmlHandler(std::vector< rpg::EventCommand > &ref)
EventCommandXmlHandler(rpg::EventCommand &ref)
void EndElement(XmlReader &, const char *)
void CharacterData(XmlReader &, const std::string &data)
void StartElement(XmlReader &stream, const char *name, const char **)
enum lcf::EventCommandXmlHandler::@0 field
Definition: dbarray.cpp:13
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)