11 #include "memory_arena.h"
24 #ifndef HERALD_MEMORYARENA_MAX
25 template <
typename MemoryArenaT = MemoryArena<8192, 8>>
27 #ifndef HERALD_MEMORYARENA_PAGE
28 template <
typename MemoryArenaT = MemoryArena<HERALD_MEMORYARENA_MAX, 8>>
30 template <
typename MemoryArenaT = MemoryArena<HERALD_MEMORYARENA_MAX, HERALD_MEMORYARENA_PAGE>>
44 std::swap(entry,other.entry);
47 DataRef(
const std::uint8_t* value, std::size_t length) :
48 entry(
arena.allocate(length)) {
49 for (std::size_t i = 0;i < length; ++i) {
51 arena.set(entry, i, (
unsigned char)value[i]);
55 DataRef(
const std::byte* value, std::size_t length) : entry(
arena.allocate(length)) {
56 for (std::size_t i = 0;i < length; ++i) {
58 arena.set(entry, i, (
unsigned char)value[i]);
63 for (std::size_t i = 0;i < from.size(); ++i) {
65 arena.set(entry, i, (
unsigned char)from[i]);
70 for (std::size_t i = 0;i < from.
size(); ++i) {
71 arena.set(entry, i, from.
arena.get(from.entry,i));
76 DataRef(std::byte repeating, std::size_t count) : entry(
arena.allocate(count)) {
77 for (std::size_t i = 0;i < count; ++i) {
78 arena.set(entry,i,(
unsigned char)repeating);
82 DataRef(std::size_t reserveLength) : entry(
arena.allocate(reserveLength)) {
91 entry =
arena.allocate(other.entry.byteLength);
92 for (std::size_t i = 0;i < other.
size(); ++i) {
93 arena.set(entry, i, other.
arena.get(other.entry,i));
108 const std::size_t length = hex.
size();
109 std::string hexInput;
111 if (1 == length % 2) {
118 DataRef d(hexInput.size() / 2);
120 for (std::size_t i = 0; i < hexInput.size(); i += 2) {
121 std::string byteString = hexInput.substr(i, 2);
122 std::byte
byte = std::byte(strtol(byteString.c_str(), NULL, 16));
124 arena.set(d.entry,i / 2, (
unsigned char)
byte);
139 if (offset >= entry.byteLength) {
142 DataRef copy(entry.byteLength - offset);
143 for (std::size_t i = 0;i < entry.byteLength - offset;++i) {
144 copy.
arena.set(copy.entry,i,
arena.get(entry,i + offset));
154 if (offset >= entry.byteLength) {
157 std::size_t correctedLength = length;
158 if (length > entry.byteLength || length + offset > entry.byteLength) {
159 correctedLength = entry.byteLength - offset;
169 for (std::size_t i = 0;i < correctedLength;++i) {
170 copy.
arena.set(copy.entry,i,
arena.get(entry,offset + i));
178 std::byte
at(std::size_t index)
const {
179 if (index > (
unsigned short)(entry.byteLength - 1)) {
182 return std::byte(
arena.get(entry,index));
192 if (other.
size() > entry.byteLength) {
195 for (std::size_t pos = 0; pos < other.
size();++pos) {
196 arena.set(entry,pos,other.
arena.get(other.entry,pos));
203 auto curSize = entry.byteLength;
204 arena.reserve(entry,curSize + length);
205 for (std::size_t pos = 0; pos < length;++pos) {
206 arena.set(entry,curSize + pos,rawData.
arena.get(rawData.entry,pos + offset));
217 auto curSize = entry.byteLength;
218 arena.reserve(entry,curSize + rawData.size());
219 for (std::size_t pos = 0; pos < rawData.size();++pos) {
220 arena.set(entry,curSize + pos,rawData[pos]);
225 void append(
const std::uint8_t* rawData, std::size_t offset, std::size_t length)
227 auto curSize = entry.byteLength;
228 arena.reserve(entry,curSize + length);
229 for (std::size_t i = 0;i < length;++i) {
230 arena.set(entry,curSize + i,(
unsigned char)(rawData[offset + i]));
238 if (offset > rawData.
size()) {
241 std::size_t checkedLength = length;
242 if (length > (rawData.
size() - offset)) {
243 checkedLength = rawData.
size() - offset;
245 auto curSize = entry.byteLength;
246 arena.reserve(entry,curSize + checkedLength);
247 for (std::size_t i = 0;i < checkedLength;++i) {
248 arena.set(entry,curSize + i,
249 rawData.
arena.get(rawData.entry,offset + (checkedLength - i - 1)));
260 auto orig = entry.byteLength;
261 arena.reserve(entry,rawData.
size() + orig);
262 for (std::size_t pos = 0; pos < rawData.
size();++pos) {
263 arena.set(entry,orig + pos,rawData.
arena.get(rawData.entry,pos));
271 std::size_t curSize = entry.byteLength;
272 arena.reserve(entry,curSize + 1);
274 arena.set(entry,curSize,(
unsigned char)rawData);
281 std::size_t curSize = entry.byteLength;
282 arena.reserve(entry,curSize + 1);
284 arena.set(entry,curSize,(
unsigned char)(rawData));
291 std::size_t curSize = entry.byteLength;
292 arena.reserve(entry,curSize + 2);
293 arena.set(entry,curSize,(
unsigned char)(rawData & 0xff));
294 arena.set(entry,curSize + 1,(
unsigned char)(rawData >> 8));
300 std::size_t curSize = entry.byteLength;
301 arena.reserve(entry,curSize + 4);
302 arena.set(entry,curSize,(
unsigned char)(rawData & 0xff));
303 arena.set(entry,curSize + 1,(
unsigned char)(rawData >> 8));
304 arena.set(entry,curSize + 2,(
unsigned char)(rawData >> 16));
305 arena.set(entry,curSize + 3,(
unsigned char)(rawData >> 24));
311 std::size_t curSize = entry.byteLength;
312 arena.reserve(entry,curSize + 8);
313 arena.set(entry,curSize,(
unsigned char)(rawData & 0xff));
314 arena.set(entry,curSize + 1,(
unsigned char)(rawData >> 8));
315 arena.set(entry,curSize + 2,(
unsigned char)(rawData >> 16));
316 arena.set(entry,curSize + 3,(
unsigned char)(rawData >> 24));
317 arena.set(entry,curSize + 4,(
unsigned char)(rawData >> 32));
318 arena.set(entry,curSize + 5,(
unsigned char)(rawData >> 40));
319 arena.set(entry,curSize + 6,(
unsigned char)(rawData >> 48));
320 arena.set(entry,curSize + 7,(
unsigned char)(rawData >> 56));
324 bool uint8(std::size_t fromIndex, uint8_t& into)
const noexcept
326 if (fromIndex > (
unsigned short)(entry.byteLength - 1)) {
329 into = std::uint8_t(
arena.get(entry,fromIndex));
334 bool uint16(std::size_t fromIndex, uint16_t& into)
const noexcept
336 if (fromIndex > (
unsigned short)(entry.byteLength - 2)) {
339 into = (std::uint16_t(std::uint8_t(
arena.get(entry,fromIndex + 1))) << 8) | std::uint16_t(std::uint8_t(
arena.get(entry,fromIndex)));
344 bool uint32(std::size_t fromIndex, uint32_t& into)
const noexcept
346 if (fromIndex > entry.byteLength - 4) {
349 into = std::uint32_t(std::uint8_t(
arena.get(entry,fromIndex))) | (std::uint32_t(std::uint8_t(
arena.get(entry,fromIndex + 1))) << 8) |
350 (std::uint32_t(std::uint8_t(
arena.get(entry,fromIndex + 2))) << 16) | (std::uint32_t(std::uint8_t(
arena.get(entry,fromIndex + 3))) << 24);
355 bool uint64(std::size_t fromIndex, uint64_t& into)
const noexcept
357 if (entry.byteLength < 8 || fromIndex > entry.byteLength - 8) {
360 into = (std::uint64_t(std::uint8_t(
arena.get(entry,fromIndex + 7))) << 56) | (std::uint64_t(std::uint8_t(
arena.get(entry,fromIndex + 6))) << 48) |
361 (std::uint64_t(std::uint8_t(
arena.get(entry,fromIndex + 5))) << 40) | (std::uint64_t(std::uint8_t(
arena.get(entry,fromIndex + 4))) << 32) |
362 (std::uint64_t(std::uint8_t(
arena.get(entry,fromIndex + 3))) << 24) | (std::uint64_t(std::uint8_t(
arena.get(entry,fromIndex + 2))) << 16) |
363 (std::uint64_t(std::uint8_t(
arena.get(entry,fromIndex + 1))) << 8) | std::uint64_t(std::uint8_t(
arena.get(entry,fromIndex)));
371 if (
size() != other.size()) {
380 return hashCode() == other.hashCode();
386 if (
size() != other.size()) {
389 return hashCode() != other.hashCode();
395 return hashCode() < other.hashCode();
401 return hashCode() > other.hashCode();
407 DataRef result(entry.byteLength);
409 for (std::size_t pos = 0;pos < entry.byteLength;++pos) {
410 result.
arena.set(result.entry,pos,
arena.get(entry,entry.byteLength - pos - 1));
421 DataRef result(entry.byteLength);
426 std::uint8_t value, original;
427 for (std::size_t i = 0;i < entry.byteLength;++i) {
428 original = std::uint8_t(
arena.get(entry,i));
430 for (
int b = 0;b < 8;++b) {
431 if ((original & (1 << b)) > 0) {
432 value |= 1 << (7 - b);
436 result.
arena.set(result.entry,entry.byteLength - i - 1,value);
445 if (0 == entry.byteLength) {
449 std::size_t
size = entry.byteLength;
450 result.reserve(
size * 2);
452 for (std::size_t i = 0; i <
size; ++i) {
454 v = std::size_t(
arena.get(entry,i));
455 result += hexChars[0x0F & (v >> 4)];
456 result += hexChars[0x0F & v ];
465 return std::hash<DataRef<MemoryArenaT>>{}(*this);
469 std::size_t
size() const noexcept{
470 return entry.byteLength;
477 arena.deallocate(entry);
480 static MemoryArenaT& getArena() {
485 static const char hexChars[];
494 template <
typename MemoryArenaT>
497 template <
typename MemoryArenaT>
499 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
500 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f'
512 template <std::
size_t maxSize = 8>
515 static constexpr std::size_t MaxSize = maxSize;
527 sections[sz] = toCopy;
538 if (index >= MaxSize) {
541 return sections[index];
550 static Data emptyRef;
551 std::array<Data,MaxSize> sections;
556 template <std::
size_t maxSize>
563 template <
typename MemoryArenaT>
569 inline void hash_combine_impl(std::size_t& seed, std::size_t value)
571 seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
574 template<
typename MemoryArenaT>
575 struct hash<
herald::datatype::DataRef<MemoryArenaT>>
582 for (std::size_t pos = 0;pos < v.
size();++pos) {
583 ok = v.
uint8(pos,ui);
584 hash_combine_impl(hv, std::hash<std::uint8_t>()(ui));
The main data workhorse class of the Herald API.
Definition: data.h:33
bool operator>(const DataRef &other) const noexcept
Greater than operator for another DataRef instance (same memory arena)
Definition: data.h:399
DataRef(const DataRef &from)
Initialises a DataRef copying another data object (uses more data, to ensure only one object owns the...
Definition: data.h:69
std::byte at(std::size_t index) const
Returns the individual byte at index position, or a byte value of zero if index is out of bounds.
Definition: data.h:178
DataRef(const std::string &from)
Initialises a DataRef from a string of chars.
Definition: data.h:62
~DataRef()
Default destructor.
Definition: data.h:99
bool uint16(std::size_t fromIndex, uint16_t &into) const noexcept
Returns whether reading a single uint16_t to into at fromIndex was successful.
Definition: data.h:334
void append(uint64_t rawData)
Appends a single uint64_t.
Definition: data.h:309
DataRef subdata(std::size_t offset) const
Returns a NEWLY allocated DataRef instance returning a subset of this instance.
Definition: data.h:137
std::string hexEncodedString() const noexcept
Returns a hex encoded string of this binary data.
Definition: data.h:443
void append(std::byte rawData)
Appends a single byte.
Definition: data.h:269
std::size_t hashCode() const noexcept
Returns the hash code of this instance.
Definition: data.h:462
DataRef(std::size_t reserveLength)
Initialises a DataRef with reserveLength bytes of undefined data.
Definition: data.h:82
void append(uint32_t rawData)
Appends a single uint32_t.
Definition: data.h:298
void append(const std::string &rawData)
Appends a set of characters to the end of this DataRef.
Definition: data.h:215
DataRef(std::byte repeating, std::size_t count)
Initialises a DataRef with count number of repeating bytes.
Definition: data.h:76
bool operator<(const DataRef &other) const noexcept
Less than operator for another DataRef instance (same memory arena)
Definition: data.h:393
DataRef(const std::uint8_t *value, std::size_t length)
Initialises a DataRef from a std::uint8_t array of length length
Definition: data.h:47
void appendReversed(const DataRef &rawData, std::size_t offset, std::size_t length)
Appends the specified DataRef to this one, but in its reverse order.
Definition: data.h:236
static DataRef fromHexEncodedString(const std::string &hex)
Creates a new DataRef object from a hexadecimal encoded string.
Definition: data.h:105
DataRef(DataRef &&other)
Takes control of another DataRef's memory allocation.
Definition: data.h:41
std::size_t size() const noexcept
Returns the size in allocated bytes of this instance.
Definition: data.h:469
void append(uint8_t rawData)
appends a single uint8_t
Definition: data.h:279
bool operator!=(const DataRef &other) const noexcept
Inequality operator for another DataRef instance (same memory arena)
Definition: data.h:384
DataRef()
Creates a DataRef with no memory used.
Definition: data.h:36
DataRef & operator=(const DataRef &other)
Copy assign operator. Copies the data to be sure only one object owns the entry.
Definition: data.h:89
DataRef reversed() const
Returns a new DataRef instance with the same data as this one, but in the reverse order.
Definition: data.h:405
bool uint8(std::size_t fromIndex, uint8_t &into) const noexcept
Returns whether reading a single uint8_t to into at fromIndex was successful.
Definition: data.h:324
void clear() noexcept
Clears (deallocates) the bytes referred to by this instance.
Definition: data.h:475
bool uint32(std::size_t fromIndex, uint32_t &into) const noexcept
Returns whether reading a single uint32_t to into at fromIndex was successful.
Definition: data.h:344
void assign(const DataRef &other)
Assigns the data in-place, reserving the size required if the current size is too small.
Definition: data.h:190
bool operator==(const DataRef &other) const noexcept
Equality operator for another DataRef instance (same memory arena)
Definition: data.h:369
DataRef(const std::byte *value, std::size_t length)
Initialises a DataRef from a std::byte array of length length
Definition: data.h:55
DataRef reverseEndianness() const
Returns the same order of bytes, but with the bits in each byte reversed.
Definition: data.h:419
bool uint64(std::size_t fromIndex, uint64_t &into) const noexcept
Returns whether reading a single uint64_t to into at fromIndex was successful.
Definition: data.h:355
void append(const DataRef &rawData, std::size_t offset, std::size_t length)
Copies another DataRef into this instance, expanding if required.
Definition: data.h:201
DataRef subdata(std::size_t offset, std::size_t length) const
Returns a NEWLY allocated DataRef instance returning a subset of this instance.
Definition: data.h:151
static MemoryArenaT arena
Instantiates the MemoryArena instance used by all DataRefs that share it.
Definition: data.h:486
std::string description() const
Returns the hex encoded string represetation as the description.
Definition: data.h:131
void append(uint16_t rawData)
Appends a single uint16_t.
Definition: data.h:289
void append(const DataRef &rawData)
Appends the specified DataRef to this one.
Definition: data.h:258
void append(const std::uint8_t *rawData, std::size_t offset, std::size_t length)
Copies a uint8_t array onto the end of this instance, expanding if necessary.
Definition: data.h:225
Represents a fixed array of Data references using the default memory arena that tracks its own in-use...
Definition: data.h:513
void append(const Data &toCopy) noexcept
Adds a new section, if room exists. Otherwise quietly performs a NO OP.
Definition: data.h:523
const Data & operator[](std::size_t index) noexcept
Returns the DataRef at the relevant index, or an empty DataRef.
Definition: data.h:545
~DataSections() noexcept=default
Default destructor.
std::size_t size() noexcept
Returns the number of dataref elements in use.
Definition: data.h:532
DataSections() noexcept
Default constructors. No memory allocation other than size (8 bytes)
Definition: data.h:518
const Data & get(std::size_t index) noexcept
Returns the DataRef at the relevant index, or an empty DataRef.
Definition: data.h:537
DataRef<> Data
Defaults references to Data to equal the DataRef with the default Memory Arena dimensions,...
Definition: data.h:506
Acts as a non-global memory arena for arbitrary classes.
Definition: aggregates.h:15
Represents an external 'pointer' to an allocated memory area.
Definition: memory_arena.h:20