Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/nall/serializer.hpp
2 views
1
#ifndef NALL_SERIALIZER_HPP
2
#define NALL_SERIALIZER_HPP
3
4
#include <type_traits>
5
#include <utility>
6
#include <nall/stdint.hpp>
7
#include <nall/utility.hpp>
8
9
namespace nall {
10
//serializer: a class designed to save and restore the state of classes.
11
//
12
//benefits:
13
//- data() will be portable in size (it is not necessary to specify type sizes.)
14
//- data() will be portable in endianness (always stored internally as little-endian.)
15
//- one serialize function can both save and restore class states.
16
//
17
//caveats:
18
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
19
//- floating-point usage is not portable across platforms
20
21
class serializer {
22
public:
23
enum mode_t { Load, Save, Size };
24
25
mode_t mode() const {
26
return imode;
27
}
28
29
const uint8_t* data() const {
30
return idata;
31
}
32
33
unsigned size() const {
34
return isize;
35
}
36
37
unsigned capacity() const {
38
return icapacity;
39
}
40
41
template<typename T> void floatingpoint(T &value) {
42
enum { size = sizeof(T) };
43
//this is rather dangerous, and not cross-platform safe;
44
//but there is no standardized way to export FP-values
45
uint8_t *p = (uint8_t*)&value;
46
if(imode == Save) {
47
for(unsigned n = 0; n < size; n++) idata[isize++] = p[n];
48
} else if(imode == Load) {
49
for(unsigned n = 0; n < size; n++) p[n] = idata[isize++];
50
} else {
51
isize += size;
52
}
53
}
54
55
template<typename T> void integer(T &value) {
56
enum { size = std::is_same<bool, T>::value ? 1 : sizeof(T) };
57
if(imode == Save) {
58
for(unsigned n = 0; n < size; n++) idata[isize++] = (uintmax_t)value >> (n << 3);
59
} else if(imode == Load) {
60
value = 0;
61
for(unsigned n = 0; n < size; n++) value |= (uintmax_t)idata[isize++] << (n << 3);
62
} else if(imode == Size) {
63
isize += size;
64
}
65
}
66
67
template<typename T> void integer(const T &value) {
68
enum { size = std::is_same<bool, T>::value ? 1 : sizeof(T) };
69
if(imode == Save) {
70
for(unsigned n = 0; n < size; n++) idata[isize++] = (uintmax_t)value >> (n << 3);
71
} else if(imode == Load) {
72
} else if(imode == Size) {
73
isize += size;
74
}
75
}
76
77
template<typename T> void array(T *array, int size) {
78
for(unsigned n = 0; n < size; n++) integer(array[n]);
79
}
80
81
template<typename T> void array(T &array) {
82
enum { size = sizeof(T) / sizeof(typename std::remove_extent<T>::type) };
83
for(unsigned n = 0; n < size; n++) integer(array[n]);
84
}
85
86
template<typename T> void array(const T &array) {
87
enum { size = sizeof(T) / sizeof(typename std::remove_extent<T>::type) };
88
for(unsigned n = 0; n < size; n++) integer(array[n]);
89
}
90
91
template<typename T> void array(T array, unsigned size) {
92
for(unsigned n = 0; n < size; n++) integer(array[n]);
93
}
94
95
//copy
96
serializer& operator=(const serializer &s) {
97
if(idata) delete[] idata;
98
99
imode = s.imode;
100
idata = new uint8_t[s.icapacity];
101
isize = s.isize;
102
icapacity = s.icapacity;
103
104
memcpy(idata, s.idata, s.icapacity);
105
return *this;
106
}
107
108
serializer(const serializer &s) : idata(0) {
109
operator=(s);
110
}
111
112
//move
113
serializer& operator=(serializer &&s) {
114
if(idata) delete[] idata;
115
116
imode = s.imode;
117
idata = s.idata;
118
isize = s.isize;
119
icapacity = s.icapacity;
120
121
s.idata = 0;
122
return *this;
123
}
124
125
serializer(serializer &&s)
126
: idata(nullptr) //zero 16-jun-2015 - was a bug not to have this. operator= chokes on uninitialized idata otherwise
127
{
128
operator=(std::move(s));
129
}
130
131
//construction
132
serializer() {
133
imode = Size;
134
idata = 0;
135
isize = 0;
136
icapacity = 0;
137
}
138
139
serializer(unsigned capacity) {
140
imode = Save;
141
idata = new uint8_t[capacity]();
142
isize = 0;
143
icapacity = capacity;
144
}
145
146
serializer(const uint8_t *data, unsigned capacity) {
147
imode = Load;
148
idata = new uint8_t[capacity];
149
isize = 0;
150
icapacity = capacity;
151
memcpy(idata, data, capacity);
152
}
153
154
~serializer() {
155
if(idata) delete[] idata;
156
}
157
158
private:
159
mode_t imode;
160
uint8_t *idata;
161
unsigned isize;
162
unsigned icapacity;
163
};
164
165
};
166
167
#endif
168
169