blob: 1ca28aff110c501f6dda422f1f2d53b83fc5a5aa [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.
74 memcpy(o_buf, (char*)iv_buffer + iv_currentIndex, i_size);
75
76 // Increment the curent index for the next piece of data.
77 iv_currentIndex += i_size;
Zane Shelley83da2452019-10-25 15:45:34 -050078 }
Paul Greenwood31a54882019-08-01 17:05:09 -050079};
80
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050081/** @brief Template specialization for uint16_t. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -050082template <>
83inline ChipDataStream& ChipDataStream::operator>>(uint16_t& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -050084{
85 read(&o_right, sizeof(o_right));
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050086 o_right = be16toh(o_right); // Chip Data is big-endian
Zane Shelley83da2452019-10-25 15:45:34 -050087 return *this;
88}
Paul Greenwood31a54882019-08-01 17:05:09 -050089
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050090/** @brief Template specialization for int16_t. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -050091template <>
92inline ChipDataStream& ChipDataStream::operator>>(int16_t& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -050093{
94 read(&o_right, sizeof(o_right));
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050095 o_right = be16toh(o_right); // Chip Data is big-endian
Zane Shelley83da2452019-10-25 15:45:34 -050096 return *this;
97}
Paul Greenwood31a54882019-08-01 17:05:09 -050098
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -050099/** @brief Template specialization for uint32_t. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -0500100template <>
101inline ChipDataStream& ChipDataStream::operator>>(uint32_t& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -0500102{
103 read(&o_right, sizeof(o_right));
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500104 o_right = be32toh(o_right); // Chip Data is big-endian
Zane Shelley83da2452019-10-25 15:45:34 -0500105 return *this;
106}
Paul Greenwood31a54882019-08-01 17:05:09 -0500107
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500108/** @brief Template specialization for int32_t. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -0500109template <>
110inline ChipDataStream& ChipDataStream::operator>>(int32_t& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -0500111{
112 read(&o_right, sizeof(o_right));
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500113 o_right = be32toh(o_right); // Chip Data is big-endian
Zane Shelley83da2452019-10-25 15:45:34 -0500114 return *this;
115}
Paul Greenwood31a54882019-08-01 17:05:09 -0500116
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500117/** @brief Template specialization for uint64_t. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -0500118template <>
119inline ChipDataStream& ChipDataStream::operator>>(uint64_t& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -0500120{
121 read(&o_right, sizeof(o_right));
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500122 o_right = be64toh(o_right); // Chip Data is big-endian
Zane Shelley83da2452019-10-25 15:45:34 -0500123 return *this;
124}
Paul Greenwood31a54882019-08-01 17:05:09 -0500125
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500126/** @brief Template specialization for int64_t. */
Zane Shelley7f7a42d2019-10-28 13:28:31 -0500127template <>
128inline ChipDataStream& ChipDataStream::operator>>(int64_t& o_right)
Zane Shelley83da2452019-10-25 15:45:34 -0500129{
130 read(&o_right, sizeof(o_right));
Zane Shelleyb8b3cdf2020-05-04 13:28:04 -0500131 o_right = be64toh(o_right); // Chip Data is big-endian
Zane Shelley83da2452019-10-25 15:45:34 -0500132 return *this;
133}
Paul Greenwood31a54882019-08-01 17:05:09 -0500134
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500135/** @brief Template specialization for RegisterId_t. */
136template <>
137inline ChipDataStream& ChipDataStream::operator>>(RegisterId_t& o_right)
138{
139 // A register ID is only 3 bytes, but there isn't a 24-bit integer type. So
140 // extract 3 bytes to a uint32_t and drop the unused byte.
141 uint32_t tmp = 0;
142 read(&tmp, 3);
143 o_right = static_cast<RegisterId_t>(be32toh(tmp) >> 8);
144 return *this;
145}
146
Zane Shelley83da2452019-10-25 15:45:34 -0500147} // namespace libhei