blob: cb3ed7d6f4cf999e2704a1af0e54ecff59e3a9c6 [file] [log] [blame]
Paul Greenwood31a54882019-08-01 17:05:09 -05001#pragma once
2
Paul Greenwood31a54882019-08-01 17:05:09 -05003#include <endian.h>
Paul Greenwood31a54882019-08-01 17:05:09 -05004#include <string.h>
5
Zane Shelleyd5073512021-01-14 12:51:18 -06006#include <util/hei_includes.hpp>
Zane Shelleyca9f6252019-10-25 21:17:30 -05007
Paul Greenwood31a54882019-08-01 17:05:09 -05008namespace libhei
9{
10
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050011/** @brief A streaming utility to read a Chip Data File buffer. */
Paul Greenwood31a54882019-08-01 17:05:09 -050012class ChipDataStream
13{
Paul Greenwood31a54882019-08-01 17:05:09 -050014 public:
Zane Shelley83da2452019-10-25 15:45:34 -050015 /**
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050016 * @brief Constructor.
17 * @param i_buffer A pointer to the buffer.
18 * @param i_bufferSize The buffer size.
19 */
Zane Shelleyfe27b652019-10-28 11:33:07 -050020 ChipDataStream(void* i_buffer, size_t i_bufferSize) :
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050021 iv_buffer(i_buffer), iv_bufferSize(i_bufferSize)
22 {
23 HEI_ASSERT(nullptr != i_buffer);
24 HEI_ASSERT(0 < i_bufferSize);
25 }
Paul Greenwood31a54882019-08-01 17:05:09 -050026
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050027 /** @brief Destructor. */
Zane Shelley83da2452019-10-25 15:45:34 -050028 ~ChipDataStream() = default;
Paul Greenwood31a54882019-08-01 17:05:09 -050029
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050030 /** @brief Copy constructor. */
31 ChipDataStream(const ChipDataStream&) = delete;
Paul Greenwood31a54882019-08-01 17:05:09 -050032
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050033 /** @brief Assignment operator. */
34 ChipDataStream& operator=(const ChipDataStream&) = delete;
35
36 private:
37 /** Pointer to the first address of the Chip Data File buffer. */
38 const void* const iv_buffer;
39
40 /** The Chip Data File buffer size. */
41 const size_t iv_bufferSize;
42
43 /** Current byte index within the buffer. */
44 size_t iv_currentIndex = 0;
45
46 public:
47 /** @brief Output stream operator. */
Zane Shelley83da2452019-10-25 15:45:34 -050048 template <class D>
Zane Shelleyfe27b652019-10-28 11:33:07 -050049 ChipDataStream& operator>>(D& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -050050 {
51 read(&o_right, sizeof(D));
52 return *this;
53 }
Paul Greenwood31a54882019-08-01 17:05:09 -050054
Zane Shelley0165edc2020-05-11 22:28:29 -050055 /** @return True, if the stream is currently at the end of the file. */
56 bool eof()
57 {
58 return iv_currentIndex == iv_bufferSize;
59 }
60
Paul Greenwood31a54882019-08-01 17:05:09 -050061 private:
Zane Shelley83da2452019-10-25 15:45:34 -050062 /**
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050063 * @brief Copies the given number of data bytes into the buffer from the
64 * current index and then increments the index.
65 * @param o_buf The output buffer.
66 * @param i_size The number of bytes to copy.
67 */
Zane Shelleyfe27b652019-10-28 11:33:07 -050068 void read(void* o_buf, size_t i_size)
Zane Shelley83da2452019-10-25 15:45:34 -050069 {
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050070 // Check for buffer overflow.
71 HEI_ASSERT((iv_currentIndex + i_size) <= iv_bufferSize);
72
73 // Copy the buffer.
Zane Shelley5a78fa82022-09-16 16:49:58 -050074 memcpy(o_buf, static_cast<const char*>(iv_buffer) + iv_currentIndex,
75 i_size);
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050076
77 // Increment the curent index for the next piece of data.
78 iv_currentIndex += i_size;
Zane Shelley83da2452019-10-25 15:45:34 -050079 }
Paul Greenwood31a54882019-08-01 17:05:09 -050080};
81
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050082/** @brief Template specialization for uint16_t. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -050083template <>
84inline ChipDataStream& ChipDataStream::operator>>(uint16_t& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -050085{
86 read(&o_right, sizeof(o_right));
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050087 o_right = be16toh(o_right); // Chip Data is big-endian
Zane Shelley83da2452019-10-25 15:45:34 -050088 return *this;
89}
Paul Greenwood31a54882019-08-01 17:05:09 -050090
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050091/** @brief Template specialization for int16_t. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -050092template <>
93inline ChipDataStream& ChipDataStream::operator>>(int16_t& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -050094{
95 read(&o_right, sizeof(o_right));
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050096 o_right = be16toh(o_right); // Chip Data is big-endian
Zane Shelley83da2452019-10-25 15:45:34 -050097 return *this;
98}
Paul Greenwood31a54882019-08-01 17:05:09 -050099
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500100/** @brief Template specialization for uint32_t. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -0500101template <>
102inline ChipDataStream& ChipDataStream::operator>>(uint32_t& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -0500103{
104 read(&o_right, sizeof(o_right));
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500105 o_right = be32toh(o_right); // Chip Data is big-endian
Zane Shelley83da2452019-10-25 15:45:34 -0500106 return *this;
107}
Paul Greenwood31a54882019-08-01 17:05:09 -0500108
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500109/** @brief Template specialization for int32_t. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -0500110template <>
111inline ChipDataStream& ChipDataStream::operator>>(int32_t& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -0500112{
113 read(&o_right, sizeof(o_right));
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500114 o_right = be32toh(o_right); // Chip Data is big-endian
Zane Shelley83da2452019-10-25 15:45:34 -0500115 return *this;
116}
Paul Greenwood31a54882019-08-01 17:05:09 -0500117
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500118/** @brief Template specialization for uint64_t. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -0500119template <>
120inline ChipDataStream& ChipDataStream::operator>>(uint64_t& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -0500121{
122 read(&o_right, sizeof(o_right));
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500123 o_right = be64toh(o_right); // Chip Data is big-endian
Zane Shelley83da2452019-10-25 15:45:34 -0500124 return *this;
125}
Paul Greenwood31a54882019-08-01 17:05:09 -0500126
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500127/** @brief Template specialization for int64_t. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -0500128template <>
129inline ChipDataStream& ChipDataStream::operator>>(int64_t& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -0500130{
131 read(&o_right, sizeof(o_right));
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500132 o_right = be64toh(o_right); // Chip Data is big-endian
Zane Shelley83da2452019-10-25 15:45:34 -0500133 return *this;
134}
Paul Greenwood31a54882019-08-01 17:05:09 -0500135
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500136/** @brief Template specialization for RegisterId_t. */
137template <>
138inline ChipDataStream& ChipDataStream::operator>>(RegisterId_t& o_right)
139{
140 // A register ID is only 3 bytes, but there isn't a 24-bit integer type. So
141 // extract 3 bytes to a uint32_t and drop the unused byte.
142 uint32_t tmp = 0;
143 read(&tmp, 3);
144 o_right = static_cast<RegisterId_t>(be32toh(tmp) >> 8);
145 return *this;
146}
147
Zane Shelley83da2452019-10-25 15:45:34 -0500148} // namespace libhei