-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathbinary.hpp
More file actions
77 lines (68 loc) · 2.88 KB
/
binary.hpp
File metadata and controls
77 lines (68 loc) · 2.88 KB
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
#include "polyweb.hpp"
#include <concepts>
#include <cstddef>
#include <iterator>
#include <string.h>
#include <type_traits>
namespace pw {
namespace binary {
namespace detail {
template <typename T>
concept ByteAliasingType =
std::same_as<T, char> ||
std::same_as<T, signed char> ||
std::same_as<T, unsigned char> ||
std::same_as<T, std::byte>;
template <typename It>
concept ReadableByteIterator = std::input_iterator<It> && ByteAliasingType<std::iter_value_t<It>>;
template <typename It, typename T>
concept WritableToByte = ByteAliasingType<T> &&
requires(It it, T value) {
*it = value;
};
template <typename It>
concept ByteOutputIterator =
WritableToByte<It, char> ||
WritableToByte<It, signed char> ||
WritableToByte<It, unsigned char> ||
WritableToByte<It, std::byte>;
template <typename It>
concept ByteIterator = ReadableByteIterator<It> || ByteOutputIterator<It>;
template <typename It>
concept ContiguousByteIterator = ByteIterator<It> && std::contiguous_iterator<It>;
} // namespace detail
template <typename T, detail::ContiguousByteIterator InputIt>
requires std::is_trivially_copyable_v<T>
InputIt read(InputIt first, InputIt last, T& ret, int byte_order = BIG_ENDIAN) {
if (std::distance(first, last) >= (ptrdiff_t) sizeof(T)) {
if (byte_order == BYTE_ORDER) {
memcpy(&ret, &*first, sizeof(T));
} else {
reverse_memcpy(&ret, &*first, sizeof(T));
}
std::advance(first, sizeof(T));
}
return first;
}
template <typename T, detail::ContiguousByteIterator InputIt>
requires std::is_trivially_copyable_v<T>
bool try_read(InputIt& first, InputIt last, T& ret, int byte_order = BIG_ENDIAN) {
InputIt old_first = first;
first = read(first, last, ret, byte_order);
return first != old_first;
}
template <typename T, detail::ByteOutputIterator OutputIt>
requires std::is_trivially_copyable_v<T>
OutputIt write(OutputIt ret, const T& value, int byte_order = BIG_ENDIAN) {
auto bytes = (const char*) &value;
for (size_t i = 0; i < sizeof(T); ++i) {
if (byte_order == BYTE_ORDER) {
*ret++ = bytes[i];
} else {
*ret++ = bytes[sizeof(T) - 1 - i];
}
}
return ret;
}
} // namespace binary
} // namespace pw