#ifndef __VEREIGN_BYTES_VIEW_HH #define __VEREIGN_BYTES_VIEW_HH #include <cstring> #include <string> #include <string_view> #include <stdexcept> #include <algorithm> namespace vereign::bytes { class View { public: View() noexcept : size_{0}, data_{nullptr} {} View(const uint8_t* data, std::size_t size) noexcept : size_{size}, data_{data} { } View(std::string_view str) noexcept : size_{str.length()}, data_{str.length() > 0 ? reinterpret_cast<const uint8_t*>(str.data()): nullptr} { } View(const void* ptr, std::size_t size) noexcept : size_{size}, data_{static_cast<const uint8_t*>(ptr)} { } View(const View&) = default; auto operator=(const View&) -> View& = default; auto Slice(std::size_t start) const -> View { if (start >= size_) { return View(data_, 0); } return View(data_ + start, size_ - start); } auto Slice(std::size_t start, std::size_t end) const -> View { if (start >= size_) { return View(data_, 0); } return View(data_ + start, std::min(size_, end) - start); } auto Data() const noexcept -> const uint8_t* { return data_; } auto CharData() const noexcept -> const char* { return reinterpret_cast<const char*>(data_); } auto Size() const noexcept -> std::size_t { return size_; } auto String() const noexcept -> std::string_view { return std::string_view{CharData(), size_}; } auto operator==(View other) const noexcept -> bool { if (size_ != other.size_) { return false; } return std::memcmp(data_, other.data_, size_) == 0; } auto operator[](std::size_t index) const -> const uint8_t& { if (index >= size_ ) { throw std::runtime_error("index out of bounds"); } return data_[index]; } private: std::size_t size_ = 0; const uint8_t* data_ = nullptr; }; } // namespace vereign::bytes #endif // __VEREIGN_BYTES_VIEW_HH