forked from hideakitai/Packetizer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
type_packer.h
184 lines (154 loc) · 5.33 KB
/
type_packer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#ifndef TYPE_PACKER_H
#define TYPE_PACKER_H
#include <stdint.h>
#include <iostream> //Only used by printFlags, comment out if you like
#include <vector>
void ByteSwap(void * data, int size);
//Basic template for adding simple data types
template<typename T>
void push_back_type(std::vector<unsigned char>& vec, T& thing)
{
unsigned char *p = (unsigned char *)&thing;
for (int i = 0; i < sizeof(T); i++)
{
vec.push_back(p[i]);
}
}
//Override for arrays.
template<typename T>
void push_back_type(std::vector<unsigned char>& vec, T* thing, int size)
{
for (int pos = 0; pos < size; pos++)
{
unsigned char *p = (unsigned char *)&thing[pos];
for (int i = 0; i < sizeof(T); i++)
{
vec.push_back(p[i]);
}
}
}
//Override for std::vectors.
template<typename T>
void push_back_type(std::vector<unsigned char>& vec, std::vector<T>& thing)
{
for (auto discrete_thingamajig : thing)
{
push_back_type(vec, discrete_thingamajig);
}
}
//Override for passing in const values. Careful with type deduction!
template<typename T>
void push_back_type_const(std::vector<unsigned char>& vec, const T thing)
{
unsigned char *p = (unsigned char *)&thing;
for (int i = 0; i < sizeof(T); i++)
{
vec.push_back(p[i]);
}
}
//Variadic template recurses above functions so we can pass an endlessly long list of return containers
//template <typename T, typename... Rest>
//int unpack_type(const std::vector<unsigned char>& raw_buff, int pos, T &t, Rest&... rest) {
// return unpack_type(raw_buff, unpack_type(raw_buff, pos, t), rest...);
//}
//Variadic template Push back a list of junk
template <typename T, typename... Rest>
void push_back_type(std::vector<unsigned char>& raw_buff, T &t, Rest&... rest)
{
push_back_type(raw_buff, t);
push_back_type(raw_buff, rest...);
}
//This is for array returns (data types like float[], double[], int[] etc.)
template<typename T>
int unpack_type(const std::vector<unsigned char>& raw_buff, int pos, T *thing, int arr_size)
{
bool overflow = false;
for (int data_position = 0; data_position < arr_size; data_position++)
{
uint8_t temp[sizeof(T)];
for (unsigned int i = 0 + pos; i < sizeof(T) + pos; i++ )
{
if (i < raw_buff.size()) { temp[i-pos] = (uint8_t)(raw_buff[data_position*sizeof(T)+i]); }
else {overflow = true;}
}
if (!overflow) {
thing[data_position] = (*((T *) &temp[0]));
}
}
return pos+(arr_size * sizeof(T));
}
//This is for single-value returns (data types like float, double, int etc.), passed by ref
template<typename T>
int unpack_type(const std::vector<unsigned char>& raw_buff, int pos, T &thing)
{
bool overflow = false;
uint8_t temp[sizeof(T)];
for (unsigned int i = 0 + pos; i < sizeof(T) + pos; i++ )
{
if (i < raw_buff.size()) { temp[i-pos] = (uint8_t)(raw_buff[i]); }
else {overflow = true;}
}
if (!overflow) {
thing = (*((T *) &temp[0]));
}
return pos+(sizeof(T));
}
//This is for std::vector returns (std::vector<float>, std::vector<int> etc)
template<typename T>
int unpack_type(const std::vector<unsigned char>& raw_buff, int pos, std::vector<T>& new_container)
{
bool overflow = false;
for (int data_position = 0; data_position < new_container.size(); data_position++)
{
uint8_t temp[sizeof(T)];
for (unsigned int i = 0 + pos; i < sizeof(T) + pos; i++ )
{
if (i < raw_buff.size()) { temp[i-pos] = (uint8_t)(raw_buff[data_position*sizeof(T)+i]); }
else {overflow = true;}
}
if (!overflow) {
new_container.at(data_position) = (*((T *) &temp[0]));
}
}
return pos+(new_container.size() * sizeof(T));;
}
//Variadic template recurses above functions so we can pass an endlessly long list of return containers
template <typename T, typename... Rest>
int unpack_type(const std::vector<unsigned char>& raw_buff, int pos, T &t, Rest&... rest) {
return unpack_type(raw_buff, unpack_type(raw_buff, pos, t), rest...);
}
//Version that takes no initial pos, and assumes zero
template <typename T, typename... Rest>
int unpack_type(const std::vector<unsigned char>& raw_buff, T &t, Rest&... rest)
{
int pos = 0;
return unpack_type(raw_buff, unpack_type(raw_buff, pos, t), rest...);
}
void ByteSwap(void * data, int size)
{
char * ptr = (char *) data;
for (int i = 0; i < size/2; ++i)
std::swap(ptr[i], ptr[size-1-i]);
}
bool LittleEndian()
{
int test = 1;
return *((char *)&test) == 1;
}
//Set flag at position x to true/false
void setFlag(uint8_t& flag_char, uint8_t pos, bool bit_val) { flag_char ^= (-bit_val ^ flag_char) & (1UL << pos); }
//Flip flag at position
void toggleFlag(uint8_t& flag_char, uint8_t pos) { flag_char ^= 1UL << pos; }
//Get flag value at specified bit position
bool getFlagAt(uint8_t& flag_char, uint8_t pos) { return (flag_char >> pos) & 1U; }
//For debugging, cout a flags bits
void printFlags(uint8_t& flag_char)
{
//std::cout << std::endl;
for (int i = 0; i < 8; i++)
{
std::cout << "[" << i << "]:" << (bool)getFlagAt(flag_char, i) << " ";
}
std::cout << std::endl;
}
#endif