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/LengthHelper.h"
14 : #include "someip/PrimitiveTypes.h"
15 : #include "someip/SomeIpParser.h"
16 : #include "someip/SomeIpSerializer.h"
17 : #include "someip/StringEncoding.h"
18 :
19 : #include <etl/vector.h>
20 :
21 : namespace someip
22 : {
23 : namespace internal
24 : {
25 : /// \cond INTERNAL
26 : template<class T, size_t S>
27 : struct GetSizeHelper<::etl::vector<T, S>>
28 : {
29 4 : static uint32_t getSize(::etl::vector<T, S> const& t, uint32_t const lengthSize)
30 : {
31 4 : uint32_t size = lengthSize;
32 :
33 12 : for (uint32_t i = 0U; i < t.size(); ++i)
34 : {
35 8 : size += GetSizeHelper<T>::getSize(t[i], lengthSize);
36 : }
37 :
38 4 : return size;
39 : }
40 :
41 : static uint32_t
42 1 : getSize(::etl::vector<T, S> const& t, uint32_t const lengthSize, Encoding const encoding)
43 : {
44 1 : uint32_t size = lengthSize;
45 :
46 5 : for (uint32_t i = 0U; i < t.size(); ++i)
47 : {
48 4 : size += GetSizeHelper<T>::getSize(t[i], lengthSize, encoding);
49 : }
50 :
51 1 : return size;
52 : }
53 : };
54 :
55 : /// \endcond
56 :
57 : } // namespace internal
58 : } // namespace someip
59 :
60 : namespace someip
61 : {
62 : /**
63 : * DynamicArrayParser is a helper class used for reading a SOME/IP dynamic array from
64 : * an array of bytes.
65 : *
66 : * \tparam T The type of the underlying dynamic array.
67 : * \tparam LENGTH_TYPE The type used for the length field.
68 : */
69 : template<class T, class LENGTH_TYPE>
70 : class DynamicArrayParser
71 : {
72 : public:
73 : DynamicArrayParser() = delete;
74 :
75 : /**
76 : * Create a DynamicArrayParser that will fill the specified 'obj' with objects of type 'T'.
77 : *
78 : * \param obj The estd vector to fill
79 : * \param parser The SomeIpParser used to parse the dynamic array items
80 : * \param minLength The minimum number of elements required for this dynamic array
81 : * \param isBigEndian True if this dynamic array is stored in big endian, false for little
82 : * endian
83 : */
84 : static void
85 : parse(::etl::ivector<T>& obj, SomeIpParser& parser, size_t minLength, bool isBigEndian);
86 : };
87 :
88 : /**
89 : * DynamicArraySerializer is a helper class used for writing a SOME/IP dynamic array to
90 : * an array of bytes.
91 : *
92 : * \tparam T The type of the underlying dynamic array.
93 : * \tparam LENGTH_TYPE The type used for the length field.
94 : */
95 : template<class T, class LENGTH_TYPE>
96 : class DynamicArraySerializer
97 : {
98 : public:
99 : DynamicArraySerializer() = delete;
100 :
101 : /**
102 : * Create a DynamicArraySerializer to serialize the specified vector into an array of bytes.
103 : *
104 : * \param obj The vector to serialize.
105 : * \param serialize The SomeIpSerializer used to serialize the dynamic array items
106 : * \param minLength The minimum number of elements required for this dynamic array
107 : * \param isBigEndian True if this dynamic array is stored in big endian, false for little
108 : * endian
109 : */
110 : static void serialize(
111 : ::etl::ivector<T> const& obj,
112 : SomeIpSerializer& serializer,
113 : size_t minLength,
114 : bool isBigEndian);
115 : };
116 :
117 : /*
118 : * inline implementation
119 : */
120 :
121 : /*
122 : * DynamicArrayParser
123 : */
124 : // static
125 : template<class T, class LENGTH_TYPE>
126 9 : void DynamicArrayParser<T, LENGTH_TYPE>::parse(
127 : ::etl::ivector<T>& obj, SomeIpParser& parser, size_t const minLength, bool const isBigEndian)
128 : {
129 9 : obj.clear();
130 :
131 9 : parser.bigEndian();
132 :
133 3 : LENGTH_TYPE const numBytes
134 9 : = static_cast<LENGTH_TYPE>(LengthParserHelper<LENGTH_TYPE>::parseLength(parser));
135 :
136 9 : if (!parser.isGood())
137 : {
138 2 : return;
139 : }
140 :
141 7 : if (isBigEndian == false)
142 : {
143 1 : parser.littleEndian();
144 : }
145 :
146 7 : size_t pos = 0U;
147 7 : size_t const endPosition = parser.getCurrentPosition() + static_cast<size_t>(numBytes);
148 20 : while (parser.getCurrentPosition() < endPosition)
149 : {
150 15 : if (pos >= obj.max_size())
151 : {
152 : // fatal. Trying to read in too many values!
153 1 : obj.clear();
154 1 : parser.setFailure();
155 1 : return;
156 : }
157 :
158 13 : T element{};
159 14 : parser >> element;
160 14 : if (!parser.isGood())
161 : {
162 1 : obj.clear();
163 1 : return;
164 : }
165 13 : obj.push_back(element);
166 :
167 13 : pos++;
168 : }
169 :
170 5 : if (pos < minLength)
171 : {
172 1 : parser.setFailure();
173 1 : obj.clear();
174 : }
175 : }
176 :
177 : /*
178 : * DynamicArraySerializer
179 : */
180 : // static
181 : template<class T, class LENGTH_TYPE>
182 9 : void DynamicArraySerializer<T, LENGTH_TYPE>::serialize(
183 : ::etl::ivector<T> const& obj,
184 : SomeIpSerializer& serializer,
185 : size_t const minLength,
186 : bool const isBigEndian)
187 : {
188 9 : if (!serializer.isGood())
189 : {
190 2 : return;
191 : }
192 :
193 8 : if (obj.size() < minLength)
194 : {
195 1 : serializer.setFailure();
196 1 : return;
197 : }
198 :
199 7 : serializer.bigEndian();
200 :
201 7 : LengthSerializerHelper<LENGTH_TYPE> const helper(serializer);
202 :
203 7 : size_t const length = obj.size();
204 :
205 7 : if (isBigEndian == false)
206 : {
207 1 : serializer.littleEndian();
208 : }
209 : // write out each element
210 27 : for (size_t i = 0U; i < length; ++i)
211 : {
212 20 : serializer << obj[i];
213 : }
214 7 : }
215 :
216 : } // namespace someip
|