1 /*
2 * Copyright (c) 2011-2015, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 #include "ArrayParameter.h"
31 #include <sstream> // for istringstream
32 #include "Tokenizer.h"
33 #include "ParameterType.h"
34 #include "ParameterAccessContext.h"
35 #include "ConfigurationAccessContext.h"
36 #include "ParameterBlackboard.h"
37 #include "Utility.h"
38 #include <assert.h>
39
40 #define base CParameter
41
42 using std::string;
43
CArrayParameter(const string & strName,const CTypeElement * pTypeElement)44 CArrayParameter::CArrayParameter(const string &strName, const CTypeElement *pTypeElement)
45 : base(strName, pTypeElement)
46 {
47 }
48
getFootPrint() const49 size_t CArrayParameter::getFootPrint() const
50 {
51 return getSize() * getArrayLength();
52 }
53
54 // Array length
getArrayLength() const55 size_t CArrayParameter::getArrayLength() const
56 {
57 return getTypeElement()->getArrayLength();
58 }
59
60 // Element properties
showProperties(string & strResult) const61 void CArrayParameter::showProperties(string &strResult) const
62 {
63 base::showProperties(strResult);
64
65 // Array length
66 strResult += "Array length: ";
67 strResult += std::to_string(getArrayLength());
68 strResult += "\n";
69 }
70
71 // User set/get
accessValue(CPathNavigator & pathNavigator,string & strValue,bool bSet,CParameterAccessContext & parameterAccessContext) const72 bool CArrayParameter::accessValue(CPathNavigator &pathNavigator, string &strValue, bool bSet,
73 CParameterAccessContext ¶meterAccessContext) const
74 {
75 size_t index;
76
77 if (!getIndex(pathNavigator, index, parameterAccessContext)) {
78
79 return false;
80 }
81
82 if (bSet) {
83 // Set
84 if (index == (size_t)-1) {
85
86 // No index provided, start with 0
87 index = 0;
88 }
89
90 // Actually set values
91 if (!setValues(index, getOffset() - parameterAccessContext.getBaseOffset(), strValue,
92 parameterAccessContext)) {
93 return false;
94 }
95
96 // Synchronize
97 if (!sync(parameterAccessContext)) {
98
99 appendParameterPathToError(parameterAccessContext);
100 return false;
101 }
102 } else {
103 // Get
104 if (index == (size_t)-1) {
105
106 // Whole array requested
107 strValue = getValues(getOffset() - parameterAccessContext.getBaseOffset(),
108 parameterAccessContext);
109
110 } else {
111 // Scalar requested
112 CParameter::doGetValue(strValue, getOffset() + index * getSize(),
113 parameterAccessContext);
114 }
115 }
116
117 return true;
118 }
119
120 /// Actual parameter access
121 // String access
doSetValue(const string & value,size_t offset,CParameterAccessContext & parameterAccessContext) const122 bool CArrayParameter::doSetValue(const string &value, size_t offset,
123 CParameterAccessContext ¶meterAccessContext) const
124 {
125 return setValues(0, offset, value, parameterAccessContext);
126 }
127
doGetValue(string & value,size_t offset,CParameterAccessContext & parameterAccessContext) const128 void CArrayParameter::doGetValue(string &value, size_t offset,
129 CParameterAccessContext ¶meterAccessContext) const
130 {
131 // Whole array requested
132 value = getValues(offset, parameterAccessContext);
133 }
134
135 // Boolean
access(std::vector<bool> & abValues,bool bSet,CParameterAccessContext & parameterAccessContext) const136 bool CArrayParameter::access(std::vector<bool> &abValues, bool bSet,
137 CParameterAccessContext ¶meterAccessContext) const
138 {
139 return accessValues(abValues, bSet, parameterAccessContext);
140 }
141
142 // Integer
access(std::vector<uint32_t> & auiValues,bool bSet,CParameterAccessContext & parameterAccessContext) const143 bool CArrayParameter::access(std::vector<uint32_t> &auiValues, bool bSet,
144 CParameterAccessContext ¶meterAccessContext) const
145 {
146 return accessValues(auiValues, bSet, parameterAccessContext);
147 }
148
149 // Signed Integer Access
access(std::vector<int32_t> & aiValues,bool bSet,CParameterAccessContext & parameterAccessContext) const150 bool CArrayParameter::access(std::vector<int32_t> &aiValues, bool bSet,
151 CParameterAccessContext ¶meterAccessContext) const
152 {
153 return accessValues(aiValues, bSet, parameterAccessContext);
154 }
155
156 // Double Access
access(std::vector<double> & adValues,bool bSet,CParameterAccessContext & parameterAccessContext) const157 bool CArrayParameter::access(std::vector<double> &adValues, bool bSet,
158 CParameterAccessContext ¶meterAccessContext) const
159 {
160 return accessValues(adValues, bSet, parameterAccessContext);
161 }
162
163 // String Access
access(std::vector<string> & astrValues,bool bSet,CParameterAccessContext & parameterAccessContext) const164 bool CArrayParameter::access(std::vector<string> &astrValues, bool bSet,
165 CParameterAccessContext ¶meterAccessContext) const
166 {
167 return accessValues(astrValues, bSet, parameterAccessContext);
168 }
169
170 // Dump
logValue(CParameterAccessContext & context) const171 string CArrayParameter::logValue(CParameterAccessContext &context) const
172 {
173 // Dump values
174 return getValues(0, context);
175 }
176
177 // Used for simulation and virtual subsystems
setDefaultValues(CParameterAccessContext & parameterAccessContext) const178 void CArrayParameter::setDefaultValues(CParameterAccessContext ¶meterAccessContext) const
179 {
180 // Get default value from type
181 uint32_t uiDefaultValue =
182 static_cast<const CParameterType *>(getTypeElement())->getDefaultValue();
183
184 // Write blackboard
185 CParameterBlackboard *pBlackboard = parameterAccessContext.getParameterBlackboard();
186
187 // Process
188 size_t valueIndex;
189 size_t size = getSize();
190 size_t offset = getOffset();
191 size_t arrayLength = getArrayLength();
192
193 for (valueIndex = 0; valueIndex < arrayLength; valueIndex++) {
194
195 // Beware this code works on little endian architectures only!
196 pBlackboard->writeInteger(&uiDefaultValue, size, offset);
197
198 offset += size;
199 }
200 }
201
202 // Index from path
getIndex(CPathNavigator & pathNavigator,size_t & index,CParameterAccessContext & parameterAccessContext) const203 bool CArrayParameter::getIndex(CPathNavigator &pathNavigator, size_t &index,
204 CParameterAccessContext ¶meterAccessContext) const
205 {
206 index = (size_t)-1;
207
208 string *pStrChildName = pathNavigator.next();
209
210 if (pStrChildName) {
211
212 // Check index is numeric
213 std::istringstream iss(*pStrChildName);
214
215 iss >> index;
216
217 if (!iss) {
218
219 parameterAccessContext.setError("Expected numerical expression as last item in " +
220 pathNavigator.getCurrentPath());
221
222 return false;
223 }
224
225 if (index >= getArrayLength()) {
226 std::ostringstream oss;
227
228 oss << "Provided index out of range (max is " << getArrayLength() - 1 << ")";
229
230 parameterAccessContext.setError(oss.str());
231
232 return false;
233 }
234
235 // Check no other item provided in path
236 pStrChildName = pathNavigator.next();
237
238 if (pStrChildName) {
239
240 // Should be leaf element
241 parameterAccessContext.setError("Path not found: " + pathNavigator.getCurrentPath());
242
243 return false;
244 }
245 }
246
247 return true;
248 }
249
250 // Common set value processing
setValues(size_t uiStartIndex,size_t offset,const string & strValue,CParameterAccessContext & parameterAccessContext) const251 bool CArrayParameter::setValues(size_t uiStartIndex, size_t offset, const string &strValue,
252 CParameterAccessContext ¶meterAccessContext) const
253 {
254 // Deal with value(s)
255 Tokenizer tok(strValue, Tokenizer::defaultDelimiters + ",");
256
257 std::vector<string> astrValues = tok.split();
258 size_t nbValues = astrValues.size();
259
260 // Check number of provided values
261 if (nbValues + uiStartIndex > getArrayLength()) {
262
263 // Out of bounds
264 parameterAccessContext.setError("Too many values provided");
265
266 return false;
267 }
268
269 // Process
270 size_t valueIndex;
271 size_t size = getSize();
272 offset += uiStartIndex * size;
273
274 for (valueIndex = 0; valueIndex < nbValues; valueIndex++) {
275
276 if (!doSet(astrValues[valueIndex], offset, parameterAccessContext)) {
277
278 // Append parameter path to error
279 parameterAccessContext.appendToError(" " + getPath() + "/" +
280 std::to_string(valueIndex + uiStartIndex));
281
282 return false;
283 }
284
285 offset += size;
286 }
287 return true;
288 }
289
290 // Common get value processing
getValues(size_t offset,CParameterAccessContext & parameterAccessContext) const291 string CArrayParameter::getValues(size_t offset,
292 CParameterAccessContext ¶meterAccessContext) const
293 {
294 size_t size = getSize();
295 size_t arrayLength = getArrayLength();
296
297 string output;
298
299 bool bFirst = true;
300
301 for (size_t valueIndex = 0; valueIndex < arrayLength; valueIndex++) {
302 string strReadValue;
303
304 doGet(strReadValue, offset, parameterAccessContext);
305
306 if (!bFirst) {
307
308 output += " ";
309 } else {
310
311 bFirst = false;
312 }
313
314 output += strReadValue;
315
316 offset += size;
317 }
318
319 return output;
320 }
321
322 // Generic Access
323 template <typename type>
accessValues(std::vector<type> & values,bool bSet,CParameterAccessContext & parameterAccessContext) const324 bool CArrayParameter::accessValues(std::vector<type> &values, bool bSet,
325 CParameterAccessContext ¶meterAccessContext) const
326 {
327 if (bSet) {
328
329 // Set Value
330 if (!setValues(values, parameterAccessContext)) {
331
332 appendParameterPathToError(parameterAccessContext);
333 return false;
334 }
335 if (!sync(parameterAccessContext)) {
336
337 appendParameterPathToError(parameterAccessContext);
338 return false;
339 }
340 } else {
341 // Get Value
342 if (!getValues(values, parameterAccessContext)) {
343
344 appendParameterPathToError(parameterAccessContext);
345 return false;
346 }
347 }
348 return true;
349 }
350
351 template <typename type>
setValues(const std::vector<type> & values,CParameterAccessContext & parameterAccessContext) const352 bool CArrayParameter::setValues(const std::vector<type> &values,
353 CParameterAccessContext ¶meterAccessContext) const
354 {
355 size_t nbValues = getArrayLength();
356 size_t size = getSize();
357 size_t offset = getOffset();
358
359 assert(values.size() == nbValues);
360
361 // Process
362 for (size_t valueIndex = 0; valueIndex < nbValues; valueIndex++) {
363
364 if (!doSet(values[valueIndex], offset, parameterAccessContext)) {
365
366 return false;
367 }
368
369 offset += size;
370 }
371
372 return true;
373 }
374
375 template <typename type>
getValues(std::vector<type> & values,CParameterAccessContext & parameterAccessContext) const376 bool CArrayParameter::getValues(std::vector<type> &values,
377 CParameterAccessContext ¶meterAccessContext) const
378 {
379 size_t nbValues = getArrayLength();
380 size_t size = getSize();
381 size_t offset = getOffset();
382
383 values.clear();
384
385 for (size_t valueIndex = 0; valueIndex < nbValues; valueIndex++) {
386 type readValue;
387
388 if (!doGet(readValue, offset, parameterAccessContext)) {
389
390 return false;
391 }
392
393 values.push_back(readValue);
394
395 offset += size;
396 }
397 return true;
398 }
399
400 template <typename type>
doSet(type value,size_t offset,CParameterAccessContext & parameterAccessContext) const401 bool CArrayParameter::doSet(type value, size_t offset,
402 CParameterAccessContext ¶meterAccessContext) const
403 {
404 uint32_t uiData;
405
406 if (!static_cast<const CParameterType *>(getTypeElement())
407 ->toBlackboard(value, uiData, parameterAccessContext)) {
408
409 return false;
410 }
411 // Write blackboard
412 CParameterBlackboard *pBlackboard = parameterAccessContext.getParameterBlackboard();
413
414 // Beware this code works on little endian architectures only!
415 pBlackboard->writeInteger(&uiData, getSize(), offset);
416
417 return true;
418 }
419
420 template <typename type>
doGet(type & value,size_t offset,CParameterAccessContext & parameterAccessContext) const421 bool CArrayParameter::doGet(type &value, size_t offset,
422 CParameterAccessContext ¶meterAccessContext) const
423 {
424 uint32_t uiData = 0;
425
426 // Read blackboard
427 const CParameterBlackboard *pBlackboard = parameterAccessContext.getParameterBlackboard();
428
429 // Beware this code works on little endian architectures only!
430 pBlackboard->readInteger(&uiData, getSize(), offset);
431
432 return static_cast<const CParameterType *>(getTypeElement())
433 ->fromBlackboard(value, uiData, parameterAccessContext);
434 }
435