|  | #pragma once | 
|  |  | 
|  | #include <endian.h> | 
|  | #include <string.h> | 
|  |  | 
|  | #include <util/hei_includes.hpp> | 
|  |  | 
|  | namespace libhei | 
|  | { | 
|  |  | 
|  | /** @brief A streaming utility to read a Chip Data File buffer. */ | 
|  | class ChipDataStream | 
|  | { | 
|  | public: | 
|  | /** | 
|  | * @brief Constructor. | 
|  | * @param i_buffer     A pointer to the buffer. | 
|  | * @param i_bufferSize The buffer size. | 
|  | */ | 
|  | ChipDataStream(void* i_buffer, size_t i_bufferSize) : | 
|  | iv_buffer(i_buffer), iv_bufferSize(i_bufferSize) | 
|  | { | 
|  | HEI_ASSERT(nullptr != i_buffer); | 
|  | HEI_ASSERT(0 < i_bufferSize); | 
|  | } | 
|  |  | 
|  | /** @brief Destructor. */ | 
|  | ~ChipDataStream() = default; | 
|  |  | 
|  | /** @brief Copy constructor. */ | 
|  | ChipDataStream(const ChipDataStream&) = delete; | 
|  |  | 
|  | /** @brief Assignment operator. */ | 
|  | ChipDataStream& operator=(const ChipDataStream&) = delete; | 
|  |  | 
|  | private: | 
|  | /** Pointer to the first address of the Chip Data File buffer. */ | 
|  | const void* const iv_buffer; | 
|  |  | 
|  | /** The Chip Data File buffer size. */ | 
|  | const size_t iv_bufferSize; | 
|  |  | 
|  | /** Current byte index within the buffer. */ | 
|  | size_t iv_currentIndex = 0; | 
|  |  | 
|  | public: | 
|  | /** @brief Output stream operator. */ | 
|  | template <class D> | 
|  | ChipDataStream& operator>>(D& o_right) | 
|  | { | 
|  | read(&o_right, sizeof(D)); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | /** @return True, if the stream is currently at the end of the file. */ | 
|  | bool eof() | 
|  | { | 
|  | return iv_currentIndex == iv_bufferSize; | 
|  | } | 
|  |  | 
|  | private: | 
|  | /** | 
|  | * @brief Copies the given number of data bytes into the buffer from the | 
|  | *        current index and then increments the index. | 
|  | * @param o_buf  The output buffer. | 
|  | * @param i_size The number of bytes to copy. | 
|  | */ | 
|  | void read(void* o_buf, size_t i_size) | 
|  | { | 
|  | // Check for buffer overflow. | 
|  | HEI_ASSERT((iv_currentIndex + i_size) <= iv_bufferSize); | 
|  |  | 
|  | // Copy the buffer. | 
|  | memcpy(o_buf, static_cast<const char*>(iv_buffer) + iv_currentIndex, | 
|  | i_size); | 
|  |  | 
|  | // Increment the curent index for the next piece of data. | 
|  | iv_currentIndex += i_size; | 
|  | } | 
|  | }; | 
|  |  | 
|  | /** @brief Template specialization for uint16_t. */ | 
|  | template <> | 
|  | inline ChipDataStream& ChipDataStream::operator>>(uint16_t& o_right) | 
|  | { | 
|  | read(&o_right, sizeof(o_right)); | 
|  | o_right = be16toh(o_right); // Chip Data is big-endian | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | /** @brief Template specialization for int16_t. */ | 
|  | template <> | 
|  | inline ChipDataStream& ChipDataStream::operator>>(int16_t& o_right) | 
|  | { | 
|  | read(&o_right, sizeof(o_right)); | 
|  | o_right = be16toh(o_right); // Chip Data is big-endian | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | /** @brief Template specialization for uint32_t. */ | 
|  | template <> | 
|  | inline ChipDataStream& ChipDataStream::operator>>(uint32_t& o_right) | 
|  | { | 
|  | read(&o_right, sizeof(o_right)); | 
|  | o_right = be32toh(o_right); // Chip Data is big-endian | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | /** @brief Template specialization for int32_t. */ | 
|  | template <> | 
|  | inline ChipDataStream& ChipDataStream::operator>>(int32_t& o_right) | 
|  | { | 
|  | read(&o_right, sizeof(o_right)); | 
|  | o_right = be32toh(o_right); // Chip Data is big-endian | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | /** @brief Template specialization for uint64_t. */ | 
|  | template <> | 
|  | inline ChipDataStream& ChipDataStream::operator>>(uint64_t& o_right) | 
|  | { | 
|  | read(&o_right, sizeof(o_right)); | 
|  | o_right = be64toh(o_right); // Chip Data is big-endian | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | /** @brief Template specialization for int64_t. */ | 
|  | template <> | 
|  | inline ChipDataStream& ChipDataStream::operator>>(int64_t& o_right) | 
|  | { | 
|  | read(&o_right, sizeof(o_right)); | 
|  | o_right = be64toh(o_right); // Chip Data is big-endian | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | /** @brief Template specialization for RegisterId_t. */ | 
|  | template <> | 
|  | inline ChipDataStream& ChipDataStream::operator>>(RegisterId_t& o_right) | 
|  | { | 
|  | // A register ID is only 3 bytes, but there isn't a 24-bit integer type. So | 
|  | // extract 3 bytes to a uint32_t and drop the unused byte. | 
|  | uint32_t tmp = 0; | 
|  | read(&tmp, 3); | 
|  | o_right = static_cast<RegisterId_t>(be32toh(tmp) >> 8); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | } // namespace libhei |