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