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 : /**
12 : * Contains
13 : */
14 :
15 : #include "someip/EtlString.h"
16 :
17 : namespace someip
18 : {
19 : // protected
20 : // static
21 18 : bool StringParser::parseBom(SomeIpParser& parser, char const* const bom, uint32_t const bomLength)
22 : {
23 18 : char ch = '\0';
24 :
25 53 : for (uint32_t i = 0U; i < bomLength; ++i)
26 : {
27 37 : parser >> ch;
28 37 : if ((bom != nullptr) && (ch != bom[i]))
29 : {
30 2 : parser.setFailure();
31 2 : return false;
32 : }
33 : }
34 :
35 16 : return true;
36 : }
37 :
38 : // protected
39 : // static
40 15 : void StringParser::readAndSkipNulls(SomeIpParser& parser, ::etl::istring& str, uint32_t const nulls)
41 : {
42 15 : char ch = '\0';
43 :
44 : // read in nulls
45 33 : for (uint32_t i = 0U; i < nulls; ++i)
46 : {
47 20 : parser >> ch;
48 20 : if (ch != '\0')
49 : {
50 2 : parser.setFailure();
51 2 : str.clear();
52 2 : break;
53 : }
54 : }
55 15 : }
56 :
57 : // protected
58 : // static
59 12 : void StringSerializer::writeStringBytes(
60 : SomeIpSerializer& serializer,
61 : ::etl::istring const& str,
62 : Encoding const encoding,
63 : uint32_t const nulls)
64 : {
65 : // write out the BOM
66 12 : char const* const bom = ::someip::internal::EncodingHelper::bom(encoding);
67 12 : if (bom != nullptr)
68 : {
69 11 : uint32_t const bomLength = ::someip::internal::EncodingHelper::encodingLength(encoding);
70 :
71 34 : for (uint32_t i = 0U; i < bomLength; ++i)
72 : {
73 23 : serializer << bom[i];
74 : }
75 :
76 11 : uint32_t const length = static_cast<uint32_t>(str.size());
77 :
78 : // write out each element
79 68 : for (uint32_t i = 0U; i < length; ++i)
80 : {
81 57 : serializer << str[i];
82 : }
83 :
84 : // pad with null terminators
85 34 : for (uint32_t i = 0U; i < nulls; ++i)
86 : {
87 23 : serializer << '\0';
88 : }
89 : }
90 12 : }
91 :
92 : /*
93 : * StaticStringParser
94 : */
95 : // private
96 : // static
97 2 : void StaticStringParser::readUtf8Bytes(
98 : SomeIpParser& parser, ::etl::istring& str, uint32_t const terminationLength)
99 : {
100 2 : char ch = '\0';
101 :
102 2 : size_t const strMaxSize = str.max_size();
103 13 : for (size_t i = 0U; i < (strMaxSize - 1U); ++i)
104 : {
105 12 : parser >> ch;
106 12 : if (ch == '\0')
107 : {
108 1 : break;
109 : }
110 11 : str += ch;
111 : }
112 :
113 2 : if ((strMaxSize - 1U) == str.size())
114 : {
115 1 : readAndSkipNulls(parser, str, terminationLength);
116 : }
117 : else
118 : {
119 1 : readAndSkipNulls(
120 1 : parser, str, static_cast<uint32_t>(strMaxSize - str.size()) + (terminationLength - 2U));
121 : }
122 2 : }
123 :
124 : // private
125 : // static
126 8 : void StaticStringParser::readUtf16Bytes(
127 : SomeIpParser& parser, ::etl::istring& str, uint32_t const terminationLength)
128 : {
129 : // for UTF16 we look for 2 null terminators
130 8 : char ch = '\0';
131 8 : char ch2 = '\0';
132 :
133 8 : size_t const strMaxSize = str.max_size();
134 54 : for (size_t i = 0U; i < (strMaxSize - 1U); ++i)
135 : {
136 48 : parser >> ch;
137 48 : if (ch == '\0')
138 : {
139 3 : parser >> ch2;
140 3 : if (ch2 == '\0')
141 : {
142 2 : break;
143 : }
144 :
145 1 : ++i;
146 :
147 1 : str += ch;
148 1 : str += ch2;
149 : }
150 : else
151 : {
152 45 : str += ch;
153 : }
154 : }
155 :
156 8 : if ((strMaxSize - 1U) == str.size())
157 : {
158 6 : readAndSkipNulls(parser, str, terminationLength);
159 : }
160 : else
161 : {
162 2 : readAndSkipNulls(
163 2 : parser, str, static_cast<uint32_t>(strMaxSize - str.size()) + (terminationLength - 3U));
164 : }
165 8 : }
166 :
167 : // static
168 14 : void StaticStringParser::readString(
169 : SomeIpParser& parser, ::etl::istring& str, Encoding const encoding)
170 : {
171 14 : if (!parser.isGood())
172 : {
173 1 : return;
174 : }
175 :
176 13 : str.clear();
177 :
178 13 : char const* const bom = ::someip::internal::EncodingHelper::bom(encoding);
179 13 : uint32_t const bomLength = ::someip::internal::EncodingHelper::encodingLength(encoding);
180 : uint32_t const terminationLength
181 13 : = ::someip::internal::EncodingHelper::terminationLength(encoding);
182 :
183 : // make sure we have enough bytes!
184 13 : if (parser.bytesAvailable() < (((bomLength + str.max_size()) - 1U) + terminationLength))
185 : {
186 2 : parser.setFailure();
187 2 : return;
188 : }
189 :
190 : // read in the BOM
191 11 : if (!parseBom(parser, bom, bomLength))
192 : {
193 1 : return;
194 : }
195 :
196 10 : if (encoding == Encoding::SOMEIP_ENCODING_UTF8)
197 : {
198 2 : readUtf8Bytes(parser, str, terminationLength);
199 : }
200 : else
201 : {
202 8 : readUtf16Bytes(parser, str, terminationLength);
203 : }
204 : }
205 :
206 : /*
207 : * StaticStringSerializer
208 : */
209 : // static
210 11 : void StaticStringSerializer::writeString(
211 : SomeIpSerializer& serializer, ::etl::istring const& str, Encoding const encoding)
212 : {
213 11 : if (!serializer.isGood())
214 : {
215 1 : return;
216 : }
217 :
218 : uint32_t const terminationLength
219 10 : = ::someip::internal::EncodingHelper::terminationLength(encoding);
220 : uint32_t const nulls
221 10 : = static_cast<uint32_t>((str.max_size() - str.size()) - 1U) + terminationLength;
222 :
223 10 : writeStringBytes(serializer, str, encoding, nulls);
224 : }
225 :
226 : /*
227 : * DynamicStringParserBase
228 : */
229 7 : void DynamicStringParserBase::parseStringBytes(
230 : SomeIpParser& parser, ::etl::istring& str, Encoding const encoding, uint32_t const numBytes)
231 : {
232 7 : char const* const bom = ::someip::internal::EncodingHelper::bom(encoding);
233 7 : uint32_t const bomLength = ::someip::internal::EncodingHelper::encodingLength(encoding);
234 : uint32_t const terminationLength
235 7 : = ::someip::internal::EncodingHelper::terminationLength(encoding);
236 :
237 : // verify we have the correct BOM
238 7 : if (!parseBom(parser, bom, bomLength))
239 : {
240 2 : return;
241 : }
242 :
243 6 : uint32_t const usefulBytes = numBytes - bomLength - terminationLength;
244 :
245 6 : if (usefulBytes >= str.max_size())
246 : {
247 1 : parser.setFailure();
248 1 : return;
249 : }
250 :
251 5 : char ch = '\0';
252 :
253 34 : for (size_t i = 0U; i < usefulBytes; ++i)
254 : {
255 29 : parser >> ch;
256 29 : str += ch;
257 : }
258 :
259 5 : readAndSkipNulls(parser, str, terminationLength);
260 : }
261 :
262 : } // namespace someip
|