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