liblcf
lsd_reader.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of liblcf. Copyright (c) 2021 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 <cmath>
11 #include <fstream>
12 #include <cerrno>
13 #include <cstring>
14 
15 #include "lcf/lsd/reader.h"
16 #include "lcf/lsd/chunks.h"
17 #include "lcf/rpg/save.h"
18 #include "lcf/reader_util.h"
19 #include "reader_struct.h"
20 
21 namespace lcf {
22 
23 double LSD_Reader::ToTDateTime(std::time_t t) {
24  // 25569 is UnixDateDelta: number of days between 1970-01-01 and 1900-01-01
25  return(t / 86400.0 + 25569.0);
26 }
27 
28 std::time_t LSD_Reader::ToUnixTimestamp(double ms) {
29  return(std::time_t(ms * 86400.0 - 25569.0 * 86400.0 + 0.5));
30 }
31 
32 double LSD_Reader::GenerateTimestamp(std::time_t t) {
33  return ToTDateTime(t);
34 }
35 
36 void LSD_Reader::PrepareSave(rpg::Save& save, int32_t version) {
37  ++save.system.save_count;
38  save.title.timestamp = LSD_Reader::GenerateTimestamp();
39  save.easyrpg_data.version = version;
40 }
41 
42 std::unique_ptr<rpg::Save> LSD_Reader::Load(StringView filename, StringView encoding) {
43  std::ifstream stream(ToString(filename), std::ios::binary);
44  if (!stream.is_open()) {
45  fprintf(stderr, "Failed to open LSD file `%s' for reading : %s\n", ToString(filename).c_str(), strerror(errno));
46  return nullptr;
47  }
48  return LSD_Reader::Load(stream, encoding);
49 }
50 
51 bool LSD_Reader::Save(StringView filename, const rpg::Save& save, EngineVersion engine, StringView encoding) {
52  std::ofstream stream(ToString(filename), std::ios::binary);
53  if (!stream.is_open()) {
54  fprintf(stderr, "Failed to open LSD file `%s' for writing : %s\n", ToString(filename).c_str(), strerror(errno));
55  return false;
56  }
57  return LSD_Reader::Save(stream, save, engine, encoding);
58 }
59 
60 bool LSD_Reader::SaveXml(StringView filename, const rpg::Save& save, EngineVersion engine) {
61  std::ofstream stream(ToString(filename), std::ios::binary);
62  if (!stream.is_open()) {
63  fprintf(stderr, "Failed to open LSD XML file `%s' for writing : %s\n", ToString(filename).c_str(), strerror(errno));
64  return false;
65  }
66  return LSD_Reader::SaveXml(stream, save, engine);
67 }
68 
69 std::unique_ptr<rpg::Save> LSD_Reader::LoadXml(StringView filename) {
70  std::ifstream stream(ToString(filename), std::ios::binary);
71  if (!stream.is_open()) {
72  fprintf(stderr, "Failed to open LSD XML file `%s' for reading : %s\n", ToString(filename).c_str(), strerror(errno));
73  return nullptr;
74  }
75  return LSD_Reader::LoadXml(stream);
76 }
77 
78 std::unique_ptr<rpg::Save> LSD_Reader::Load(std::istream& filestream, StringView encoding) {
79  LcfReader reader(filestream, ToString(encoding));
80  if (!reader.IsOk()) {
81  LcfReader::SetError("Couldn't parse save file.\n");
82  return std::unique_ptr<rpg::Save>();
83  }
84  std::string header;
85  reader.ReadString(header, reader.ReadInt());
86  if (header.length() != 11) {
87  LcfReader::SetError("This is not a valid RPG2000 save.\n");
88  return std::unique_ptr<rpg::Save>();
89  }
90  if (header != "LcfSaveData") {
91  fprintf(stderr, "Warning: This header is not LcfSaveData and might not be a valid RPG2000 save.\n");
92  }
93  rpg::Save* save = new rpg::Save();
94  Struct<rpg::Save>::ReadLcf(*save, reader);
95  return std::unique_ptr<rpg::Save>(save);
96 }
97 
98 bool LSD_Reader::Save(std::ostream& filestream, const rpg::Save& save, EngineVersion engine, StringView encoding) {
99  LcfWriter writer(filestream, engine, ToString(encoding));
100  if (!writer.IsOk()) {
101  LcfReader::SetError("Couldn't parse save file.\n");
102  return false;
103  }
104  const std::string header("LcfSaveData");
105  writer.WriteInt(header.size());
106  writer.Write(header);
107 
108  Struct<rpg::Save>::WriteLcf(save, writer);
109  return true;
110 }
111 
112 bool LSD_Reader::SaveXml(std::ostream& filestream, const rpg::Save& save, EngineVersion engine) {
113  XmlWriter writer(filestream, engine);
114  if (!writer.IsOk()) {
115  LcfReader::SetError("Couldn't parse save file.\n");
116  return false;
117  }
118 
119  writer.BeginElement("LSD");
120  Struct<rpg::Save>::WriteXml(save, writer);
121  writer.EndElement("LSD");
122  return true;
123 }
124 
125 std::unique_ptr<rpg::Save> LSD_Reader::LoadXml(std::istream& filestream) {
126  XmlReader reader(filestream);
127  if (!reader.IsOk()) {
128  LcfReader::SetError("Couldn't parse save file.\n");
129  return std::unique_ptr<rpg::Save>();
130  }
131 
132  rpg::Save* save = new rpg::Save();
133  reader.SetHandler(new RootXmlHandler<rpg::Save>(*save, "LSD"));
134  reader.Parse();
135  return std::unique_ptr<rpg::Save>(save);
136 }
137 
138 } //namespace lcf
static void WriteXml(const S &obj, XmlWriter &stream)
static void WriteLcf(const S &obj, LcfWriter &stream)
static void ReadLcf(S &obj, LcfReader &stream)
Definition: dbarray.cpp:13