3 * Copyright (c) 2020 Project CHIP Authors
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * Utility classes for safely reading from size-limited buffers.
26 #include <lib/core/CHIPEncoding.h>
27 #include <lib/core/CHIPError.h>
28 #include <lib/support/CodeUtils.h>
33 namespace LittleEndian {
38 * Simple reader for reading little-endian things out of buffers.
44 * Create a data model reader from a given buffer and length.
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.
52 Reader(const uint8_t * buffer, uint16_t buf_len) : mBufStart(buffer), mReadPtr(buffer), mAvailable(buf_len) {}
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
59 uint16_t OctetsRead() const { return static_cast<uint16_t>(mReadPtr - mBufStart); }
62 * Number of octets we have remaining to read. Can be useful for logging.
64 uint16_t Remaining() const { return mAvailable; }
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.
71 bool HasAtLeast(size_t octets) const { return octets <= Remaining(); }
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
79 CHIP_ERROR StatusCode() const { return mStatus; }
82 * Read a single 8-bit unsigned integer.
84 * @param [out] dest Where the 8-bit integer goes.
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.
92 Reader & Read8(uint8_t * dest)
99 * Read a single 16-bit unsigned integer.
101 * @param [out] dest Where the 16-bit integer goes.
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.
109 Reader & Read16(uint16_t * dest)
116 * Read a single 32-bit unsigned integer.
118 * @param [out] dest Where the 32-bit integer goes.
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.
126 Reader & Read32(uint32_t * dest)
133 * Read a single 64-bit unsigned integer.
135 * @param [out] dest Where the 64-bit integer goes.
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.
143 Reader & Read64(uint64_t * dest)
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.
156 template <typename T>
157 void RawRead(T * retval);
160 * Advance the Reader forward by the specified number of octets.
162 * @param len The number of octets to skip.
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.
168 Reader & Skip(uint16_t len)
170 len = ::chip::min(len, mAvailable);
172 mAvailable = static_cast<uint16_t>(mAvailable - len);
180 const uint8_t * const mBufStart;
183 * Our current read point.
185 const uint8_t * mReadPtr;
188 * The number of octets we can still read starting at mReadPtr.
193 * Our current status.
195 CHIP_ERROR mStatus = CHIP_NO_ERROR;
198 } // namespace LittleEndian
199 } // namespace Encoding