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