Skip to content

Instantly share code, notes, and snippets.

@Sam-Belliveau
Last active August 12, 2019 23:26
Show Gist options
  • Select an option

  • Save Sam-Belliveau/d3fc2626b6a6749d42ef3df005b21121 to your computer and use it in GitHub Desktop.

Select an option

Save Sam-Belliveau/d3fc2626b6a6749d42ef3df005b21121 to your computer and use it in GitHub Desktop.
Constexpr library for manipulating the rawbytes of a type while avoiding UB
#ifndef SAM_BELLIVEAU_RAW_BYTE_CONTAINTER
#define SAM_BELLIVEAU_RAW_BYTE_CONTAINTER 1
#include <cstdint> // Size Types
#include <cstring> // std::memcpy
#include <exception> // std::overflow
#include <initializer_list> // std::initializer_list
#include <iterator> // Iterator stuff
template<class InputType>
class RawBytes
{
private:
static constexpr std::size_t type_size = sizeof(InputType);
public:
using input_type = InputType;
using byte_type = std::uint8_t;
using value_type = byte_type;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using iterator = value_type*;
using const_iterator = const value_type*;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reference = value_type&;
using const_reference = value_type;
private: // Variables
byte_type data_[type_size];
// Set Data Array
constexpr inline void set_data(const InputType& input) noexcept
{ std::memcpy(&data_, &input, type_size); }
public: // Constructors
constexpr RawBytes() : data_{} {}
constexpr RawBytes(const RawBytes& other) = default;
constexpr RawBytes& operator=(const RawBytes& other) = default;
constexpr inline RawBytes(const InputType& input) noexcept
{ std::memcpy(&data_, &input, type_size); }
constexpr inline RawBytes& operator=(const InputType& input) noexcept
{ std::memcpy(&data_, &input, type_size); }
template<class T>
constexpr inline RawBytes(const std::initializer_list<T>& input) noexcept
{
data_ = {};
for(size_type i = 0; i < type_size && i < input.size(); ++i)
data_[i] = static_cast<byte_type>(input[i]);
}
template<class T>
constexpr inline RawBytes& operator=(const std::initializer_list<T>& input) noexcept
{
data_ = {};
for(size_type i = 0; i < type_size && i < input.size(); ++i)
data_[i] = static_cast<byte_type>(input[i]);
}
public: // Operators
constexpr inline size_type size() const noexcept { return type_size; }
constexpr inline reference operator[](size_type i) noexcept { return data_[i]; }
constexpr inline const_reference operator[](size_type i) const noexcept { return data_[i]; }
constexpr inline reference at(size_type i)
{
if(i < type_size) return data_[i];
else throw std::overflow_error("RawBytes.at(i) -> Overflow");
}
constexpr inline const_reference at(size_type i) const
{
if(i < type_size) return data_[i];
else throw std::overflow_error("RawBytes.at(i) -> Overflow");
}
constexpr inline InputType get() const noexcept
{
InputType output;
std::memcpy(&output, &data_, type_size);
return output;
}
public: // Iterators
constexpr inline iterator begin() noexcept { return &data_[0]; }
constexpr inline const_iterator begin() const noexcept { return &data_[0]; }
constexpr inline const_iterator cbegin() const noexcept { return &data_[0]; }
constexpr inline iterator end() noexcept { return &data_[type_size]; }
constexpr inline const_iterator end() const noexcept { return &data_[type_size]; }
constexpr inline const_iterator cend() const noexcept { return &data_[type_size]; }
inline reverse_iterator rbegin() const noexcept { return &data_[type_size]; }
inline const_reverse_iterator rbegin() noexcept { return &data_[type_size]; }
inline const_reverse_iterator crbegin() const noexcept { return &data_[type_size]; }
inline reverse_iterator rend() const noexcept { return &data_[0]; }
inline const_reverse_iterator rend() noexcept { return &data_[0]; }
inline const_reverse_iterator crend() const noexcept { return &data_[0]; }
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment