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