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