1 #ifndef LOADSAVEDATA_H
2 #define LOADSAVEDATA_H
3 
4 #include "Types.h"
5 #include "IEncodingCorrector.h"
6 
7 #include <string_theory/string>
8 
9 #include <algorithm>
10 #include <type_traits>
11 
12 
13 ////////////////////////////////////////////////////////////////////////////
14 // DataWriter
15 ////////////////////////////////////////////////////////////////////////////
16 
17 
18 /** Class for serializing data.
19  * Assumes the endianess is correct. */
20 class DataWriter
21 {
22 private:
23 	DataWriter(const DataWriter&) = delete; // no copy
24 	DataWriter& operator=(const DataWriter&) = delete; // no assign
25 public:
26 	/** Constructor.
27 	 * @param buf Pointer to the buffer for writing data. */
28 	explicit DataWriter(uint8_t* buf);
29 
30 	/** Write UTF-8 encoded string.
31 	 * @param str      String to write
32 	 * @param numChars Number of `char` characters to write. */
33 	void writeUTF8(const ST::string& str, size_t numChars);
34 
35 	/** Write UTF-16 encoded string.
36 	 * @param str      String to write
37 	 * @param numChars Number of `char16_t` characters to write. */
38 	void writeUTF16(const ST::string& str, size_t numChars);
39 
40 	/** Write UTF-32 encoded string.
41 	 * @param str      String to write
42 	 * @param numChars Number of `char32_t` characters to write. */
43 	void writeUTF32(const ST::string& str, size_t numChars);
44 
45 	void writeU8 (uint8_t  value);        /**< Write uint8_t */
46 	void writeU16(uint16_t value);        /**< Write uint16_t */
47 	void writeU32(uint32_t value);        /**< Write uint32_t */
48 
49 	/* Write a value. */
50 	template<typename T>
write(const T & value)51 	void write(const T& value)
52 	{
53 		static_assert(std::is_trivially_copyable<T>::value, "memcpy requires a trivially copyable type");
54 		size_t numBytes = sizeof(T);
55 		memcpy(m_buf, &value, numBytes);
56 		move(numBytes);
57 	}
58 
59 	/* Write an array of values. */
60 	template<typename T>
writeArray(const T * arr,size_t len)61 	void writeArray(const T* arr, size_t len)
62 	{
63 		static_assert(std::is_trivially_copyable<T>::value, "memcpy requires a trivially copyable type");
64 		size_t numBytes = len * sizeof(T);
65 		memcpy(m_buf, arr, numBytes);
66 		move(numBytes);
67 	}
68 
69 	/* Write zeroed bytes. */
70 	void skip(size_t numBytes);
71 
72 	/** Get number of the consumed bytes during writing. */
73 	size_t getConsumed() const;
74 
75 protected:
76 	uint8_t* m_buf;
77 	uint8_t* m_original;
78 
79 	/** Move pointer to \a numBytes bytes forward. */
80 	void move(size_t numBytes);
81 };
82 
83 
84 ////////////////////////////////////////////////////////////////////////////
85 // DataReader
86 ////////////////////////////////////////////////////////////////////////////
87 
88 
89 /** Class for reading serializing data.
90  * Assumes the endianess is correct. */
91 class DataReader
92 {
93 private:
94 	DataReader(const DataReader&) = delete; // no copy
95 	DataReader& operator=(const DataReader&) = delete; // no assign
96 public:
97 	/** Constructor.
98 	 * @param buf Pointer to the buffer for writing data. */
99 	explicit DataReader(const uint8_t* buf);
100 
101 	/** Read UTF-8 encoded string.
102 	 * @param numChars Number of `char` characters to read.
103 	 * @param validation What happens with invalid character sequences. */
104 	ST::string readUTF8(size_t numChars, ST::utf_validation_t validation = ST_DEFAULT_VALIDATION);
105 
106 	/** Read UTF-16 encoded string.
107 	 * @param numChars Number of `char16_t` characters to read.
108 	 * @param fixer Optional encoding corrector.  It is used for fixing incorrectly encoded text.
109 	 * @param validation What happens with invalid character sequences. */
110 	ST::string readUTF16(size_t numChars, const IEncodingCorrector* fixer = nullptr, ST::utf_validation_t validation = ST_DEFAULT_VALIDATION);
111 
112 	/** Read UTF-32 encoded string.
113 	 * @param numChars Number of `char32_t` characters to read.
114 	 * @param validation What happens with invalid character sequences. */
115 	ST::string readUTF32(size_t numChars, ST::utf_validation_t validation = ST_DEFAULT_VALIDATION);
116 
117 	uint8_t  readU8();            /**< Read uint8_t */
118 	uint16_t readU16();           /**< Read uint16_t */
119 	uint32_t readU32();           /**< Read uint32_t */
120 
121 	/* Read raw bytes. */
122 	void readBytes(uint8_t* bytes, size_t numBytes);
123 
124 	/* Read a value. */
125 	template<typename T>
read()126 	T read()
127 	{
128 		static_assert(std::is_trivially_copyable<T>::value, "memcpy requires a trivially copyable type");
129 		size_t numBytes = sizeof(T);
130 		T value;
131 		memcpy(&value, m_buf, numBytes);
132 		move(numBytes);
133 		return value;
134 	}
135 
136 	/* Read an array of values. */
137 	template<typename T>
readArray(T * arr,size_t len)138 	void readArray(T* arr, size_t len)
139 	{
140 		static_assert(std::is_trivially_copyable<T>::value, "memcpy requires a trivially copyable type");
141 		size_t numBytes = len * sizeof(T);
142 		memcpy(arr, m_buf, numBytes);
143 		move(numBytes);
144 	}
145 
146 	/* Read and discard bytes. */
147 	void skip(size_t numBytes);
148 
149 	/** Get number of the consumed bytes during reading. */
150 	size_t getConsumed() const;
151 
152 protected:
153 	const uint8_t* m_buf;
154 	const uint8_t* m_original;
155 
156 	/** Move pointer to \a numBytes bytes forward. */
157 	void move(size_t numBytes);
158 };
159 
160 
161 #define INJ_STR(D, S, Size)  (D).writeArray<char>((S), (Size));
162 #define INJ_BOOLA(D, S, Size)  (D).writeArray<BOOLEAN>((S), (Size));
163 #define INJ_I8A(D, S, Size)  (D).writeArray<INT8>((S), (Size));
164 #define INJ_U8A(D, S, Size)  (D).writeArray<UINT8>((S), (Size));
165 #define INJ_I16A(D, S, Size) (D).writeArray<INT16>((S), (Size));
166 #define INJ_U16A(D, S, Size) (D).writeArray<UINT16>((S), (Size));
167 #define INJ_I32A(D, S, Size) (D).writeArray<INT32>((S), (Size));
168 #define INJ_BOOL(D, S)   (D).write<BOOLEAN>((S));
169 #define INJ_BYTE(D, S)   (D).write<BYTE>((S));
170 #define INJ_I8(D, S)     (D).write<INT8>((S));
171 #define INJ_U8(D, S)     (D).write<UINT8>((S));
172 #define INJ_I16(D, S)    (D).write<INT16>((S));
173 #define INJ_U16(D, S)    (D).write<UINT16>((S));
174 #define INJ_I32(D, S)    (D).write<INT32>((S));
175 #define INJ_U32(D, S)    (D).write<UINT32>((S));
176 #define INJ_FLOAT(D, S)  (D).write<FLOAT>((S));
177 #define INJ_DOUBLE(D, S) (D).write<DOUBLE>((S));
178 #define INJ_PTR(D, S) INJ_SKIP(D, 4)
179 #define INJ_SKIP(D, Size) (D).skip((Size));
180 #define INJ_SKIP_I16(D)   (D).skip(2);
181 #define INJ_SKIP_I32(D)   (D).skip(4);
182 #define INJ_SKIP_U8(D)    (D).skip(1);
183 #define INJ_SOLDIER(D, S) (D).write<SoldierID>(Soldier2ID((S)));
184 #define INJ_VEC3(D, S) INJ_FLOAT(D, (S).x); INJ_FLOAT(D, (S).y); INJ_FLOAT(D, (S).z);
185 
186 #define EXTR_STR(S, D, Size)  (S).readArray<char>((D), (Size));
187 #define EXTR_BOOLA(S, D, Size) (S).readArray<BOOLEAN>((D), (Size));
188 #define EXTR_I8A(S, D, Size)  (S).readArray<INT8>((D), (Size));
189 #define EXTR_U8A(S, D, Size)  (S).readArray<UINT8>((D), (Size));
190 #define EXTR_I16A(S, D, Size) (S).readArray<INT16>((D), (Size));
191 #define EXTR_U16A(S, D, Size) (S).readArray<UINT16>((D), (Size));
192 #define EXTR_I32A(S, D, Size) (S).readArray<INT32>((D), (Size));
193 #define EXTR_BOOL(S, D)   (D) = (S).read<BOOLEAN>();
194 #define EXTR_BYTE(S, D)   (D) = (S).read<BYTE>();
195 #define EXTR_I8(S, D)     (D) = (S).read<INT8>();
196 #define EXTR_U8(S, D)     (D) = (S).read<UINT8>();
197 #define EXTR_I16(S, D)    (D) = (S).read<INT16>();
198 #define EXTR_U16(S, D)    (D) = (S).read<UINT16>();
199 #define EXTR_I32(S, D)    (D) = (S).read<INT32>();
200 #define EXTR_U32(S, D)    (D) = (S).read<UINT32>();
201 #define EXTR_FLOAT(S, D)  (D) = (S).read<FLOAT>();
202 #define EXTR_DOUBLE(S, D) (D) = (S).read<DOUBLE>();
203 #define EXTR_PTR(S, D) (D) = NULL; (S).skip(4);
204 #define EXTR_SKIP(S, Size) (S).skip((Size));
205 #define EXTR_SKIP_I16(S)   (S).skip(2);
206 #define EXTR_SKIP_I32(S)   (S).skip(4);
207 #define EXTR_SKIP_U8(S)    (S).skip(1);
208 #define EXTR_SOLDIER(S, D) (D) = ID2Soldier((S).read<SoldierID>());
209 #define EXTR_VEC3(S, D) EXTR_FLOAT(S, (D).x); EXTR_FLOAT(S, (D).y); EXTR_FLOAT(S, (D).z);
210 
211 #endif
212