1 /*
2 *
3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
6 * Public License
7 *
8 * See LICENSING which should be included
9 * along with this file for more details
10 *
11 */
12
13 #ifndef __SAVE_H__
14 #define __SAVE_H__
15
16 #include <ctime>
17 #include <fstream>
18 #include <vector>
19 #include <deque>
20 #include <list>
21 #include <map>
22 #include <set>
23
24 #include "error.h"
25 #include "festring.h"
26 #include "fearray.h"
27
28 #define RAW_SAVE_LOAD(type)\
29 inline outputfile& operator<<(outputfile& SaveFile, type Value)\
30 {\
31 SaveFile.Write(reinterpret_cast<char*>(&Value), sizeof(Value));\
32 return SaveFile;\
33 }\
34 \
35 inline inputfile& operator>>(inputfile& SaveFile, type& Value)\
36 {\
37 SaveFile.Read(reinterpret_cast<char*>(&Value), sizeof(Value));\
38 return SaveFile;\
39 }
40
41 typedef std::map<festring, long> valuemap;
42
43 class outputfile
44 {
45 public:
46 outputfile(cfestring&, truth = true);
Put(char What)47 void Put(char What) { File.put(What); }
Write(cchar * Data,long Size)48 void Write(cchar* Data, long Size) { File.write(Data, Size); }
IsOpen()49 truth IsOpen() { return File.is_open(); }
50 void Close();
~outputfile()51 ~outputfile(){Close();}
52 static void SetSafeSaving(truth b);
GetFullFilename()53 festring GetFullFilename(){return FileName;}
54 private:
55 static truth bakcupBeforeSaving;
56 static truth saveOnNewFileAlways;
57 std::ofstream File;
58 festring FileName;
59 festring FileNameNewTmp;
60 };
61
62 class inputfile
63 {
64 public:
65 inputfile(cfestring&, const valuemap* = 0, truth = true);
66 festring ReadWord(truth = true);
67 void ReadWord(festring&, truth = true);
68 char ReadLetter(truth = true);
69 long ReadNumber(int = 0xFF, truth = false);
70 festring ReadStringOrNumber (long *num, truth *isString, truth PreserveTerminator=false);
71 v2 ReadVector2d();
72 rect ReadRect();
Get()73 int Get() { return File.get(); }
Read(char * Data,long Size)74 void Read(char* Data, long Size) { File.read(Data, Size); }
IsOpen()75 truth IsOpen() { return File.is_open(); }
Eof()76 truth Eof() { return File.eof(); }
SeekPosBegin(long Offset)77 void SeekPosBegin(long Offset) { File.seekg(Offset, std::ios::beg); }
SeekPosCurrent(long Offset)78 void SeekPosCurrent(long Offset) { File.seekg(Offset, std::ios::cur); }
SeekPosEnd(long Offset)79 void SeekPosEnd(long Offset) { File.seekg(Offset, std::ios::end); }
TellPos()80 long TellPos() { return File.tellg(); }
TellLine()81 ulong TellLine() { return TellLineOfPos(TellPos()); }
82 ulong TellLineOfPos(long);
GetFileName()83 cfestring& GetFileName() const { return FileName; }
Close()84 void Close() { File.close(); }
GetFullFilename()85 festring GetFullFilename(){return FileName;}
86 private:
87 festring ReadNumberIntr (int CallLevel, long *num, truth *isString, truth allowStr, truth PreserveTerminator);
88 int HandlePunct(festring&, int, int);
89 std::ifstream File;
90 festring FileName;
91 const valuemap* ValueMap;
92 truth lastWordWasString;
93 };
94
95 std::vector<festring> ListFiles(festring, cfestring&);
96 void MakePath(cfestring&);
97
98 /* Reads a binary form variable of type type and returns it.
99 * An inputfile template member function would be far more elegant,
100 * but VC doesn't seem to understand it. */
101
ReadType(inputfile & SaveFile)102 template <class type> inline type ReadType(inputfile& SaveFile)
103 {
104 type Variable;
105 SaveFile >> Variable;
106 return Variable;
107 }
108
ReadData(truth & Type,inputfile & SaveFile)109 inline void ReadData(truth& Type, inputfile& SaveFile)
110 { Type = SaveFile.ReadNumber(); }
ReadData(char & Type,inputfile & SaveFile)111 inline void ReadData(char& Type, inputfile& SaveFile)
112 { Type = SaveFile.ReadNumber(); }
ReadData(uchar & Type,inputfile & SaveFile)113 inline void ReadData(uchar& Type, inputfile& SaveFile)
114 { Type = SaveFile.ReadNumber(); }
ReadData(short & Type,inputfile & SaveFile)115 inline void ReadData(short& Type, inputfile& SaveFile)
116 { Type = SaveFile.ReadNumber(); }
ReadData(ushort & Type,inputfile & SaveFile)117 inline void ReadData(ushort& Type, inputfile& SaveFile)
118 { Type = SaveFile.ReadNumber(); }
ReadData(long & Type,inputfile & SaveFile)119 inline void ReadData(long& Type, inputfile& SaveFile)
120 { Type = SaveFile.ReadNumber(); }
ReadData(ulong & Type,inputfile & SaveFile)121 inline void ReadData(ulong& Type, inputfile& SaveFile)
122 { Type = SaveFile.ReadNumber(); }
ReadData(int & Type,inputfile & SaveFile)123 inline void ReadData(int& Type, inputfile& SaveFile)
124 { Type = SaveFile.ReadNumber(); }
ReadData(packv2 & Type,inputfile & SaveFile)125 inline void ReadData(packv2& Type, inputfile& SaveFile)
126 { Type = SaveFile.ReadVector2d(); }
ReadData(v2 & Type,inputfile & SaveFile)127 inline void ReadData(v2& Type, inputfile& SaveFile)
128 { Type = SaveFile.ReadVector2d(); }
ReadData(rect & Type,inputfile & SaveFile)129 inline void ReadData(rect& Type, inputfile& SaveFile)
130 { Type = SaveFile.ReadRect(); }
131 void ReadData(festring&, inputfile&);
132 void ReadData(fearray<long>&, inputfile&);
133 void ReadData(fearray<festring>&, inputfile&);
134
135 template <class type>
ReadData(fearray<type> & Array,inputfile & SaveFile)136 inline void ReadData(fearray<type>& Array, inputfile& SaveFile)
137 {
138 Array.Clear();
139 festring Word;
140 SaveFile.ReadWord(Word);
141
142 if(Word == "=")
143 SaveFile.ReadWord(Word);
144
145 if(Word == "=")
146 {
147 Array.Allocate(1);
148 ReadData(Array.Data[0], SaveFile);
149 return;
150 }
151
152 if(Word != "{")
153 ABORT("Array syntax error \"%s\" found in file %s, line %ld!",
154 Word.CStr(), SaveFile.GetFileName().CStr(), SaveFile.TellLine());
155
156 typedef typename fearray<type>::sizetype sizetype;
157 sizetype Size = SaveFile.ReadNumber();
158 Array.Allocate(Size);
159
160 for(sizetype c = 0; c < Size; ++c)
161 ReadData(Array.Data[c], SaveFile);
162
163 if(SaveFile.ReadWord() != "}")
164 ABORT("Illegal array terminator \"%s\" encountered in file %s, line %ld!",
165 Word.CStr(), SaveFile.GetFileName().CStr(), SaveFile.TellLine());
166 }
167
168 inline outputfile& operator<<(outputfile& SaveFile, truth Value)
169 {
170 SaveFile.Put(Value);
171 return SaveFile;
172 }
173
174 inline inputfile& operator>>(inputfile& SaveFile, truth& Value)
175 {
176 Value = SaveFile.Get();
177 return SaveFile;
178 }
179
180 inline outputfile& operator<<(outputfile& SaveFile, char Value)
181 {
182 SaveFile.Put(Value);
183 return SaveFile;
184 }
185
186 inline inputfile& operator>>(inputfile& SaveFile, char& Value)
187 {
188 Value = SaveFile.Get();
189 return SaveFile;
190 }
191
192 inline outputfile& operator<<(outputfile& SaveFile, uchar Value)
193 {
194 SaveFile.Put(Value);
195 return SaveFile;
196 }
197
198 inline inputfile& operator>>(inputfile& SaveFile, uchar& Value)
199 {
200 Value = SaveFile.Get();
201 return SaveFile;
202 }
203
204 inline outputfile& operator<<(outputfile& SaveFile, short Value)
205 {
206 SaveFile.Put(Value);
207 SaveFile.Put(Value >> 8);
208 return SaveFile;
209 }
210
211 inline inputfile& operator>>(inputfile& SaveFile, short& Value)
212 {
213 int LowWord = SaveFile.Get();
214 Value = SaveFile.Get() << 8 | LowWord;
215 return SaveFile;
216 }
217
218 inline outputfile& operator<<(outputfile& SaveFile, ushort Value)
219 {
220 SaveFile.Put(Value);
221 SaveFile.Put(Value >> 8);
222 return SaveFile;
223 }
224
225 inline inputfile& operator>>(inputfile& SaveFile, ushort& Value)
226 {
227 int LowWord = SaveFile.Get();
228 Value = SaveFile.Get() << 8 | LowWord;
229 return SaveFile;
230 }
231
232 RAW_SAVE_LOAD(long)
233 RAW_SAVE_LOAD(ulong)
234 RAW_SAVE_LOAD(int)
235 RAW_SAVE_LOAD(uint)
236 RAW_SAVE_LOAD(double)
237 RAW_SAVE_LOAD(packv2)
238 RAW_SAVE_LOAD(v2)
239 RAW_SAVE_LOAD(rect)
240
241 outputfile& operator<<(outputfile&, cfestring&);
242 inputfile& operator>>(inputfile&, festring&);
243 outputfile& operator<<(outputfile&, cchar*);
244 inputfile& operator>>(inputfile&, char*&);
245
246 template <class type1, class type2>
247 inline outputfile& operator<<(outputfile& SaveFile,
248 const std::pair<type1, type2>& Pair)
249 {
250 SaveFile << Pair.first << Pair.second;
251 return SaveFile;
252 }
253
254 template <class type1, class type2>
255 inline inputfile& operator>>(inputfile& SaveFile,
256 std::pair<type1, type2>& Pair)
257 {
258 SaveFile >> Pair.first >> Pair.second;
259 return SaveFile;
260 }
261
262 template <class type>
263 inline outputfile& operator<<(outputfile& SaveFile,
264 const std::vector<type>& Vector)
265 {
266 SaveFile << ulong(Vector.size());
267
268 for(ulong c = 0; c < Vector.size(); ++c)
269 SaveFile << Vector[c];
270
271 return SaveFile;
272 }
273
274 template <class type>
275 inline inputfile& operator>>(inputfile& SaveFile,
276 std::vector<type>& Vector)
277 {
278 Vector.resize(ReadType<ulong>(SaveFile), type());
279
280 for(ulong c = 0; c < Vector.size(); ++c)
281 SaveFile >> Vector[c];
282
283 return SaveFile;
284 }
285
286 template <class type>
287 inline outputfile& operator<<(outputfile& SaveFile,
288 const std::deque<type>& Deque)
289 {
290 SaveFile << ulong(Deque.size());
291
292 for(ulong c = 0; c < Deque.size(); ++c)
293 SaveFile << Deque[c];
294
295 return SaveFile;
296 }
297
298 template <class type>
299 inline inputfile& operator>>(inputfile& SaveFile,
300 std::deque<type>& Deque)
301 {
302 Deque.resize(ReadType<ulong>(SaveFile), type());
303
304 for(ulong c = 0; c < Deque.size(); ++c)
305 SaveFile >> Deque[c];
306
307 return SaveFile;
308 }
309
310 template <class type>
311 inline outputfile& operator<<(outputfile& SaveFile,
312 const std::list<type>& List)
313 {
314 SaveFile << ulong(List.size());
315
316 for(const type& Element : List)
317 SaveFile << Element;
318
319 return SaveFile;
320 }
321
322 template <class type>
323 inline inputfile& operator>>(inputfile& SaveFile,
324 std::list<type>& List)
325 {
326 List.resize(ReadType<ulong>(SaveFile), type());
327
328 for(type& Element : List)
329 SaveFile >> Element;
330
331 return SaveFile;
332 }
333
334 template <class type1, class type2>
335 inline outputfile& operator<<(outputfile& SaveFile,
336 const std::map<type1, type2>& Map)
337 {
338 SaveFile << ulong(Map.size());
339
340 for(const typename std::map<type1, type2>::value_type& Pair : Map)
341 SaveFile << Pair.first << Pair.second;
342
343 return SaveFile;
344 }
345
346 template <class type1, class type2>
347 inline inputfile& operator>>(inputfile& SaveFile,
348 std::map<type1, type2>& Map)
349 {
350 Map.clear();
351 type1 First;
352 ulong Size;
353 SaveFile >> Size;
354 typename std::map<type1, type2>::iterator i;
355
356 for(ulong c = 0; c < Size; ++c)
357 {
358 SaveFile >> First;
359 i = Map.insert(Map.end(), std::make_pair(First, type2()));
360 SaveFile >> i->second;
361 }
362
363 return SaveFile;
364 }
365
366 template <class type>
367 inline outputfile& operator<<(outputfile& SaveFile,
368 const std::set<type>& Set)
369 {
370 SaveFile << ulong(Set.size());
371
372 for(const typename std::set<type>::value_type& Element : Set)
373 SaveFile << Element;
374
375 return SaveFile;
376 }
377
378 template <class type>
379 inline inputfile& operator>>(inputfile& SaveFile,
380 std::set<type>& Set)
381 {
382 Set.clear();
383 ulong Size;
384 SaveFile >> Size;
385
386 for(ulong c = 0; c < Size; ++c)
387 {
388 type Value;
389 SaveFile >> Value;
390 Set.insert(Value);
391 }
392
393 return SaveFile;
394 }
395
396 template <class type>
397 inline outputfile& operator<<(outputfile& SaveFile,
398 const fearray<type>& Array)
399 {
400 typename fearray<type>::sizetype c, Size = Array.Size;
401 SaveFile << Size;
402
403 for(c = 0; c < Size; ++c)
404 SaveFile << Array[c];
405
406 return SaveFile;
407 }
408
409 template <class type>
410 inline inputfile& operator>>(inputfile& SaveFile,
411 fearray<type>& Array)
412 {
413 typename fearray<type>::sizetype c, Size;
414 SaveFile >> Size;
415 Array.Allocate(Size);
416
417 for(c = 0; c < Size; ++c)
418 SaveFile >> Array[c];
419
420 return SaveFile;
421 }
422
423 template <class type>
SaveLinkedList(outputfile & SaveFile,const type * Element)424 inline outputfile& SaveLinkedList(outputfile& SaveFile,
425 const type* Element)
426 {
427 for(const type* E = Element; E; E = E->Next)
428 {
429 SaveFile.Put(true);
430 SaveFile << E;
431 }
432
433 SaveFile.Put(false);
434 return SaveFile;
435 }
436
437 template <class type>
LoadLinkedList(inputfile & SaveFile,type * & Element)438 inline inputfile& LoadLinkedList(inputfile& SaveFile,
439 type*& Element)
440 {
441 if(SaveFile.Get())
442 {
443 SaveFile >> Element;
444 type* E;
445
446 for(E = Element; SaveFile.Get(); E = E->Next)
447 SaveFile >> E->Next;
448
449 E->Next = 0;
450 }
451 else
452 Element = 0;
453
454 return SaveFile;
455 }
456
457 template <class type>
SaveArray(outputfile & SaveFile,const type * Array,int Count)458 inline outputfile& SaveArray(outputfile& SaveFile,
459 const type* Array, int Count)
460 {
461 for(int c = 0; c < Count; ++c)
462 SaveFile << Array[c];
463
464 return SaveFile;
465 }
466
467 template <class type>
LoadArray(inputfile & SaveFile,type * Array,int Count)468 inline inputfile& LoadArray(inputfile& SaveFile,
469 type* Array, int Count)
470 {
471 for(int c = 0; c < Count; ++c)
472 SaveFile >> Array[c];
473
474 return SaveFile;
475 }
476
477 festring GetUserDataDir();
478
479 #endif
480