liblcf
ldb_reader.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 <fstream>
11 #include <cerrno>
12 #include <cstring>
13 
14 #include "lcf/ldb/reader.h"
15 #include "lcf/ldb/chunks.h"
16 #include "lcf/reader_util.h"
17 #include "reader_struct.h"
18 
19 namespace lcf {
20 
21 void LDB_Reader::PrepareSave(rpg::Database& db) {
22  ++db.system.save_count;
23 }
24 
25 std::unique_ptr<lcf::rpg::Database> LDB_Reader::Load(StringView filename, StringView encoding) {
26  std::ifstream stream(ToString(filename), std::ios::binary);
27  if (!stream.is_open()) {
28  fprintf(stderr, "Failed to open LDB file `%s' for reading : %s\n", ToString(filename).c_str(), strerror(errno));
29  return nullptr;
30  }
31  return LDB_Reader::Load(stream, encoding);
32 }
33 
34 bool LDB_Reader::Save(StringView filename, const lcf::rpg::Database& db, StringView encoding, SaveOpt opt) {
35  std::ofstream stream(ToString(filename), std::ios::binary);
36  if (!stream.is_open()) {
37  fprintf(stderr, "Failed to open LDB file `%s' for writing : %s\n", ToString(filename).c_str(), strerror(errno));
38  return false;
39  }
40  return LDB_Reader::Save(stream, db, encoding, opt);
41 }
42 
43 bool LDB_Reader::SaveXml(StringView filename, const lcf::rpg::Database& db) {
44  std::ofstream stream(ToString(filename), std::ios::binary);
45  if (!stream.is_open()) {
46  fprintf(stderr, "Failed to open LDB XML file `%s' for writing : %s\n", ToString(filename).c_str(), strerror(errno));
47  return false;
48  }
49  return LDB_Reader::SaveXml(stream, db);
50 }
51 
52 std::unique_ptr<lcf::rpg::Database> LDB_Reader::LoadXml(StringView filename) {
53  std::ifstream stream(ToString(filename), std::ios::binary);
54  if (!stream.is_open()) {
55  fprintf(stderr, "Failed to open LDB XML file `%s' for reading : %s\n", ToString(filename).c_str(), strerror(errno));
56  return nullptr;
57  }
58  return LDB_Reader::LoadXml(stream);
59 }
60 
61 std::unique_ptr<lcf::rpg::Database> LDB_Reader::Load(std::istream& filestream, StringView encoding) {
62  LcfReader reader(filestream, ToString(encoding));
63  if (!reader.IsOk()) {
64  LcfReader::SetError("Couldn't parse database file.\n");
65  return nullptr;
66  }
67  std::string header;
68  reader.ReadString(header, reader.ReadInt());
69  if (header.length() != 11) {
70  LcfReader::SetError("This is not a valid RPG2000 database.\n");
71  return nullptr;
72  }
73  if (header != "LcfDataBase") {
74  fprintf(stderr, "Warning: This header is not LcfDataBase and might not be a valid RPG2000 database.\n");
75  }
76  auto db = std::make_unique<lcf::rpg::Database>();
77  db->ldb_header = header;
78  TypeReader<rpg::Database>::ReadLcf(*db, reader, 0);
79 
80  const auto engine = GetEngineVersion(*db);
81  // Delayed initialization of some actor fields because they are engine
82  // dependent
83  for (auto& actor: db->actors) {
84  actor.Setup(engine == EngineVersion::e2k3);
85  }
86 
87  return db;
88 }
89 
90 bool LDB_Reader::Save(std::ostream& filestream, const lcf::rpg::Database& db, StringView encoding, SaveOpt opt) {
91  const auto engine = GetEngineVersion(db);
92  LcfWriter writer(filestream, engine, ToString(encoding));
93  if (!writer.IsOk()) {
94  LcfReader::SetError("Couldn't parse database file.\n");
95  return false;
96  }
97  std::string header;
98  if ( db.ldb_header.empty() || !bool(opt & SaveOpt::ePreserveHeader)) {
99  header = "LcfDataBase";
100  } else {
101  header= db.ldb_header;
102  }
103  writer.WriteInt(header.size());
104  writer.Write(header);
105  TypeReader<rpg::Database>::WriteLcf(db, writer);
106  return true;
107 }
108 
109 bool LDB_Reader::SaveXml(std::ostream& filestream, const lcf::rpg::Database& db) {
110  const auto engine = GetEngineVersion(db);
111  XmlWriter writer(filestream, engine);
112  if (!writer.IsOk()) {
113  LcfReader::SetError("Couldn't parse database file.\n");
114  return false;
115  }
116  writer.BeginElement("LDB");
117  TypeReader<rpg::Database>::WriteXml(db, writer);
118  writer.EndElement("LDB");
119  return true;
120 }
121 
122 std::unique_ptr<lcf::rpg::Database> LDB_Reader::LoadXml(std::istream& filestream) {
123  XmlReader reader(filestream);
124  if (!reader.IsOk()) {
125  LcfReader::SetError("Couldn't parse database file.\n");
126  return nullptr;;
127  }
128  auto db = std::make_unique<lcf::rpg::Database>();
129  reader.SetHandler(new RootXmlHandler<rpg::Database>(*db, "LDB"));
130  reader.Parse();
131 
132  const auto engine = GetEngineVersion(*db);
133  // Delayed initialization of some actor fields because they are engine
134  // dependent
135  for (auto& actor: db->actors) {
136  actor.Setup(engine == EngineVersion::e2k3);
137  }
138 
139  return db;
140 }
141 
142 } // namespace lcf
Definition: dbarray.cpp:13
EngineVersion GetEngineVersion(const lcf::rpg::Database &db)
Definition: saveopt.cpp:6