#ifndef XRPL_BASICS_SLICE_H_INCLUDED #define XRPL_BASICS_SLICE_H_INCLUDED #include #include #include #include #include #include #include #include #include #include #include #include namespace ripple { /** An immutable linear range of bytes. A fully constructed Slice is guaranteed to be in a valid state. A Slice is lightweight and copyable, it retains no ownership of the underlying memory. */ class Slice { private: std::uint8_t const* data_ = nullptr; std::size_t size_ = 0; public: using value_type = std::uint8_t; using const_iterator = value_type const*; /** Default constructed Slice has length 0. */ Slice() noexcept = default; Slice(Slice const&) noexcept = default; Slice& operator=(Slice const&) noexcept = default; /** Create a slice pointing to existing memory. */ Slice(void const* data, std::size_t size) noexcept : data_(reinterpret_cast(data)), size_(size) { } /** Return `true` if the byte range is empty. */ [[nodiscard]] bool empty() const noexcept { return size_ == 0; } /** Returns the number of bytes in the storage. This may be zero for an empty range. */ /** @{ */ [[nodiscard]] std::size_t size() const noexcept { return size_; } [[nodiscard]] std::size_t length() const noexcept { return size_; } /** @} */ /** Return a pointer to beginning of the storage. @note The return type is guaranteed to be a pointer to a single byte, to facilitate pointer arithmetic. */ std::uint8_t const* data() const noexcept { return data_; } /** Access raw bytes. */ std::uint8_t operator[](std::size_t i) const noexcept { XRPL_ASSERT( i < size_, "ripple::Slice::operator[](std::size_t) const : valid input"); return data_[i]; } /** Advance the buffer. */ /** @{ */ Slice& operator+=(std::size_t n) { if (n > size_) Throw("too small"); data_ += n; size_ -= n; return *this; } Slice operator+(std::size_t n) const { Slice temp = *this; return temp += n; } /** @} */ /** Shrinks the slice by moving its start forward by n characters. */ void remove_prefix(std::size_t n) { data_ += n; size_ -= n; } /** Shrinks the slice by moving its end backward by n characters. */ void remove_suffix(std::size_t n) { size_ -= n; } const_iterator begin() const noexcept { return data_; } const_iterator cbegin() const noexcept { return data_; } const_iterator end() const noexcept { return data_ + size_; } const_iterator cend() const noexcept { return data_ + size_; } /** Return a "sub slice" of given length starting at the given position Note that the subslice encompasses the range [pos, pos + rcount), where rcount is the smaller of count and size() - pos. @param pos position of the first character @count requested length @returns The requested subslice, if the request is valid. @throws std::out_of_range if pos > size() */ Slice substr( std::size_t pos, std::size_t count = std::numeric_limits::max()) const { if (pos > size()) throw std::out_of_range("Requested sub-slice is out of bounds"); return {data_ + pos, std::min(count, size() - pos)}; } }; //------------------------------------------------------------------------------ template inline void hash_append(Hasher& h, Slice const& v) { h(v.data(), v.size()); } inline bool operator==(Slice const& lhs, Slice const& rhs) noexcept { if (lhs.size() != rhs.size()) return false; if (lhs.size() == 0) return true; return std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0; } inline bool operator!=(Slice const& lhs, Slice const& rhs) noexcept { return !(lhs == rhs); } inline bool operator<(Slice const& lhs, Slice const& rhs) noexcept { return std::lexicographical_compare( lhs.data(), lhs.data() + lhs.size(), rhs.data(), rhs.data() + rhs.size()); } template Stream& operator<<(Stream& s, Slice const& v) { s << strHex(v); return s; } template std::enable_if_t< std::is_same::value || std::is_same::value, Slice> makeSlice(std::array const& a) { return Slice(a.data(), a.size()); } template std::enable_if_t< std::is_same::value || std::is_same::value, Slice> makeSlice(std::vector const& v) { return Slice(v.data(), v.size()); } template Slice makeSlice(std::basic_string const& s) { return Slice(s.data(), s.size()); } } // namespace ripple #endif