AsmGrader 0.0.0
Loading...
Searching...
No Matches
byte_vector.hpp
Go to the documentation of this file.
1#pragma once
2
6
7#include <boost/mp11/detail/mp_list.hpp>
8#include <boost/mp11/list.hpp>
9#include <gsl/assert>
10#include <gsl/util>
11#include <libassert/assert.hpp>
12#include <range/v3/algorithm/copy.hpp>
13#include <range/v3/algorithm/copy_n.hpp>
14#include <range/v3/algorithm/transform.hpp>
15#include <range/v3/iterator/concepts.hpp>
16#include <range/v3/range/access.hpp>
17#include <range/v3/range/concepts.hpp>
18#include <range/v3/range/primitives.hpp>
19#include <range/v3/range/traits.hpp>
20
21#include <array>
22#include <cstddef>
23#include <initializer_list>
24#include <memory>
25#include <tuple>
26#include <type_traits>
27#include <utility>
28#include <vector>
29
30namespace asmgrader {
31
32template <EndiannessKind Endianness>
34{
35public:
36 // A bunch of aliases for use with algorithm templates that check for them
38 using allocator_type = std::allocator<Byte>;
39 using size_type = std::size_t;
40 using difference_type = std::ptrdiff_t;
44 using const_pointer = const value_type*;
45 using iterator = std::vector<Byte>::iterator;
46 using const_iterator = std::vector<Byte>::const_iterator;
47 using reverse_iterator = std::vector<Byte>::reverse_iterator;
48 using const_reverse_iterator = std::vector<Byte>::const_reverse_iterator;
49
50 // Essentialy forwarding a lot of std::vector member functions
51 ByteVector() = default;
52
53 template <ranges::input_iterator It>
54 ByteVector(It first, It last)
55 : data_{first, last} {}
56
57 ByteVector(std::initializer_list<Byte> init)
58 : data_{init} {}
59
60 explicit ByteVector(std::size_t count, Byte value = Byte{})
61 : data_(count, Byte{value}) {}
62
63 bool empty() const { return data_.empty(); }
64
65 Byte& operator[](size_t idx) { return data_[idx]; }
66
67 const Byte& operator[](size_t idx) const { return data_[idx]; }
68
69 Byte& at(size_t idx) { return data_.at(idx); }
70
71 const Byte& at(size_t idx) const { return data_.at(idx); }
72
73 template <ranges::input_iterator It>
74 auto insert(const_iterator pos, It first, It last) {
75 return data_.insert(pos, first, last);
76 }
77
78 // yes, taking a Byte by reference is a bit strange, but it's done to
79 // match std container conventions, and is going to be optimized away anyways.
80 void push_back(const Byte& value) { data_.push_back(value); }
81
82 template <typename... Args>
83 void emplace_back(Args&&... args) {
84 data_.emplace_back(std::forward<Args>(args)...);
85 }
86
87 auto begin() { return data_.begin(); }
88
89 auto begin() const { return data_.begin(); }
90
91 auto cbegin() const { return data_.cend(); }
92
93 auto end() { return data_.end(); }
94
95 auto end() const { return data_.end(); }
96
97 auto cend() const { return data_.cend(); }
98
99 auto data() { return data_.data(); }
100
101 auto data() const { return data_.data(); }
102
103 size_t size() const { return data_.size(); }
104
105 void resize(std::size_t new_size) { data_.resize(new_size); }
106
109 template <ranges::range Range>
110 requires requires(Range range, std::size_t size, Byte byte) {
111 { range.resize(size) };
112 { static_cast<ranges::range_value_t<Range>>(byte.value) };
113 }
114 Range to_range() const {
115 Range result;
116 result.resize(this->size());
117
118 ranges::transform(*this, result.begin(),
119 [](Byte byte) { return static_cast<ranges::range_value_t<Range>>(byte.value); });
120
121 return result;
122 }
123
124 template <typename... Types>
125 requires(sizeof...(Types) > 0 && (std::is_trivially_copyable_v<Types> && ...))
126 auto bit_cast_to() const
127 -> std::conditional_t<sizeof...(Types) == 1, boost::mp11::mp_first<boost::mp11::mp_list<Types...>>,
128 std::tuple<Types...>> {
129 constexpr auto TOTAL_SIZE = (sizeof(Types) + ...);
130 ASSERT(TOTAL_SIZE <= size());
131
132 std::tuple<std::array<Byte, sizeof(Types)>...> bytes;
133
134 std::apply(
135 [&bytes, iter = begin()](auto&&... elems) mutable {
136 ((ranges::copy_n(std::exchange(iter, iter + sizeof(Types)), sizeof(Types), elems.begin())), ...);
137 },
138 bytes);
139
140 if constexpr (sizeof...(Types) == 1) {
141 return {std::bit_cast<Types>(std::get<0>(bytes))...};
142 } else {
143 return std::apply([](auto&&... args) { return std::tuple{(std::bit_cast<Types>(args))...}; }, bytes);
144 }
145 }
146
147private:
148 template <ranges::range Range>
149 requires requires(ranges::range_value_t<Range> value) { static_cast<Byte>(value); }
150 void init_range_to_bytes(const Range& range) {
151 Expects(size() == ranges::size(range));
152
153 ranges::transform(range, this->begin(), [](u8 value) { return Byte{value}; });
154 }
155
156 std::vector<Byte> data_;
157 // TODO:
158 // Endianness endianness_ = Endianness::Native;
159};
160
162
163static_assert(ranges::range<NativeByteVector>);
164
165} // namespace asmgrader
Definition byte_vector.hpp:34
const Byte & operator[](size_t idx) const
Definition byte_vector.hpp:67
std::allocator< Byte > allocator_type
Definition byte_vector.hpp:38
const Byte & at(size_t idx) const
Definition byte_vector.hpp:71
auto cbegin() const
Definition byte_vector.hpp:91
ByteVector(std::size_t count, Byte value=Byte{})
Definition byte_vector.hpp:60
void push_back(const Byte &value)
Definition byte_vector.hpp:80
ByteVector(It first, It last)
Definition byte_vector.hpp:54
std::vector< Byte >::iterator iterator
Definition byte_vector.hpp:45
size_t size() const
Definition byte_vector.hpp:103
auto end()
Definition byte_vector.hpp:93
std::size_t size_type
Definition byte_vector.hpp:39
Byte & at(size_t idx)
Definition byte_vector.hpp:69
void emplace_back(Args &&... args)
Definition byte_vector.hpp:83
void resize(std::size_t new_size)
Definition byte_vector.hpp:105
auto cend() const
Definition byte_vector.hpp:97
std::vector< Byte >::const_reverse_iterator const_reverse_iterator
Definition byte_vector.hpp:48
auto begin() const
Definition byte_vector.hpp:89
Byte & operator[](size_t idx)
Definition byte_vector.hpp:65
auto data() const
Definition byte_vector.hpp:101
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:126
std::vector< Byte >::reverse_iterator reverse_iterator
Definition byte_vector.hpp:47
std::ptrdiff_t difference_type
Definition byte_vector.hpp:40
auto begin()
Definition byte_vector.hpp:87
ByteVector(std::initializer_list< Byte > init)
Definition byte_vector.hpp:57
bool empty() const
Definition byte_vector.hpp:63
auto end() const
Definition byte_vector.hpp:95
auto insert(const_iterator pos, It first, It last)
Definition byte_vector.hpp:74
Range to_range() const
T should be a stdlib-compatible container type where Byte is convertible to T::value_type.
Definition byte_vector.hpp:114
std::vector< Byte >::const_iterator const_iterator
Definition byte_vector.hpp:46
auto data()
Definition byte_vector.hpp:99
More user-friendly interface wrapper for a byte-like integral.
Definition byte.hpp:18
Definition asm_buffer.hpp:20
Definition byte_array.hpp:94