Last active
August 12, 2019 23:26
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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