mirror of https://github.com/openXC7/prjxray.git
116 lines
2.7 KiB
C++
116 lines
2.7 KiB
C++
#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
|