AsmGrader 0.0.0
Loading...
Searching...
No Matches
byte_vector.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <boost/mp11/detail/mp_list.hpp>
6#include <boost/mp11/list.hpp>
7#include <gsl/assert>
8#include <gsl/util>
9#include <range/v3/algorithm/copy.hpp>
10#include <range/v3/algorithm/transform.hpp>
11#include <range/v3/iterator/concepts.hpp>
12#include <range/v3/range/access.hpp>
13#include <range/v3/range/concepts.hpp>
14#include <range/v3/range/primitives.hpp>
15#include <range/v3/range/traits.hpp>
16
17#include <array>
18#include <cstddef>
19#include <initializer_list>
20#include <memory>
21#include <span>
22#include <tuple>
23#include <type_traits>
24#include <utility>
25#include <vector>
26
27namespace asmgrader {
28
29static_assert(ranges::input_iterator<const std::byte*>);
30
32{
33public:
34 // A bunch of aliases for use with algorithm templates that check for them
35 using value_type = std::byte;
36 using allocator_type = std::allocator<std::byte>;
37 using size_type = std::size_t;
38 using difference_type = std::ptrdiff_t;
42 using const_pointer = const value_type*;
43 using iterator = std::vector<std::byte>::iterator;
44 using const_iterator = std::vector<std::byte>::const_iterator;
45 using reverse_iterator = std::vector<std::byte>::reverse_iterator;
46 using const_reverse_iterator = std::vector<std::byte>::const_reverse_iterator;
47
48 // Essentialy forwarding a lot of std::vector member functions
49 ByteVector() = default;
50
51 template <ranges::input_iterator It>
52 ByteVector(It first, It last)
53 : data_{first, last} {}
54
55 ByteVector(std::initializer_list<std::byte> init)
56 : data_{init} {}
57
58 template <typename ByteLike = std::byte>
59 requires requires(ByteLike value) { static_cast<std::byte>(value); }
60 explicit ByteVector(std::size_t count, ByteLike value = std::byte{0})
61 : data_{count, std::byte{value}} {}
62
63 std::byte& operator[](size_t idx) { return data_[idx]; }
64
65 const std::byte& operator[](size_t idx) const { return data_[idx]; }
66
67 template <ranges::input_iterator It>
68 auto insert(const_iterator pos, It first, It last) {
69 return data_.insert(pos, first, last);
70 }
71
72 template <typename ByteLike>
73 requires requires(ByteLike value) { static_cast<std::byte>(value); }
74 void push_back(ByteLike value) {
75 data_.push_back(value);
76 }
77
78 template <typename ByteLike>
79 requires requires(ByteLike value) { static_cast<std::byte>(value); }
80 void emplace_back(ByteLike value) {
81 data_.emplace_back(value);
82 }
83
84 auto begin() { return data_.begin(); }
85
86 auto begin() const { return data_.begin(); }
87
88 auto cbegin() const { return data_.cend(); }
89
90 auto end() { return data_.end(); }
91
92 auto end() const { return data_.end(); }
93
94 auto cend() const { return data_.cend(); }
95
96 auto data() { return data_.data(); }
97
98 auto data() const { return data_.data(); }
99
100 size_t size() const { return data_.size(); }
101
102 void resize(std::size_t new_size) { data_.resize(new_size); }
103
104 // Extra ctors to convert from byte-like types (e.g., uint8_t)
105 ByteVector(std::initializer_list<u8> init)
106 : data_{init.size()} {
107 init_range_to_bytes(init);
108 }
109
112 template <ranges::range Range>
113 requires requires(Range range, std::size_t size, std::byte byte) {
114 { range.resize(size) };
115 { std::to_integer<ranges::range_value_t<Range>>(byte) };
116 }
117 Range to_range() const {
118 Range result;
119 result.resize(this->size());
120
121 ranges::transform(*this, result.begin(),
122 [](std::byte value) { return std::to_integer<ranges::range_value_t<Range>>(value); });
123
124 return result;
125 }
126
127 template <typename... Types>
128 requires(std::is_trivially_copyable_v<Types> && ...)
129 auto bit_cast_to() const
130 -> std::conditional_t<sizeof...(Types) == 1, boost::mp11::mp_first<boost::mp11::mp_list<Types...>>,
131 std::tuple<Types...>> {
132 constexpr auto TOTAL_SIZE = (sizeof(Types) + ...);
133 Expects(TOTAL_SIZE <= size());
134
135 std::array<std::byte, TOTAL_SIZE> bytes;
136 ranges::copy(begin(), begin() + TOTAL_SIZE, bytes.begin());
137
138 return {std::bit_cast<Types>(bytes)...};
139 }
140
141 template <ranges::range Range>
142 static ByteVector from(const Range& range) {
143 auto raw_bytes = std::as_bytes(std::span{range});
144
145 static_assert(ranges::input_iterator<decltype(raw_bytes.begin())>);
146
147 return {raw_bytes.begin(), raw_bytes.end()};
148 }
149
150 template <typename... Ts>
151 static ByteVector from(const Ts&... args) {
152 ByteVector result((sizeof(Ts) + ...));
153
154 auto it = ranges::begin(result);
155
156 (ranges::copy(std::bit_cast<std::array<std::byte, sizeof(Ts)>>(args), std::exchange(it, it + sizeof(Ts))), ...);
157
158 return result;
159 }
160
161private:
162 template <ranges::range Range>
163 requires requires(ranges::range_value_t<Range> value) { static_cast<std::byte>(value); }
164 void init_range_to_bytes(const Range& range) {
165 Expects(size() == ranges::size(range));
166
167 ranges::transform(range, this->begin(), [](u8 value) { return std::byte{value}; });
168 }
169
170 std::vector<std::byte> data_;
171};
172
173} // namespace asmgrader
Definition byte_vector.hpp:32
std::size_t size_type
Definition byte_vector.hpp:37
auto begin() const
Definition byte_vector.hpp:86
const std::byte & operator[](size_t idx) const
Definition byte_vector.hpp:65
void resize(std::size_t new_size)
Definition byte_vector.hpp:102
std::byte value_type
Definition byte_vector.hpp:35
std::allocator< std::byte > allocator_type
Definition byte_vector.hpp:36
auto cbegin() const
Definition byte_vector.hpp:88
auto insert(const_iterator pos, It first, It last)
Definition byte_vector.hpp:68
std::byte & operator[](size_t idx)
Definition byte_vector.hpp:63
std::vector< std::byte >::const_reverse_iterator const_reverse_iterator
Definition byte_vector.hpp:46
auto end()
Definition byte_vector.hpp:90
ByteVector(std::initializer_list< u8 > init)
Definition byte_vector.hpp:105
std::ptrdiff_t difference_type
Definition byte_vector.hpp:38
void push_back(ByteLike value)
Definition byte_vector.hpp:74
ByteVector(std::initializer_list< std::byte > init)
Definition byte_vector.hpp:55
auto begin()
Definition byte_vector.hpp:84
void emplace_back(ByteLike value)
Definition byte_vector.hpp:80
auto data()
Definition byte_vector.hpp:96
std::vector< std::byte >::iterator iterator
Definition byte_vector.hpp:43
value_type & reference
Definition byte_vector.hpp:39
auto bit_cast_to() const -> std::conditional_t< sizeof...(Types)==1, boost::mp11::mp_first< boost::mp11::mp_list< Types... > >, std::tuple< Types... > >
Definition byte_vector.hpp:129
Range to_range() const
T should be a stdlib-compatible container type where std::byte is convertible to T::value_type.
Definition byte_vector.hpp:117
auto end() const
Definition byte_vector.hpp:92
size_t size() const
Definition byte_vector.hpp:100
const value_type * const_pointer
Definition byte_vector.hpp:42
static ByteVector from(const Ts &... args)
Definition byte_vector.hpp:151
ByteVector(It first, It last)
Definition byte_vector.hpp:52
ByteVector(std::size_t count, ByteLike value=std::byte{0})
Definition byte_vector.hpp:60
auto data() const
Definition byte_vector.hpp:98
const value_type & const_reference
Definition byte_vector.hpp:40
auto cend() const
Definition byte_vector.hpp:94
std::vector< std::byte >::reverse_iterator reverse_iterator
Definition byte_vector.hpp:45
static ByteVector from(const Range &range)
Definition byte_vector.hpp:142
value_type * pointer
Definition byte_vector.hpp:41
std::vector< std::byte >::const_iterator const_iterator
Definition byte_vector.hpp:44
Definition asm_buffer.hpp:19