Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / lib / support / BufferReader.h
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *
5  *    Licensed under the Apache License, Version 2.0 (the "License");
6  *    you may not use this file except in compliance with the License.
7  *    You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *    Unless required by applicable law or agreed to in writing, software
12  *    distributed under the License is distributed on an "AS IS" BASIS,
13  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *    See the License for the specific language governing permissions and
15  *    limitations under the License.
16  */
17
18 /**
19  *  @file
20  *    Utility classes for safely reading from size-limited buffers.
21  */
22
23 #pragma once
24
25 #include <climits>
26 #include <lib/core/CHIPEncoding.h>
27 #include <lib/core/CHIPError.h>
28 #include <lib/support/CodeUtils.h>
29 #include <stdint.h>
30
31 namespace chip {
32 namespace Encoding {
33 namespace LittleEndian {
34
35 /**
36  *  @class Reader
37  *
38  *  Simple reader for reading little-endian things out of buffers.
39  */
40 class Reader
41 {
42 public:
43     /**
44      * Create a data model reader from a given buffer and length.
45      *
46      * @param buffer The octet buffer to read from.  The caller must ensure
47      *               (most simply by allocating the reader on the stack) that
48      *               the buffer outlives the reader.  The buffer is allowed to
49      *               be null if buf_len is 0.
50      * @param buf_len The number of octets in the buffer.
51      */
52     Reader(const uint8_t * buffer, uint16_t buf_len) : mBufStart(buffer), mReadPtr(buffer), mAvailable(buf_len) {}
53
54     /**
55      * Number of octets we have read so far.  This might be able to go away once
56      * we do less switching back and forth between DataModelReader and raw
57      * buffers.
58      */
59     uint16_t OctetsRead() const { return static_cast<uint16_t>(mReadPtr - mBufStart); }
60
61     /**
62      * Number of octets we have remaining to read.  Can be useful for logging.
63      */
64     uint16_t Remaining() const { return mAvailable; }
65
66     /**
67      * Test whether we have at least the given number of octets left to read.
68      * This takes a size_t, not uint16_t, to make life a bit simpler for
69      * consumers and avoid casting.
70      */
71     bool HasAtLeast(size_t octets) const { return octets <= Remaining(); }
72
73     /**
74      * The reader status.  Once the status becomes a failure status, all later
75      * read operations become no-ops and the status continues to be a failure
76      * status.
77      */
78     CHECK_RETURN_VALUE
79     CHIP_ERROR StatusCode() const { return mStatus; }
80
81     /**
82      * Read a single 8-bit unsigned integer.
83      *
84      * @param [out] dest Where the 8-bit integer goes.
85      *
86      * @note The read can put the reader in a failed-status state if there are
87      *       not enough octets available.  Callers must either continue to do
88      *       more reads on the return value or check its status to see whether
89      *       the sequence of reads that has been performed succeeded.
90      */
91     CHECK_RETURN_VALUE
92     Reader & Read8(uint8_t * dest)
93     {
94         RawRead(dest);
95         return *this;
96     }
97
98     /**
99      * Read a single 16-bit unsigned integer.
100      *
101      * @param [out] dest Where the 16-bit integer goes.
102      *
103      * @note The read can put the reader in a failed-status state if there are
104      *       not enough octets available.  Callers must either continue to do
105      *       more reads on the return value or check its status to see whether
106      *       the sequence of reads that has been performed succeeded.
107      */
108     CHECK_RETURN_VALUE
109     Reader & Read16(uint16_t * dest)
110     {
111         RawRead(dest);
112         return *this;
113     }
114
115     /**
116      * Read a single 32-bit unsigned integer.
117      *
118      * @param [out] dest Where the 32-bit integer goes.
119      *
120      * @note The read can put the reader in a failed-status state if there are
121      *       not enough octets available.  Callers must either continue to do
122      *       more reads on the return value or check its status to see whether
123      *       the sequence of reads that has been performed succeeded.
124      */
125     CHECK_RETURN_VALUE
126     Reader & Read32(uint32_t * dest)
127     {
128         RawRead(dest);
129         return *this;
130     }
131
132     /**
133      * Read a single 64-bit unsigned integer.
134      *
135      * @param [out] dest Where the 64-bit integer goes.
136      *
137      * @note The read can put the reader in a failed-status state if there are
138      *       not enough octets available.  Callers must either continue to do
139      *       more reads on the return value or check its status to see whether
140      *       the sequence of reads that has been performed succeeded.
141      */
142     CHECK_RETURN_VALUE
143     Reader & Read64(uint64_t * dest)
144     {
145         RawRead(dest);
146         return *this;
147     }
148
149     /**
150      * Helper for our various APIs so we don't have to write out various logic
151      * multiple times.  This is public so that consumers that want to read into
152      * whatever size a logical thing they are reading into has don't have to
153      * hardcode the right API.  This is meant for other reader classes that
154      * delegate to this one.
155      */
156     template <typename T>
157     void RawRead(T * retval);
158
159     /**
160      * Advance the Reader forward by the specified number of octets.
161      *
162      * @param len The number of octets to skip.
163      *
164      * @note If the len argument is greater than the number of available octets
165      *       remaining, the Reader will advance to the end of the buffer
166      *       without entering a failed-status state.
167      */
168     Reader & Skip(uint16_t len)
169     {
170         len = ::chip::min(len, mAvailable);
171         mReadPtr += len;
172         mAvailable = static_cast<uint16_t>(mAvailable - len);
173         return *this;
174     }
175
176 private:
177     /**
178      * Our buffer start.
179      */
180     const uint8_t * const mBufStart;
181
182     /**
183      * Our current read point.
184      */
185     const uint8_t * mReadPtr;
186
187     /**
188      * The number of octets we can still read starting at mReadPtr.
189      */
190     uint16_t mAvailable;
191
192     /**
193      * Our current status.
194      */
195     CHIP_ERROR mStatus = CHIP_NO_ERROR;
196 };
197
198 } // namespace LittleEndian
199 } // namespace Encoding
200 } // namespace chip