ScummVM API documentation
data-io.h
1/* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#ifndef COMMON_DATA_IO_H
23#define COMMON_DATA_IO_H
24
25#include "common/scummsys.h"
26
27namespace Common {
28
29enum class EndianStorageFormat {
30 Big,
31 Little,
32};
33
34// Traits for a storage format. You can specialize this to make more storage formats
35// that have their own behavior.
36template<class TDataFormat>
38};
39
40template<>
41struct DataFormatTraits<EndianStorageFormat> {
42 static inline bool isLittleEndian(EndianStorageFormat storageFormat) {
43 return storageFormat == EndianStorageFormat::Little;
44 }
45};
46
47template<class TDataFormat, class T>
49 static const uint kMaxSize = sizeof(T);
50
51 static uint computeSize(TDataFormat dataFormat);
52
53 static void encode(TDataFormat dataFormat, byte *data, const T &value);
54 static void decode(TDataFormat dataFormat, const byte *data, T &value);
55};
56
57template<class TDataFormat, class T>
58uint SimpleDataIO<TDataFormat, T>::computeSize(TDataFormat dataFormat) {
59 return sizeof(T);
60}
61
62template<class TDataFormat, class T>
63void SimpleDataIO<TDataFormat, T>::encode(TDataFormat dataFormat, byte *data, const T &value) {
64 const byte *valueBytes = reinterpret_cast<const byte *>(&value);
65 byte *dataBytes = reinterpret_cast<byte *>(data);
66
67 const bool isTargetLE = DataFormatTraits<TDataFormat>::isLittleEndian(dataFormat);
68#ifdef SCUMM_LITTLE_ENDIAN
69 const bool isSystemLE = true;
70#endif
71#ifdef SCUMM_BIG_ENDIAN
72 const bool isSystemLE = false;
73#endif
74
75 const bool requiresSwap = (isSystemLE != isTargetLE);
76
77 byte temp[sizeof(T)];
78
79 if (requiresSwap) {
80 for (uint i = 0; i < sizeof(T); i++)
81 temp[i] = valueBytes[sizeof(T) - 1 - i];
82 } else {
83 for (uint i = 0; i < sizeof(T); i++)
84 temp[i] = valueBytes[i];
85 }
86
87 for (uint i = 0; i < sizeof(T); i++)
88 dataBytes[i] = temp[i];
89}
90
91template<class TDataFormat, class T>
92void SimpleDataIO<TDataFormat, T>::decode(TDataFormat dataFormat, const byte *data, T &value) {
93 byte *valueBytes = reinterpret_cast<byte *>(&value);
94 const byte *dataBytes = reinterpret_cast<const byte *>(data);
95
96 const bool isTargetLE = DataFormatTraits<TDataFormat>::isLittleEndian(dataFormat);
97#ifdef SCUMM_LITTLE_ENDIAN
98 const bool isSystemLE = true;
99#endif
100#ifdef SCUMM_BIG_ENDIAN
101 const bool isSystemLE = false;
102#endif
103
104 const bool requiresSwap = (isSystemLE != isTargetLE);
105
106 byte temp[sizeof(T)];
107
108 if (requiresSwap) {
109 for (uint i = 0; i < sizeof(T); i++)
110 temp[i] = dataBytes[sizeof(T) - 1 - i];
111 } else {
112 for (uint i = 0; i < sizeof(T); i++)
113 temp[i] = dataBytes[i];
114 }
115
116 for (uint i = 0; i < sizeof(T); i++)
117 valueBytes[i] = temp[i];
118}
119
120template<class TDataFormat, class T>
121struct DataIO {
122};
123
124template<class TDataFormat>
125struct DataIO<TDataFormat, uint8> : public SimpleDataIO<TDataFormat, uint8> {
126};
127
128template<class TDataFormat>
129struct DataIO<TDataFormat, uint16> : public SimpleDataIO<TDataFormat, uint16> {
130};
131template<class TDataFormat>
132struct DataIO<TDataFormat, uint32> : public SimpleDataIO<TDataFormat, uint32> {
133};
134template<class TDataFormat>
135struct DataIO<TDataFormat, uint64> : public SimpleDataIO<TDataFormat, uint64> {
136};
137
138template<class TDataFormat>
139struct DataIO<TDataFormat, int8> : public SimpleDataIO<TDataFormat, int8> {
140};
141
142template<class TDataFormat>
143struct DataIO<TDataFormat, int16> : public SimpleDataIO<TDataFormat, int16> {
144};
145
146template<class TDataFormat>
147struct DataIO<TDataFormat, int32> : public SimpleDataIO<TDataFormat, int32> {
148};
149
150template<class TDataFormat>
151struct DataIO<TDataFormat, int64> : public SimpleDataIO<TDataFormat, int64> {
152};
153
154template<class TDataFormat>
155struct DataIO<TDataFormat, char> : public SimpleDataIO<TDataFormat, char> {
156};
157
158template<class TDataFormat>
159struct DataIO<TDataFormat, float> : public SimpleDataIO<TDataFormat, float> {
160};
161
162template<class TDataFormat>
163struct DataIO<TDataFormat, double> : public SimpleDataIO<TDataFormat, double> {
164};
165
166template<class TDataFormat, class T, class... TMore>
167struct DataMultipleIO;
168
169template<class TDataFormat, class T>
170struct DataMultipleIO<TDataFormat, T> {
171 static const uint kMaxSize = DataIO<TDataFormat, T>::kMaxSize;
172
173 static uint computeSize(TDataFormat dataFormat);
174
175 static void encode(TDataFormat dataFormat, byte *data, const T &value);
176 static void decode(TDataFormat dataFormat, const byte *data, T &value);
177};
178
179template<class TDataFormat, class T>
180uint DataMultipleIO<TDataFormat, T>::computeSize(TDataFormat dataFormat) {
181 return DataIO<TDataFormat, T>::computeSize(dataFormat);
182}
183
184template<class TDataFormat, class T>
185void DataMultipleIO<TDataFormat, T>::encode(TDataFormat dataFormat, byte *data, const T &value) {
186 return DataIO<TDataFormat, T>::encode(dataFormat, data, value);
187}
188
189template<class TDataFormat, class T>
190void DataMultipleIO<TDataFormat, T>::decode(TDataFormat dataFormat, const byte *data, T &value) {
191 return DataIO<TDataFormat, T>::decode(dataFormat, data, value);
192}
193
194template<class TDataFormat, class T, uint TSize>
195struct DataMultipleIO<TDataFormat, T[TSize]> {
196 static const uint kMaxSize = DataIO<TDataFormat, T>::kMaxSize * TSize;
197
198 static uint computeSize(TDataFormat dataFormat);
199
200 static void encode(TDataFormat dataFormat, byte *data, const T (&value)[TSize]);
201 static void decode(TDataFormat dataFormat, const byte *data, T (&value)[TSize]);
202};
203
204template<class TDataFormat, class T, uint TSize>
205uint DataMultipleIO<TDataFormat, T[TSize]>::computeSize(TDataFormat dataFormat) {
206 return DataMultipleIO<TDataFormat, T>::computeSize(dataFormat) * TSize;
207}
208
209template<class TDataFormat, class T, uint TSize>
210void DataMultipleIO<TDataFormat, T[TSize]>::encode(TDataFormat dataFormat, byte *data, const T (&value)[TSize]) {
211 const uint elementSize = DataIO<TDataFormat, T>::computeSize(dataFormat);
212 for (uint i = 0; i < TSize; i++)
213 DataMultipleIO<TDataFormat, T>::encode(dataFormat, data + elementSize * i, value[i]);
214}
215
216template<class TDataFormat, class T, uint TSize>
217void DataMultipleIO<TDataFormat, T[TSize]>::decode(TDataFormat dataFormat, const byte *data, T (&value)[TSize]) {
218 const uint elementSize = DataIO<TDataFormat, T>::computeSize(dataFormat);
219 for (uint i = 0; i < TSize; i++)
220 DataMultipleIO<TDataFormat, T>::decode(dataFormat, data + elementSize * i, value[i]);
221}
222
223template<class TDataFormat, class T, class... TMore>
225 static const uint kMaxSize = DataIO<TDataFormat, T>::kMaxSize + DataMultipleIO<TDataFormat, TMore...>::kMaxSize;
226
227 static uint computeSize(TDataFormat dataFormat);
228
229 static void encode(TDataFormat dataFormat, byte *data, const T &firstValue, const TMore &...moreValues);
230 static void decode(TDataFormat dataFormat, const byte *data, T &firstValue, TMore &...moreValues);
231};
232
233template<class TDataFormat, class T, class... TMore>
236}
237
238template<class TDataFormat, class T, class... TMore>
239void DataMultipleIO<TDataFormat, T, TMore...>::encode(TDataFormat dataFormat, byte *data, const T &firstValue, const TMore &...moreValues) {
240 DataMultipleIO<TDataFormat, T>::encode(dataFormat, data, firstValue);
241 DataMultipleIO<TDataFormat, TMore...>::encode(dataFormat, data + DataMultipleIO<TDataFormat, T>::computeSize(dataFormat), moreValues...);
242}
243
244template<class TDataFormat, class T, class... TMore>
245void DataMultipleIO<TDataFormat, T, TMore...>::decode(TDataFormat dataFormat, const byte *data, T &firstValue, TMore &...moreValues) {
246 DataMultipleIO<TDataFormat, T>::decode(dataFormat, data, firstValue);
247 DataMultipleIO<TDataFormat, TMore...>::decode(dataFormat, data + DataMultipleIO<TDataFormat, T>::computeSize(dataFormat), moreValues...);
248}
249
250} // End of namespace Common
251
252#endif
Definition: algorithm.h:29
Definition: data-io.h:37
Definition: data-io.h:121
Definition: data-io.h:224
Definition: data-io.h:48