liblcf
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
reader_struct.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 liblcf authors
3  * This file is released under the MIT License
4  * http://opensource.org/licenses/MIT
5  */
6 
7 #include <cstring>
8 #include <iostream>
9 #include <iomanip>
10 #include "ldb_reader.h"
11 #include "lmt_reader.h"
12 #include "lmu_reader.h"
13 #include "lsd_reader.h"
14 #include "reader_struct.h"
15 #include "rpg_save.h"
16 
17 // Read/Write Struct
18 
19 template <class S>
21  if (!field_map.empty())
22  return;
23  for (int i = 0; fields[i] != NULL; i++)
24  field_map[fields[i]->id] = fields[i];
25 }
26 
27 template <class S>
29  if (!tag_map.empty())
30  return;
31  for (int i = 0; fields[i] != NULL; i++)
32  tag_map[fields[i]->name] = fields[i];
33 }
34 
35 template <class S>
36 void Struct<S>::ReadLcf(S& obj, LcfReader& stream) {
37  MakeFieldMap();
38 
39  LcfReader::Chunk chunk_info;
40 
41  while (!stream.Eof()) {
42  chunk_info.ID = stream.ReadInt();
43  if (chunk_info.ID == 0)
44  break;
45 
46  chunk_info.length = stream.ReadInt();
47  if (chunk_info.length == 0)
48  continue;
49 
50  typename field_map_type::const_iterator it = field_map.find(chunk_info.ID);
51  if (it != field_map.end()) {
52 #ifdef LCF_DEBUG_TRACE
53  printf("0x%02x (size: %d, pos: 0x%x): %s\n", chunk_info.ID, chunk_info.length, stream.Tell(), it->second->name);
54 #endif
55  it->second->ReadLcf(obj, stream, chunk_info.length);
56  }
57  else
58  stream.Skip(chunk_info);
59  }
60 }
61 
62 template <class S>
63 void Struct<S>::WriteLcf(const S& obj, LcfWriter& stream) {
64  S ref = S();
65  int last = -1;
66  for (int i = 0; fields[i] != NULL; i++) {
67  const Field<S>* field = fields[i];
68  if (field->id < last)
69  std::cerr << "field order mismatch: " << field->id
70  << " after " << last
71  << " in struct " << name
72  << std::endl;
73  //printf("\n%s", field->name);
74  if (field->IsDefault(obj, ref)) {
75  //printf(" -> default");
76  continue;
77  }
78  stream.WriteInt(field->id);
79  stream.WriteInt(field->LcfSize(obj, stream));
80  field->WriteLcf(obj, stream);
81  }
82  stream.WriteInt(0);
83 }
84 
85 template <>
86 void Struct<RPG::Save>::WriteLcf(const RPG::Save& obj, LcfWriter& stream) {
87  RPG::Save ref = RPG::Save();
88  int last = -1;
89  for (int i = 0; fields[i] != NULL; i++) {
90  const Field<RPG::Save>* field = fields[i];
91  if (field->id < last)
92  std::cerr << "field order mismatch: " << field->id
93  << " after " << last
94  << " in struct " << name
95  << std::endl;
96  printf("\n%s", field->name);
97  if (field->IsDefault(obj, ref)) {
98  printf(" -> default");
99  continue;
100  }
101  stream.WriteInt(field->id);
102  stream.WriteInt(field->LcfSize(obj, stream));
103  field->WriteLcf(obj, stream);
104  }
105  // stream.WriteInt(0); // This last byte broke savegames
106 }
107 
108 template <class S>
109 int Struct<S>::LcfSize(const S& obj, LcfWriter& stream) {
110  int result = 0;
111  S ref = S();
112  for (int i = 0; fields[i] != NULL; i++) {
113  const Field<S>* field = fields[i];
114  //printf("%s\n", field->name);
115  if (field->IsDefault(obj, ref))
116  continue;
117  result += LcfReader::IntSize(field->id);
118  int size = field->LcfSize(obj, stream);
119  result += LcfReader::IntSize(size);
120  result += size;
121  }
122  result += LcfReader::IntSize(0);
123  return result;
124 }
125 
126 template <class S>
127 void Struct<S>::WriteXml(const S& obj, XmlWriter& stream) {
128  IDReader::WriteXmlTag(obj, name, stream);
129  for (int i = 0; fields[i] != NULL; i++) {
130  const Field<S>* field = fields[i];
131  field->WriteXml(obj, stream);
132  }
133  stream.EndElement(name);
134 }
135 
136 template <class S>
137 class StructXmlHandler : public XmlHandler {
138 public:
139  StructXmlHandler(S& ref) : ref(ref), field(NULL) {
141  }
142 
143  void StartElement(XmlReader& stream, const char* name, const char** /* atts */) {
144  field = Struct<S>::tag_map[name];
145  field->BeginXml(ref, stream);
146  }
147 
148  void EndElement(XmlReader& /* stream */, const char* /* name */) {
149  field = NULL;
150  }
151 
152  void CharacterData(XmlReader& /* stream */, const std::string& data) {
153  if (field != NULL)
154  field->ParseXml(ref, data);
155  }
156 private:
157  S& ref;
158  const Field<S>* field;
159 };
160 
161 template <class S>
163 public:
164  StructFieldXmlHandler(S& ref) : ref(ref) {}
165 
166  void StartElement(XmlReader& stream, const char* name, const char** atts) {
167  if (strcmp(name, Struct<S>::name) != 0)
168  stream.Error("Expecting %s but got %s", Struct<S>::name, name);
170  stream.SetHandler(new StructXmlHandler<S>(ref));
171  }
172 private:
173  S& ref;
174 };
175 
176 template <class S>
177 void Struct<S>::BeginXml(S& obj, XmlReader& stream) {
178  stream.SetHandler(new StructFieldXmlHandler<S>(obj));
179 }
180 
181 // Read/Write std::vector<Struct>
182 
183 template <class S>
184 void Struct<S>::ReadLcf(std::vector<S>& vec, LcfReader& stream) {
185  int count = stream.ReadInt();
186  vec.resize(count);
187  for (int i = 0; i < count; i++) {
188  IDReader::ReadID(vec[i], stream);
189  TypeReader<S>::ReadLcf(vec[i], stream, 0);
190  }
191 }
192 
193 template <class S>
194 void Struct<S>::WriteLcf(const std::vector<S>& vec, LcfWriter& stream) {
195  int count = vec.size();
196  stream.WriteInt(count);
197  for (int i = 0; i < count; i++) {
198  IDReader::WriteID(vec[i], stream);
199  TypeReader<S>::WriteLcf(vec[i], stream);
200  }
201 }
202 
203 template <class S>
204 int Struct<S>::LcfSize(const std::vector<S>& vec, LcfWriter& stream) {
205  int result = 0;
206  int count = vec.size();
207  result += LcfReader::IntSize(count);
208  for (int i = 0; i < count; i++) {
209  result += IDReader::IDSize(vec[i]);
210  result += TypeReader<S>::LcfSize(vec[i], stream);
211  }
212  return result;
213 }
214 
215 template <class S>
216 void Struct<S>::WriteXml(const std::vector<S>& vec, XmlWriter& stream) {
217  int count = vec.size();
218  for (int i = 0; i < count; i++)
219  TypeReader<S>::WriteXml(vec[i], stream);
220 }
221 
222 template <class S>
224 public:
225  StructVectorXmlHandler(std::vector<S>& ref) : ref(ref) {}
226 
227  void StartElement(XmlReader& stream, const char* name, const char** atts) {
228  if (strcmp(name, Struct<S>::name) != 0)
229  stream.Error("Expecting %s but got %s", Struct<S>::name, name);
230  ref.resize(ref.size() + 1);
231  S& obj = ref.back();
233  stream.SetHandler(new StructXmlHandler<S>(obj));
234  }
235 private:
236  std::vector<S>& ref;
237 };
238 
239 template <class S>
240 void Struct<S>::BeginXml(std::vector<S>& obj, XmlReader& stream) {
241  stream.SetHandler(new StructVectorXmlHandler<S>(obj));
242 }
243 
244 // Instantiate templates
245 
246 template class Struct<RPG::Actor>;
247 template class Struct<RPG::Animation>;
248 template class Struct<RPG::AnimationCellData>;
249 template class Struct<RPG::AnimationFrame>;
250 template class Struct<RPG::AnimationTiming>;
251 template class Struct<RPG::Attribute>;
252 template class Struct<RPG::BattleCommand>;
253 template class Struct<RPG::BattleCommands>;
254 template class Struct<RPG::BattlerAnimation>;
255 template class Struct<RPG::BattlerAnimationData>;
257 template class Struct<RPG::Chipset>;
258 template class Struct<RPG::Class>;
259 template class Struct<RPG::CommonEvent>;
260 template class Struct<RPG::Database>;
261 template class Struct<RPG::Encounter>;
262 template class Struct<RPG::Enemy>;
263 template class Struct<RPG::EnemyAction>;
264 template class Struct<RPG::Event>;
265 template class Struct<RPG::EventPage>;
266 template class Struct<RPG::EventPageCondition>;
267 template class Struct<RPG::Item>;
268 template class Struct<RPG::ItemAnimation>;
269 template class Struct<RPG::Learning>;
270 template class Struct<RPG::Map>;
271 template class Struct<RPG::MapInfo>;
272 template class Struct<RPG::MoveRoute>;
273 template class Struct<RPG::Music>;
274 template class Struct<RPG::Save>;
275 template class Struct<RPG::SaveActor>;
276 template class Struct<RPG::SaveCommonEvent>;
277 template class Struct<RPG::SaveEventCommands>;
278 template class Struct<RPG::SaveEventData>;
279 template class Struct<RPG::SaveEvents>;
280 template class Struct<RPG::SaveInventory>;
281 template class Struct<RPG::SaveMapEvent>;
282 template class Struct<RPG::SaveMapInfo>;
283 template class Struct<RPG::SavePartyLocation>;
284 template class Struct<RPG::SavePicture>;
285 template class Struct<RPG::SaveScreen>;
286 template class Struct<RPG::SaveSystem>;
287 template class Struct<RPG::SaveTarget>;
288 template class Struct<RPG::SaveTitle>;
289 template class Struct<RPG::SaveVehicleLocation>;
290 template class Struct<RPG::Skill>;
291 template class Struct<RPG::Sound>;
292 template class Struct<RPG::Start>;
293 template class Struct<RPG::State>;
294 template class Struct<RPG::Switch>;
295 template class Struct<RPG::System>;
296 template class Struct<RPG::Terms>;
297 template class Struct<RPG::Terrain>;
298 template class Struct<RPG::TestBattler>;
299 template class Struct<RPG::Troop>;
300 template class Struct<RPG::TroopMember>;
301 template class Struct<RPG::TroopPage>;
302 template class Struct<RPG::TroopPageCondition>;
303 template class Struct<RPG::Variable>;
static void MakeTagMap()
static void BeginXml(S &obj, XmlReader &stream)
RPG::Database data
Definition: data.cpp:11
void SetHandler(XmlHandler *handler)
Definition: reader_xml.cpp:92
void Skip(const struct LcfReader::Chunk &chunk_info)
Definition: reader_lcf.cpp:229
virtual void WriteLcf(const S &obj, LcfWriter &stream) const =0
void CharacterData(XmlReader &, const std::string &data)
virtual bool IsDefault(const S &obj, const S &ref) const =0
void WriteInt(int val)
Definition: writer_lcf.cpp:58
void EndElement(const std::string &name)
Definition: writer_xml.cpp:177
void Error(const char *fmt,...)
Definition: reader_xml.cpp:71
StructVectorXmlHandler(std::vector< S > &ref)
uint32_t length
Definition: reader_lcf.h:84
static void MakeFieldMap()
const char *const name
int ReadInt()
Definition: reader_lcf.cpp:82
void StartElement(XmlReader &stream, const char *name, const char **atts)
std::vector< S > & ref
virtual void WriteXml(const S &obj, XmlWriter &stream) const =0
static void ReadLcf(S &obj, LcfReader &stream)
bool Save(const std::string &filename, const std::string &encoding)
Definition: ldb_reader.cpp:40
void StartElement(XmlReader &stream, const char *name, const char **atts)
void StartElement(XmlReader &stream, const char *name, const char **)
static int LcfSize(const S &obj, LcfWriter &stream)
static int IntSize(unsigned int x)
Definition: reader_lcf.cpp:255
bool Eof() const
Definition: reader_lcf.cpp:174
uint32_t Tell()
Definition: reader_lcf.cpp:194
static void WriteLcf(const S &obj, LcfWriter &stream)
virtual int LcfSize(const S &obj, LcfWriter &stream) const =0
const Field< S > * field
void EndElement(XmlReader &, const char *)
static void WriteXml(const S &obj, XmlWriter &stream)