Line data Source code
1 : /********************************************************************************
2 : * Copyright (c) 2026 Accenture
3 : *
4 : * This program and the accompanying materials are made available under the
5 : * terms of the Apache License Version 2.0 which is available at
6 : * https://www.apache.org/licenses/LICENSE-2.0
7 : *
8 : * SPDX-License-Identifier: Apache-2.0
9 : ********************************************************************************/
10 :
11 : #pragma once
12 :
13 : #include "someip/ISomeIpSerializable.h"
14 : #include "someip/SomeIpStreamer.h"
15 :
16 : #include <etl/span.h>
17 : #include <etl/unaligned_type.h>
18 :
19 : #include <cstdint>
20 :
21 : #include <cmath>
22 :
23 : namespace someip
24 : {
25 : /**
26 : * The SomeIpParser class provides an easy way to parse Some/IP
27 : * types from raw bytes. The class is created with a buffer to
28 : * ensure that buffer overwrites do not happen. If a parser object
29 : * enters an error state all subsequent reads will be empty operations;
30 : * they will not cause other problems.
31 : *
32 : * \section SomeIpParser_example Usage example
33 : * \code{.cpp}
34 : * void parser(::etl::span<const uint8_t> source, ISomeIpSerializable& obj)
35 : * {
36 : * SomeIpParser parser(source);
37 : *
38 : * // read the object
39 : * parser >> obj;
40 : *
41 : * // read some more data
42 : * uint32_t value;
43 : * parser >> value;
44 : * }
45 : * \endcode
46 : */
47 : class SomeIpParser : public SomeIpStreamer
48 : {
49 : public:
50 : /**
51 : * Creates a new SomeIpParser using the specified constant byte buffer.
52 : *
53 : * \param buffer The buffer that holds the bytes that will be read.
54 : */
55 : explicit SomeIpParser(::etl::span<uint8_t const> buffer);
56 :
57 : /**
58 : * Reads a bool value from the current position in the buffer by reading
59 : * in a uint8_t and converting that to a bool.
60 : *
61 : * \param item The boolean value to read.
62 : *
63 : * \note If the parser is in an error state then no value will be read
64 : * from the buffer. If there is no space left in the buffer to read the value
65 : * then the parser will set to an error state.
66 : */
67 4 : void operator>>(bool& item) { read_byte(item); }
68 :
69 : /**
70 : * Reads a char value from the current position in the buffer.
71 : *
72 : * \param item The char value to read.
73 : *
74 : * \note If the parser is in an error state then no value will be read
75 : * from the buffer. If there is no space left in the buffer to read the value
76 : * then the parser will set to an error state.
77 : */
78 149 : void operator>>(char& item) { read_byte(item); }
79 :
80 : /**
81 : * Reads a uint8_t value from the current position in the buffer.
82 : *
83 : * \param item The uint8_t value to read.
84 : *
85 : * \note If the parser is in an error state then no value will be read
86 : * from the buffer. If there is no space left in the buffer to read the value
87 : * then the parser will set to an error state.
88 : */
89 43 : void operator>>(uint8_t& item) { read_byte(item); }
90 :
91 : /**
92 : * Reads an int8_t value from the current position in the buffer.
93 : *
94 : * \param item The int8_t value to read.
95 : *
96 : * \note If the parser is in an error state then no value will be read
97 : * from the buffer. If there is no space left in the buffer to read the value
98 : * then the parser will set to an error state.
99 : */
100 4 : void operator>>(int8_t& item) { read_byte(item); }
101 :
102 : /**
103 : * Reads a uint16_t value from the current position in the buffer in the
104 : * currently selected endianness.
105 : *
106 : * \param item The uint16_t value to read.
107 : *
108 : * \note If the parser is in an error state then no value will be read
109 : * from the buffer. If there is no space left in the buffer to read the value
110 : * then the parser will set to an error state.
111 : */
112 15 : void operator>>(uint16_t& item) { read(item); }
113 :
114 : /**
115 : * Reads an int16_t value from the current position in the buffer in the
116 : * currently selected endianness.
117 : *
118 : * \param item The int16_t value to read.
119 : *
120 : * \note If the parser is in an error state then no value will be read
121 : * from the buffer. If there is no space left in the buffer to read the value
122 : * then the parser will set to an error state.
123 : */
124 4 : void operator>>(int16_t& item) { read(item); }
125 :
126 : /**
127 : * Reads a uint32_t value from the current position in the buffer in the
128 : * currently selected endianness.
129 : *
130 : * \param item The uint32_t value to read.
131 : *
132 : * \note If the parser is in an error state then no value will be read
133 : * from the buffer. If there is no space left in the buffer to read the value
134 : * then the parser will set to an error state.
135 : */
136 16 : void operator>>(uint32_t& item) { read(item); }
137 :
138 : /**
139 : * Reads an int32_t value from the current position in the buffer in the
140 : * currently selected endianness.
141 : *
142 : * \param item The int32_t value to read.
143 : *
144 : * \note If the parser is in an error state then no value will be read
145 : * from the buffer. If there is no space left in the buffer to read the value
146 : * then the parser will set to an error state.
147 : */
148 4 : void operator>>(int32_t& item) { read(item); }
149 :
150 : /**
151 : * Reads a uint64_t value from the current position in the buffer in the
152 : * currently selected endianness.
153 : *
154 : * \param item The uint64_t value to read.
155 : *
156 : * \note If the parser is in an error state then no value will be read
157 : * from the buffer. If there is no space left in the buffer to read the value
158 : * then the parser will set to an error state.
159 : */
160 4 : void operator>>(uint64_t& item) { read(item); }
161 :
162 : /**
163 : * Reads an int64_t value from the current position in the buffer in the
164 : * currently selected endianness.
165 : *
166 : * \param item The int64_t value to read.
167 : *
168 : * \note If the parser is in an error state then no value will be read
169 : * from the buffer. If there is no space left in the buffer to read the value
170 : * then the parser will set to an error state.
171 : */
172 4 : void operator>>(int64_t& item) { read(item); }
173 :
174 : /**
175 : * Reads a float value from the current position in the buffer according to the
176 : * IEEE-754 standard. 4 bytes will be read from the buffer.
177 : *
178 : * \param item The float value to read.
179 : *
180 : * \note If the parser is in an error state then no value will be read
181 : * from the buffer. If there is no space left in the buffer to read the value
182 : * then the parser will set to an error state.
183 : */
184 : void operator>>(float_t& item);
185 :
186 : /**
187 : * Reads a double value from the current position in the buffer according to the
188 : * IEEE-754 standard. 8 bytes will be read from the buffer.
189 : *
190 : * \param item The double value to read.
191 : *
192 : * \note If the parser is in an error state then no value will be read
193 : * from the buffer. If there is no space left in the buffer to read the value
194 : * then the parser will set to an error state.
195 : */
196 : void operator>>(double_t& item);
197 :
198 : /**
199 : * Reads the ISomeIpSerializable object from the stream.
200 : * This calls the ISomeIpSerializable::parseFromArray method.
201 : *
202 : * \param item The serializable object to read.
203 : *
204 : * \note If the stream is in an error state then no value will be read
205 : * from the buffer. If an error happens during the call to parseFromArray then
206 : * the parser will be set to an error state. The data in the underlying object may
207 : * be corrupted and incomplete and should not be used.
208 : */
209 : void operator>>(ISomeIpSerializable& item);
210 :
211 : /**
212 : * Skips the specified number of bytes if there are that many bytes left.
213 : * If there are not enough bytes to skip then the parser is set to an error state.
214 : *
215 : * \param bytes The number of bytes to skip.
216 : */
217 : void skip(size_t bytes);
218 :
219 : uint32_t readTypeFieldSize();
220 :
221 120 : size_t getCurrentPosition() const { return _currentPos; }
222 :
223 4 : void resetCurrentPosition() { _currentPos = 0U; }
224 :
225 : /**
226 : * Returns how much more data can be read
227 : */
228 31 : size_t bytesAvailable() const { return _buffer.size() - _currentPos; }
229 :
230 : ::etl::span<uint8_t const> getAvailableBuffer() const { return _buffer.subspan(_currentPos); }
231 :
232 : private:
233 : template<typename T>
234 47 : void read(T& item)
235 : {
236 47 : if (hasSpace(sizeof(T)) && isGood())
237 : {
238 35 : if (_bigEndian)
239 : {
240 25 : item = ::etl::unaligned_type<T, ::etl::endian::big>(&_buffer[_currentPos]);
241 : }
242 : else
243 : {
244 10 : item = ::etl::unaligned_type<T, ::etl::endian::little>(&_buffer[_currentPos]);
245 : }
246 35 : _currentPos += sizeof(T);
247 : }
248 47 : }
249 :
250 : template<typename T>
251 200 : void read_byte(T& item)
252 : {
253 200 : if (hasSpace(1) && isGood())
254 : {
255 195 : item = static_cast<T>(_buffer[_currentPos]);
256 195 : _currentPos++;
257 : }
258 200 : }
259 :
260 283 : bool hasSpace(size_t const length)
261 : {
262 283 : if (_currentPos + length > _buffer.size())
263 : {
264 20 : _errorCode = ErrorCode::SOMEIP_ERROR;
265 20 : return false;
266 : }
267 :
268 263 : return true;
269 : }
270 :
271 : ::etl::span<uint8_t const> _buffer;
272 : size_t _currentPos;
273 : };
274 :
275 : void skip(SomeIpParser& parser, uint16_t tag);
276 :
277 : } // namespace someip
|