blob: 683f9c3f6ee4da0915ec080eb2bac18bf13c7682 [file] [log] [blame]
#ifndef PRJXRAY_LIB_BIG_ENDIAN_SPAN
#define PRJXRAY_LIB_BIG_ENDIAN_SPAN
#include <cassert>
#include <iterator>
#include <absl/types/span.h>
namespace prjxray {
template <typename WordType, typename ByteType>
class BigEndianSpan {
public:
constexpr static size_t kBytesPerElement = sizeof(WordType);
using byte_type = ByteType;
using word_type = WordType;
using size_type = std::size_t;
class value_type {
public:
operator WordType() const {
WordType word = 0;
for (size_t ii = 0; ii < kBytesPerElement; ++ii) {
word |= (static_cast<WordType>(bytes_[ii])
<< ((kBytesPerElement - 1 - ii) * 8));
}
return word;
}
value_type& operator=(WordType word) {
for (size_t ii = 0; ii < kBytesPerElement; ++ii) {
bytes_[ii] =
((word >>
((kBytesPerElement - 1 - ii) * 8)) &
0xFF);
}
return *this;
}
protected:
friend class BigEndianSpan<WordType, ByteType>;
value_type(absl::Span<ByteType> bytes) : bytes_(bytes){};
private:
absl::Span<ByteType> bytes_;
};
class iterator
: public std::iterator<std::input_iterator_tag, value_type> {
public:
value_type operator*() const { return value_type(bytes_); }
bool operator==(const iterator& other) const {
return bytes_ == other.bytes_;
}
bool operator!=(const iterator& other) const {
return bytes_ != other.bytes_;
}
iterator& operator++() {
bytes_ = bytes_.subspan(kBytesPerElement);
return *this;
}
protected:
friend class BigEndianSpan<WordType, ByteType>;
iterator(absl::Span<ByteType> bytes) : bytes_(bytes){};
private:
absl::Span<ByteType> bytes_;
};
using pointer = value_type*;
using reference = value_type&;
BigEndianSpan(absl::Span<ByteType> bytes) : bytes_(bytes){};
constexpr size_type size() const noexcept {
return bytes_.size() / kBytesPerElement;
};
constexpr size_type length() const noexcept { return size(); }
constexpr bool empty() const noexcept { return size() == 0; }
value_type operator[](size_type pos) const {
assert(pos >= 0 && pos < size());
return value_type(bytes_.subspan((pos * kBytesPerElement)));
}
constexpr reference at(size_type pos) const {
return this->operator[](pos);
}
iterator begin() const { return iterator(bytes_); }
iterator end() const { return iterator({}); }
private:
absl::Span<ByteType> bytes_;
};
template <typename WordType, typename Container>
BigEndianSpan<WordType, typename Container::value_type> make_big_endian_span(
Container& bytes) {
return BigEndianSpan<WordType, typename Container::value_type>(
absl::Span<typename Container::value_type>(bytes));
}
} // namespace prjxray
#endif // PRJXRAY_LIB_BIG_ENDIAN_SPAN