3
3
#include < alpaca/detail/options.h>
4
4
#include < alpaca/detail/variable_length_encoding.h>
5
5
#include < cstdint>
6
+ #include < cstring>
6
7
#include < fstream>
7
8
#include < iostream>
8
9
#include < system_error>
@@ -12,6 +13,21 @@ namespace alpaca {
12
13
13
14
namespace detail {
14
15
16
+ template <options O, typename T>
17
+ void get_aligned (T& value, const uint8_t * bytes, size_t current_index)
18
+ {
19
+ if (force_aligned_access<O>() &&
20
+ reinterpret_cast <uintptr_t >(bytes + current_index) % alignof (T) != 0 )
21
+ {
22
+ // non-aligned access --> byte-byte copy
23
+ std::memcpy (&value, bytes + current_index, sizeof (T));
24
+ } else {
25
+ // aligned access, directly assign the value
26
+ value = *(reinterpret_cast <const T *>(bytes + current_index));
27
+ }
28
+ }
29
+
30
+
15
31
template <options O, typename Container>
16
32
typename std::enable_if<!std::is_array_v<Container>, bool >::type
17
33
from_bytes_crc32 (uint32_t &value, Container &bytes, std::size_t ¤t_index,
@@ -21,7 +37,9 @@ from_bytes_crc32(uint32_t &value, Container &bytes, std::size_t ¤t_index,
21
37
if (end_index < num_bytes_to_read) {
22
38
return false ;
23
39
}
24
- value = *(reinterpret_cast <const uint32_t *>(bytes.data () + current_index));
40
+
41
+ get_aligned<O>(value, &bytes[0 ], current_index);
42
+
25
43
update_value_based_on_alpaca_endian_rules<O, uint32_t >(value);
26
44
current_index += num_bytes_to_read;
27
45
return true ;
@@ -36,7 +54,9 @@ from_bytes_crc32(uint32_t &value, Container &bytes, std::size_t ¤t_index,
36
54
if (end_index < num_bytes_to_read) {
37
55
return false ;
38
56
}
39
- value = *(reinterpret_cast <const uint32_t *>(bytes + current_index));
57
+
58
+ get_aligned<O>(value, &bytes[0 ], current_index);
59
+
40
60
update_value_based_on_alpaca_endian_rules<O, uint32_t >(value);
41
61
current_index += num_bytes_to_read;
42
62
return true ;
@@ -87,7 +107,8 @@ from_bytes(T &value, Container &bytes, std::size_t ¤t_index,
87
107
// / TODO: report error
88
108
return false ;
89
109
}
90
- value = *(reinterpret_cast <const T *>(bytes.data () + current_index));
110
+
111
+ get_aligned<O>(value, &bytes[0 ], current_index);
91
112
current_index += num_bytes_to_read;
92
113
update_value_based_on_alpaca_endian_rules<O, T>(value);
93
114
return true ;
@@ -139,7 +160,8 @@ from_bytes(T &value, Container &bytes, std::size_t ¤t_index,
139
160
// / TODO: report error
140
161
return false ;
141
162
}
142
- value = *(reinterpret_cast <const T *>(bytes + current_index));
163
+
164
+ get_aligned<O>(value, &bytes[0 ], current_index);
143
165
current_index += num_bytes_to_read;
144
166
update_value_based_on_alpaca_endian_rules<O, T>(value);
145
167
return true ;
@@ -194,7 +216,8 @@ from_bytes(T &value, Container &bytes, std::size_t ¤t_index,
194
216
char value_bytes[num_bytes_to_read];
195
217
bytes.read (&value_bytes[0 ], num_bytes_to_read);
196
218
current_index += num_bytes_to_read;
197
- value = *(reinterpret_cast <const T *>(value_bytes));
219
+ get_aligned<O>(value, (uint8_t *) &value_bytes[0 ], 0 );
220
+
198
221
update_value_based_on_alpaca_endian_rules<O, T>(value);
199
222
return true ;
200
223
}
@@ -237,7 +260,7 @@ from_bytes(T &value, Container &bytes, std::size_t ¤t_index,
237
260
// / TODO: report error
238
261
return false ;
239
262
}
240
- value = *( reinterpret_cast < const T *>( bytes. data () + current_index) );
263
+ get_aligned<O>(value, & bytes[ 0 ], current_index);
241
264
current_index += num_bytes_to_read;
242
265
} else {
243
266
value = decode_varint<T>(bytes, current_index);
@@ -286,7 +309,7 @@ from_bytes(T &value, Container &bytes, std::size_t ¤t_index,
286
309
// / TODO: report error
287
310
return false ;
288
311
}
289
- value = *( reinterpret_cast < const T *>( bytes + current_index) );
312
+ get_aligned<O>(value, & bytes[ 0 ], current_index);
290
313
current_index += num_bytes_to_read;
291
314
} else {
292
315
value = decode_varint<T>(bytes, current_index);
@@ -338,7 +361,7 @@ from_bytes(T &value, Container &bytes, std::size_t ¤t_index,
338
361
char value_bytes[num_bytes_to_read];
339
362
bytes.read (&value_bytes[0 ], num_bytes_to_read);
340
363
current_index += num_bytes_to_read;
341
- value = *( reinterpret_cast < const T *>(value_bytes) );
364
+ get_aligned<O>( value, ( uint8_t *) &value_bytes[ 0 ], 0 );
342
365
} else {
343
366
value = decode_varint<T>(bytes, current_index);
344
367
}
0 commit comments