Chi-Tech
byte_array.h
Go to the documentation of this file.
1#ifndef CHITECH_BYTE_ARRAY_H
2#define CHITECH_BYTE_ARRAY_H
3
4#include <cstddef>
5#include <vector>
6#include <stdexcept>
7#include <string>
8
9namespace chi_data_types
10{
12{
13protected:
14 std::vector<std::byte> raw_data_;
15 size_t offset_ = 0;
16
17public:
18 ByteArray() = default;
19 explicit ByteArray(const size_t raw_data_size) : raw_data_(raw_data_size) {}
20 explicit ByteArray(std::vector<std::byte>&& raw_data)
21 : raw_data_(std::move(raw_data))
22 {
23 }
24 explicit ByteArray(const std::vector<std::byte>& raw_data)
25 : raw_data_(raw_data)
26 {
27 }
28
29 /**Uses the template type T to convert an associated value (of type T)
30 * to a sub-array of std::bytes and adds it to the internal byte-array.
31 *
32 * The template type T must support sizeof.*/
33 template <typename T>
34 void Write(const T& value)
35 {
36 const size_t num_bytes = sizeof(T);
37 const std::byte* value_byte_array =
38 reinterpret_cast<const std::byte*>(&value);
39
40 raw_data_.insert(
41 raw_data_.end(), value_byte_array, value_byte_array + num_bytes);
42 }
43
44 /**Uses the template type `T` to convert `sizeof(T)` number of bytes to
45 * a value of type `T`. The bytes are pulled from the internal byte-array
46 * starting at the internal address `m_offset` which can be viewed with a
47 * call to `Offset()`. This offset is incremented by the amount of bytes
48 * used and can be reset with a call to `Seek(0)`.
49 *
50 * Bounds-checking is performed by checking if the internal byte array
51 * has the required number of bytes available. If this check fails then
52 * this call will return an `out_of_range` exception.*/
53 template <typename T>
54 T Read()
55 {
56 const size_t num_bytes = sizeof(T);
57 if ((offset_ + num_bytes - 1) >= raw_data_.size())
58 throw std::out_of_range(
59 std::string("ByteArray reading error. ") +
60 " Typename: " + std::string(typeid(T).name()) + " m_offset: " +
61 std::to_string(offset_) + " size: " + std::to_string(raw_data_.size()) +
62 " num_bytes to read: " + std::to_string(num_bytes));
63
64 T value = *reinterpret_cast<T*>(&raw_data_[offset_]);
65 offset_ += num_bytes;
66
67 return value;
68 }
69
70 /**Uses the template type T to convert sizeof(T) number of bytes to
71 * a value of type T. The bytes are pulled from the internal byte-array
72 * starting at the internal address specified by the argument "address".
73 * An optional argument next_address can be used to return the location
74 * of the value after the value read.
75 * This offset is the given "address" argument incremented by the amount
76 * of bytes used.
77 *
78 * Bounds-checking is performed by checking if the internal byte array
79 * has the required number of bytes available. If this check fails then
80 * this call will return an `out_of_range` exception.*/
81 template <typename T>
82 T Read(const size_t address, size_t* next_address = nullptr) const
83 {
84 const size_t num_bytes = sizeof(T);
85 if ((address + num_bytes - 1) >= raw_data_.size())
86 throw std::logic_error(
87 std::string("ByteArray reading error. ") + " Typename: " +
88 std::string(typeid(T).name()) + " address: " + std::to_string(address) +
89 " size: " + std::to_string(raw_data_.size()) +
90 " num_bytes to read: " + std::to_string(num_bytes));
91
92 T value = *reinterpret_cast<const T*>(&raw_data_[address]);
93 if (next_address != nullptr) *next_address = address + num_bytes;
94
95 return value;
96 }
97
98 /**Appends a `ByteArray` to the current internal byte array.*/
99 void Append(const ByteArray& other_raw)
100 {
101 auto& master = raw_data_;
102
103 const auto& slave = other_raw.Data();
104 master.insert(master.end(), slave.begin(), slave.end());
105 }
106
107 /**Appends bytes from a `std::vector<std::byte>` to the internal
108 * byte array.*/
109 void Append(const std::vector<std::byte>& other_raw)
110 {
111 auto& master = raw_data_;
112
113 const auto& slave = other_raw;
114 master.insert(master.end(), slave.begin(), slave.end());
115 }
116
117 /**Clears the internal byte array and resets the address offset to zero.*/
118 void Clear()
119 {
120 raw_data_.clear();
121 offset_ = 0;
122 }
123
124 /**Moves the address marker to the supplied address.*/
125 void Seek(const size_t address = 0) { offset_ = address; }
126 /**Returns the internal address marker position.*/
127 size_t Offset() const { return offset_; }
128 /**Determines if the internal address marker is beyond the internal
129 * byte array.*/
130 bool EndOfBuffer() const { return offset_ >= raw_data_.size(); }
131 /**Returns the current size of the internal byte array.*/
132 size_t Size() const { return raw_data_.size(); }
133
134 /**Returns a reference to the internal byte array.*/
135 std::vector<std::byte>& Data() { return raw_data_; }
136 /**Returns a const reference of the internal byte array.*/
137 const std::vector<std::byte>& Data() const { return raw_data_; }
138};
139} // namespace chi_data_types
140
141#endif // CHITECH_BYTE_ARRAY_H
ByteArray(std::vector< std::byte > &&raw_data)
Definition: byte_array.h:20
ByteArray(const std::vector< std::byte > &raw_data)
Definition: byte_array.h:24
void Seek(const size_t address=0)
Definition: byte_array.h:125
std::vector< std::byte > & Data()
Definition: byte_array.h:135
void Append(const std::vector< std::byte > &other_raw)
Definition: byte_array.h:109
bool EndOfBuffer() const
Definition: byte_array.h:130
size_t Offset() const
Definition: byte_array.h:127
std::vector< std::byte > raw_data_
Definition: byte_array.h:14
T Read(const size_t address, size_t *next_address=nullptr) const
Definition: byte_array.h:82
const std::vector< std::byte > & Data() const
Definition: byte_array.h:137
void Append(const ByteArray &other_raw)
Definition: byte_array.h:99
void Write(const T &value)
Definition: byte_array.h:34
ByteArray(const size_t raw_data_size)
Definition: byte_array.h:19