1 #include "main.hpp"
2 #include "json.hpp"
3
4 #include "rapidjson/document.h"
5 #include "rapidjson/writer.h"
6 #include "rapidjson/prettywriter.h"
7 #include "rapidjson/error/en.h"
8
9 const Uint32 BinaryFormatTag = *"spff";
10
11 class JsonFileWriter : public FileInterface {
12 public:
13
JsonFileWriter()14 JsonFileWriter()
15 : buffer()
16 , writer(buffer)
17 {
18 }
19
writeObject(FILE * file,const FileHelper::SerializationFunc & serialize)20 static bool writeObject(FILE * file, const FileHelper::SerializationFunc& serialize) {
21 JsonFileWriter jfw;
22
23 jfw.beginObject();
24 serialize(&jfw);
25 jfw.endObject();
26
27 jfw.save(file);
28 return true;
29 }
30
isReading() const31 virtual bool isReading() const override { return false; }
32
beginObject()33 virtual void beginObject() override {
34 writer.StartObject();
35 }
endObject()36 virtual void endObject() override {
37 writer.EndObject();
38 }
39
beginArray(Uint32 & size)40 virtual void beginArray(Uint32 & size) override {
41 writer.StartArray();
42 }
endArray()43 virtual void endArray() override {
44 writer.EndArray();
45 }
46
propertyName(const char * fieldName)47 virtual void propertyName(const char * fieldName) override {
48 writer.Key(fieldName);
49 }
50
value(Uint32 & value)51 virtual void value(Uint32& value) override {
52 writer.Uint(value);
53 }
value(Sint32 & value)54 virtual void value(Sint32& value) override {
55 writer.Int(value);
56 }
value(float & value)57 virtual void value(float& value) override {
58 writer.Double(value);
59 }
value(double & value)60 virtual void value(double& value) override {
61 writer.Double(value);
62 }
value(bool & value)63 virtual void value(bool& value) override {
64 writer.Bool(value);
65 }
value(std::string & value,Uint32 maxLength)66 virtual void value(std::string& value, Uint32 maxLength) override {
67 assert(maxLength == 0 || value.size() <= maxLength);
68 writer.String(value.c_str());
69 }
70
71 private:
72
save(FILE * file)73 void save(FILE * file) {
74 buffer.Flush();
75 fputs(buffer.GetString(), file);
76 }
77
78 FILE * fp;
79 rapidjson::StringBuffer buffer;
80 rapidjson::PrettyWriter<rapidjson::StringBuffer> writer;
81 };
82
83 class JsonFileReader : public FileInterface {
84 public:
85
readObject(FILE * fp,const FileHelper::SerializationFunc & serialize)86 static bool readObject(FILE * fp, const FileHelper::SerializationFunc & serialize) {
87 JsonFileReader jfr;
88
89 if (!jfr.readAllFileData(fp)) {
90 return false;
91 }
92
93 jfr.beginObject();
94 serialize(&jfr);
95 jfr.endObject();
96
97 return true;
98 }
99
isReading() const100 virtual bool isReading() const override { return true; }
101
beginObject()102 virtual void beginObject() override {
103 auto cv = GetCurrentValue();
104 assert(cv->IsObject());
105 DocIterator di;
106 di.it = cv;
107 di.index = -1;
108 stack.push_back(di);
109 }
110
endObject()111 virtual void endObject() override {
112 stack.pop_back();
113 }
114
beginArray(Uint32 & size)115 virtual void beginArray(Uint32 & size) override {
116 auto cv = GetCurrentValue();
117 assert(cv->IsArray());
118 DocIterator di;
119 di.it = cv;
120 di.index = 0;
121 stack.push_back(di);
122 size = di.it->GetArray().Size();
123 }
124
endArray()125 virtual void endArray() override {
126 stack.pop_back();
127 }
propertyName(const char * fieldName)128 virtual void propertyName(const char * fieldName) override {
129 propName = fieldName;
130 }
value(Uint32 & value)131 virtual void value(Uint32& value) override {
132 auto cv = GetCurrentValue();
133 assert(cv->IsUint());
134 value = cv->GetUint();
135 }
value(Sint32 & value)136 virtual void value(Sint32& value) override {
137 auto cv = GetCurrentValue();
138 assert(cv->IsInt());
139 value = cv->GetInt();
140 }
value(float & value)141 virtual void value(float& value) override {
142 auto cv = GetCurrentValue();
143 assert(cv->IsFloat());
144 value = cv->GetFloat();
145 }
value(double & value)146 virtual void value(double& value) override {
147 auto cv = GetCurrentValue();
148 assert(cv->IsDouble());
149 value = cv->GetDouble();
150 }
value(bool & value)151 virtual void value(bool& value) override {
152 auto cv = GetCurrentValue();
153 assert(cv->IsBool());
154 value = cv->GetBool();
155 }
value(std::string & value,Uint32 maxLength)156 virtual void value(std::string& value, Uint32 maxLength) override {
157 auto cv = GetCurrentValue();
158 assert(cv->IsString());
159 assert(maxLength == 0 || cv->GetStringLength() <= maxLength);
160 value = cv->GetString();
161 }
162
163 protected:
164
GetCurrentValue()165 rapidjson::Value::ConstValueIterator GetCurrentValue() {
166 if (stack.empty()) {
167 assert(propName == nullptr);
168 return &doc;
169 }
170
171 DocIterator& di = stack.back();
172 if (di.it->IsArray()) {
173 assert(di.index >= 0);
174 return &di.it->GetArray()[di.index++];
175 }
176
177 assert(propName != nullptr);
178 rapidjson::Value::ConstValueIterator result = &(*di.it)[propName];
179 propName = nullptr;
180 return result;
181 }
182
readAllFileData(FILE * fp)183 bool readAllFileData(FILE * fp) {
184 if (fseek(fp, 0, SEEK_END)) {
185 printlog("JsonFileReader: failed to seek end (%d)", errno);
186 return false;
187 }
188
189 long size = ftell(fp);
190 if (fseek(fp, 0, SEEK_SET)) {
191 printlog("JsonFileReader: failed to seek beg (%d)", errno);
192 return false;
193 }
194
195 // reserve an extra byte for the null terminator
196 char * data = (char *)calloc(sizeof(char), size + 1);
197 assert(data);
198
199 size_t bytesRead = fread(data, sizeof(char), size, fp);
200 if (bytesRead != size) {
201 printlog("JsonFileReader: failed to read data (%d)", errno);
202 free(data);
203 return false;
204 }
205
206 // null terminate
207 data[size] = 0;
208
209 rapidjson::ParseResult result = doc.Parse(data);
210
211 free(data);
212
213 if (!result) {
214 printlog("JsonFileReader: parse error: %s (%d)", rapidjson::GetParseError_En(result.Code()), result.Offset());
215 return false;
216 }
217
218 return true;
219 }
220
221 struct DocIterator {
222 rapidjson::Value::ConstValueIterator it;
223 Uint32 index;
224 };
225
226 rapidjson::Document doc;
227 const char * propName = nullptr;
228 std::vector<DocIterator> stack;
229 };
230
231 class BinaryFileWriter : public FileInterface {
232 public:
233
BinaryFileWriter(FILE * file)234 BinaryFileWriter(FILE * file)
235 : fp(file)
236 {
237 }
238
~BinaryFileWriter()239 ~BinaryFileWriter() {
240 }
241
writeObject(FILE * fp,const FileHelper::SerializationFunc & serialize)242 static bool writeObject(FILE * fp, const FileHelper::SerializationFunc & serialize) {
243 BinaryFileWriter bfw(fp);
244
245 bfw.writeHeader();
246
247 bfw.beginObject();
248 serialize(&bfw);
249 bfw.endObject();
250
251 return true;
252 }
253
isReading() const254 virtual bool isReading() const override { return false; }
255
beginObject()256 virtual void beginObject() override {
257 }
258
endObject()259 virtual void endObject() override {
260 }
261
beginArray(Uint32 & size)262 virtual void beginArray(Uint32 & size) override {
263 fwrite(&size, sizeof(size), 1, fp);
264 }
265
endArray()266 virtual void endArray() override {
267 }
268
propertyName(const char * name)269 virtual void propertyName(const char * name) override {
270 }
271
value(Uint32 & v)272 virtual void value(Uint32& v) override {
273 fwrite(&v, sizeof(v), 1, fp);
274 }
value(Sint32 & v)275 virtual void value(Sint32& v) override {
276 fwrite(&v, sizeof(v), 1, fp);
277 }
value(float & v)278 virtual void value(float& v) override {
279 fwrite(&v, sizeof(v), 1, fp);
280 }
value(double & v)281 virtual void value(double& v) override {
282 fwrite(&v, sizeof(v), 1, fp);
283 }
value(bool & v)284 virtual void value(bool& v) override {
285 fwrite(&v, sizeof(v), 1, fp);
286 }
value(std::string & v,Uint32 maxLength)287 virtual void value(std::string& v, Uint32 maxLength) override {
288 assert(maxLength == 0 || v.size() <= maxLength);
289 writeStringInternal(v);
290 }
291
292 private:
293
writeHeader()294 void writeHeader() {
295 fwrite(&BinaryFormatTag, sizeof(BinaryFormatTag), 1, fp);
296 }
297
writeStringInternal(const std::string & v)298 void writeStringInternal(const std::string& v) {
299 Uint32 len = (Uint32)v.size();
300 fwrite(&len, sizeof(len), 1, fp);
301 if (len) {
302 fwrite(v.c_str(), sizeof(char), len, fp);
303 }
304 }
305
306 FILE* fp = nullptr;
307 };
308
309 class BinaryFileReader : public FileInterface {
310 public:
311
BinaryFileReader(FILE * file)312 BinaryFileReader(FILE * file)
313 : fp(file)
314 {
315 }
316
readObject(FILE * fp,const FileHelper::SerializationFunc & serialize)317 static bool readObject(FILE * fp, const FileHelper::SerializationFunc & serialize) {
318 BinaryFileReader bfr(fp);
319
320 if (!bfr.readHeader()) {
321 return false;
322 }
323
324 bfr.beginObject();
325 serialize(&bfr);
326 bfr.endObject();
327
328 return true;
329 }
330
isReading() const331 virtual bool isReading() const override { return true; }
332
beginObject()333 virtual void beginObject() override {
334 }
335
endObject()336 virtual void endObject() override {
337 }
338
beginArray(Uint32 & size)339 virtual void beginArray(Uint32 & size) override {
340 size_t read = fread(&size, sizeof(size), 1, fp);
341 assert(read == 1);
342 }
343
endArray()344 virtual void endArray() override {
345 }
346
propertyName(const char * name)347 virtual void propertyName(const char * name) override {
348 }
349
value(Uint32 & v)350 virtual void value(Uint32& v) override {
351 size_t read = fread(&v, sizeof(v), 1, fp);
352 assert(read == 1);
353 }
value(Sint32 & v)354 virtual void value(Sint32& v) override {
355 size_t read = fread(&v, sizeof(v), 1, fp);
356 assert(read == 1);
357 }
value(float & v)358 virtual void value(float& v) override {
359 size_t read = fread(&v, sizeof(v), 1, fp);
360 assert(read == 1);
361 }
value(double & v)362 virtual void value(double& v) override {
363 size_t read = fread(&v, sizeof(v), 1, fp);
364 assert(read == 1);
365 }
value(bool & v)366 virtual void value(bool& v) override {
367 size_t read = fread(&v, sizeof(v), 1, fp);
368 assert(read == 1);
369 }
value(std::string & v,Uint32 maxLength)370 virtual void value(std::string& v, Uint32 maxLength) override {
371 readStringInternal(v);
372 assert(maxLength == 0 || v.size() <= maxLength);
373 }
374
375 private:
376
readHeader()377 bool readHeader() {
378 Uint32 fileFormatTag;
379 size_t read = fread(&fileFormatTag, sizeof(fileFormatTag), 1, fp);
380 if (read != 1) {
381 printlog("BinaryFileReader: failed to read format tag (%d)", errno);
382 return false;
383 }
384
385 if (fileFormatTag != BinaryFormatTag) {
386 printlog("BinaryFileReader: file format tag mismatch (expected %x, got %x)", BinaryFormatTag, fileFormatTag);
387 return false;
388 }
389
390 return true;
391 }
392
readStringInternal(std::string & v)393 void readStringInternal(std::string & v) {
394 Uint32 len;
395 size_t read = fread(&len, sizeof(len), 1, fp);
396 assert(read == 1);
397
398 if (len) {
399 v.reserve(len);
400 read = fread(&v[0u], sizeof(char), len, fp);
401 assert(read == len);
402 }
403 }
404
405 FILE* fp;
406 };
407
GetFileFormat(FILE * file)408 static EFileFormat GetFileFormat(FILE * file) {
409 Uint32 fileFormatTag = 0;
410 fread(&fileFormatTag, sizeof(fileFormatTag), 1, file);
411 fseek(file, 0, SEEK_SET);
412
413 if (fileFormatTag == BinaryFormatTag) {
414 return EFileFormat::Binary;
415 }
416 else {
417 return EFileFormat::Json;
418 }
419 }
420
writeObjectInternal(const char * filename,EFileFormat format,const SerializationFunc & serialize)421 bool FileHelper::writeObjectInternal(const char * filename, EFileFormat format, const SerializationFunc& serialize) {
422 FILE * file = fopen(filename, "wb");
423 #ifndef NDEBUG
424 printlog("Opening file '%s' for write", filename);
425 #endif
426 if (!file) {
427 printlog("Unable to open file '%s' for write (%d)", filename, errno);
428 return false;
429 }
430
431 bool success = false;
432 if (format == EFileFormat::Binary) {
433 success = BinaryFileWriter::writeObject(file, serialize);
434 }
435 else if (format == EFileFormat::Json) {
436 success = JsonFileWriter::writeObject(file, serialize);
437 }
438 else {
439 assert(false);
440 }
441
442 fclose(file);
443
444 return success;
445 }
446
readObjectInternal(const char * filename,const SerializationFunc & serialize)447 bool FileHelper::readObjectInternal(const char * filename, const SerializationFunc& serialize) {
448 FILE * file = fopen(filename, "rb");
449 #ifndef NDEBUG
450 printlog("Opening file '%s' for read", filename);
451 #endif
452 if (!file) {
453 printlog("Unable to open file '%s' for read (%d)", filename, errno);
454 return false;
455 }
456
457 EFileFormat format = GetFileFormat(file);
458
459 bool success = false;
460 if (format == EFileFormat::Binary) {
461 success = BinaryFileReader::readObject(file, serialize);
462 }
463 else if(format == EFileFormat::Json) {
464 success = JsonFileReader::readObject(file, serialize);
465 }
466 else {
467 assert(false);
468 }
469
470 fclose(file);
471
472 return success;
473 }
474