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) : base(strName, pTypeElement)
45 {
46 }
47
getFootPrint() const48 uint32_t CArrayParameter::getFootPrint() const
49 {
50 return getSize() * getArrayLength();
51 }
52
53 // Array length
getArrayLength() const54 uint32_t CArrayParameter::getArrayLength() const
55 {
56 return getTypeElement()->getArrayLength();
57 }
58
59 // Element properties
showProperties(string & strResult) const60 void CArrayParameter::showProperties(string& strResult) const
61 {
62 base::showProperties(strResult);
63
64 // Array length
65 strResult += "Array length: ";
66 strResult += CUtility::toString(getArrayLength());
67 strResult += "\n";
68 }
69
70 // XML configuration settings parsing
serializeXmlSettings(CXmlElement & xmlConfigurationSettingsElementContent,CConfigurationAccessContext & configurationAccessContext) const71 bool CArrayParameter::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const
72 {
73 // Check for value space
74 handleValueSpaceAttribute(xmlConfigurationSettingsElementContent, configurationAccessContext);
75
76 // Handle access
77 if (!configurationAccessContext.serializeOut()) {
78
79 // Actually set values to blackboard
80 if (!setValues(0, configurationAccessContext.getBaseOffset(), xmlConfigurationSettingsElementContent.getTextContent(), configurationAccessContext)) {
81
82 return false;
83 }
84 } else {
85
86 // Get string value
87 string strValue;
88
89 // Whole array requested
90 getValues(configurationAccessContext.getBaseOffset(), strValue, configurationAccessContext);
91
92 // Populate value into xml text node
93 xmlConfigurationSettingsElementContent.setTextContent(strValue);
94 }
95
96 // Done
97 return true;
98 }
99
100 // User set/get
accessValue(CPathNavigator & pathNavigator,string & strValue,bool bSet,CParameterAccessContext & parameterAccessContext) const101 bool CArrayParameter::accessValue(CPathNavigator& pathNavigator, string& strValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
102 {
103 uint32_t uiIndex;
104
105 if (!getIndex(pathNavigator, uiIndex, parameterAccessContext)) {
106
107 return false;
108 }
109
110 if (bSet) {
111 // Set
112 if (uiIndex == (uint32_t)-1) {
113
114 // No index provided, start with 0
115 uiIndex = 0;
116 }
117
118 // Actually set values
119 if (!setValues(uiIndex, parameterAccessContext.getBaseOffset(), strValue, parameterAccessContext)) {
120
121 return false;
122 }
123
124 // Synchronize
125 if (!sync(parameterAccessContext)) {
126
127 appendParameterPathToError(parameterAccessContext);
128 return false;
129 }
130 } else {
131 // Get
132 if (uiIndex == (uint32_t)-1) {
133
134 // Whole array requested
135 getValues(parameterAccessContext.getBaseOffset(), strValue, parameterAccessContext);
136
137 } else {
138 // Scalar requested
139 doGetValue(strValue, getOffset() + uiIndex * getSize(), parameterAccessContext);
140 }
141 }
142
143 return true;
144 }
145
146 // Boolean
accessAsBooleanArray(std::vector<bool> & abValues,bool bSet,CParameterAccessContext & parameterAccessContext) const147 bool CArrayParameter::accessAsBooleanArray(std::vector<bool>& abValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
148 {
149 return accessValues(abValues, bSet, parameterAccessContext);
150 }
151
152 // Integer
accessAsIntegerArray(std::vector<uint32_t> & auiValues,bool bSet,CParameterAccessContext & parameterAccessContext) const153 bool CArrayParameter::accessAsIntegerArray(std::vector<uint32_t>& auiValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
154 {
155 return accessValues(auiValues, bSet, parameterAccessContext);
156 }
157
158 // Signed Integer Access
accessAsSignedIntegerArray(std::vector<int32_t> & aiValues,bool bSet,CParameterAccessContext & parameterAccessContext) const159 bool CArrayParameter::accessAsSignedIntegerArray(std::vector<int32_t>& aiValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
160 {
161 return accessValues(aiValues, bSet, parameterAccessContext);
162 }
163
164 // Double Access
accessAsDoubleArray(std::vector<double> & adValues,bool bSet,CParameterAccessContext & parameterAccessContext) const165 bool CArrayParameter::accessAsDoubleArray(std::vector<double>& adValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
166 {
167 return accessValues(adValues, bSet, parameterAccessContext);
168 }
169
170 // String Access
accessAsStringArray(std::vector<string> & astrValues,bool bSet,CParameterAccessContext & parameterAccessContext) const171 bool CArrayParameter::accessAsStringArray(std::vector<string>& astrValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
172 {
173 return accessValues(astrValues, bSet, parameterAccessContext);
174 }
175
176 // Dump
logValue(string & strValue,CErrorContext & errorContext) const177 void CArrayParameter::logValue(string& strValue, CErrorContext& errorContext) const
178 {
179 // Parameter context
180 CParameterAccessContext& parameterAccessContext = static_cast<CParameterAccessContext&>(errorContext);
181
182 // Dump values
183 getValues(0, strValue, parameterAccessContext);
184 }
185
186 // Used for simulation and virtual subsystems
setDefaultValues(CParameterAccessContext & parameterAccessContext) const187 void CArrayParameter::setDefaultValues(CParameterAccessContext& parameterAccessContext) const
188 {
189 // Get default value from type
190 uint32_t uiDefaultValue = static_cast<const CParameterType*>(getTypeElement())->getDefaultValue();
191
192 // Write blackboard
193 CParameterBlackboard* pBlackboard = parameterAccessContext.getParameterBlackboard();
194
195 // Process
196 uint32_t uiValueIndex;
197 uint32_t uiSize = getSize();
198 uint32_t uiOffset = getOffset();
199 bool bSubsystemIsBigEndian = parameterAccessContext.isBigEndianSubsystem();
200 uint32_t uiArrayLength = getArrayLength();
201
202 for (uiValueIndex = 0; uiValueIndex < uiArrayLength; uiValueIndex++) {
203
204 // Beware this code works on little endian architectures only!
205 pBlackboard->writeInteger(&uiDefaultValue, uiSize, uiOffset, bSubsystemIsBigEndian);
206
207 uiOffset += uiSize;
208 }
209 }
210
211 // Index from path
getIndex(CPathNavigator & pathNavigator,uint32_t & uiIndex,CParameterAccessContext & parameterAccessContext) const212 bool CArrayParameter::getIndex(CPathNavigator& pathNavigator, uint32_t& uiIndex, CParameterAccessContext& parameterAccessContext) const
213 {
214 uiIndex = (uint32_t)-1;
215
216 string* pStrChildName = pathNavigator.next();
217
218 if (pStrChildName) {
219
220 // Check index is numeric
221 std::istringstream iss(*pStrChildName);
222
223 iss >> uiIndex;
224
225 if (!iss) {
226
227 parameterAccessContext.setError("Expected numerical expression as last item in " + pathNavigator.getCurrentPath());
228
229 return false;
230 }
231
232 if (uiIndex >= getArrayLength()) {
233 std::ostringstream oss;
234
235 oss << "Provided index out of range (max is " << getArrayLength() - 1 << ")";
236
237 parameterAccessContext.setError(oss.str());
238
239 return false;
240 }
241
242 // Check no other item provided in path
243 pStrChildName = pathNavigator.next();
244
245 if (pStrChildName) {
246
247 // Should be leaf element
248 parameterAccessContext.setError("Path not found: " + pathNavigator.getCurrentPath());
249
250 return false;
251 }
252 }
253
254 return true;
255 }
256
257 // Common set value processing
setValues(uint32_t uiStartIndex,uint32_t uiBaseOffset,const string & strValue,CParameterAccessContext & parameterAccessContext) const258 bool CArrayParameter::setValues(uint32_t uiStartIndex, uint32_t uiBaseOffset, const string& strValue, CParameterAccessContext& parameterAccessContext) const
259 {
260 // Deal with value(s)
261 Tokenizer tok(strValue, Tokenizer::defaultDelimiters + ",");
262
263 std::vector<string> astrValues = tok.split();
264 size_t uiNbValues = astrValues.size();
265
266 // Check number of provided values
267 if (uiNbValues + uiStartIndex > getArrayLength()) {
268
269 // Out of bounds
270 parameterAccessContext.setError("Too many values provided");
271
272 return false;
273 }
274
275 // Process
276 uint32_t uiValueIndex;
277 uint32_t uiSize = getSize();
278 uint32_t uiOffset = getOffset() + uiStartIndex * uiSize - uiBaseOffset;
279
280 for (uiValueIndex = 0; uiValueIndex < uiNbValues; uiValueIndex++) {
281
282 if (!doSetValue(astrValues[uiValueIndex], uiOffset, parameterAccessContext)) {
283
284 // Append parameter path to error
285 parameterAccessContext.appendToError(" " + getPath() + "/" +
286 CUtility::toString(uiValueIndex + uiStartIndex));
287
288 return false;
289 }
290
291 uiOffset += uiSize;
292 }
293 return true;
294 }
295
296 // Common get value processing
getValues(uint32_t uiBaseOffset,string & strValues,CParameterAccessContext & parameterAccessContext) const297 void CArrayParameter::getValues(uint32_t uiBaseOffset, string& strValues, CParameterAccessContext& parameterAccessContext) const
298 {
299 uint32_t uiValueIndex;
300 uint32_t uiSize = getSize();
301 uint32_t uiOffset = getOffset() - uiBaseOffset;
302 uint32_t uiArrayLength = getArrayLength();
303
304 strValues.clear();
305
306 bool bFirst = true;
307
308 for (uiValueIndex = 0; uiValueIndex < uiArrayLength; uiValueIndex++) {
309 string strReadValue;
310
311 doGetValue(strReadValue, uiOffset, parameterAccessContext);
312
313 if (!bFirst) {
314
315 strValues += " ";
316 } else {
317
318 bFirst = false;
319 }
320
321 strValues += strReadValue;
322
323 uiOffset += uiSize;
324 }
325 }
326
327 // Generic Access
328 template <typename type>
accessValues(std::vector<type> & values,bool bSet,CParameterAccessContext & parameterAccessContext) const329 bool CArrayParameter::accessValues(std::vector<type>& values, bool bSet, CParameterAccessContext& parameterAccessContext) const
330 {
331 if (bSet) {
332
333 // Set Value
334 if (!setValues(values, parameterAccessContext)) {
335
336 appendParameterPathToError(parameterAccessContext);
337 return false;
338 }
339 if (!sync(parameterAccessContext)) {
340
341 appendParameterPathToError(parameterAccessContext);
342 return false;
343 }
344 } else {
345 // Get Value
346 if (!getValues(values, parameterAccessContext)) {
347
348 appendParameterPathToError(parameterAccessContext);
349 return false;
350 }
351 }
352 return true;
353 }
354
355 template <typename type>
setValues(const std::vector<type> & values,CParameterAccessContext & parameterAccessContext) const356 bool CArrayParameter::setValues(const std::vector<type>& values, CParameterAccessContext& parameterAccessContext) const
357 {
358 uint32_t uiNbValues = getArrayLength();
359 uint32_t uiValueIndex;
360 uint32_t uiSize = getSize();
361 uint32_t uiOffset = getOffset();
362
363 assert(values.size() == uiNbValues);
364
365 // Process
366 for (uiValueIndex = 0; uiValueIndex < uiNbValues; uiValueIndex++) {
367
368 if (!doSet(values[uiValueIndex], uiOffset, parameterAccessContext)) {
369
370 return false;
371 }
372
373 uiOffset += uiSize;
374 }
375
376 return true;
377 }
378
379 template <typename type>
getValues(std::vector<type> & values,CParameterAccessContext & parameterAccessContext) const380 bool CArrayParameter::getValues(std::vector<type>& values, CParameterAccessContext& parameterAccessContext) const
381 {
382 uint32_t uiNbValues = getArrayLength();
383 uint32_t uiValueIndex;
384 uint32_t uiSize = getSize();
385 uint32_t uiOffset = getOffset();
386
387 values.clear();
388
389 for (uiValueIndex = 0; uiValueIndex < uiNbValues; uiValueIndex++) {
390 type readValue;
391
392 if (!doGet(readValue, uiOffset, parameterAccessContext)) {
393
394 return false;
395 }
396
397 values.push_back(readValue);
398
399 uiOffset += uiSize;
400 }
401 return true;
402 }
403
404 template <typename type>
doSet(type value,uint32_t uiOffset,CParameterAccessContext & parameterAccessContext) const405 bool CArrayParameter::doSet(type value, uint32_t uiOffset, CParameterAccessContext& parameterAccessContext) const
406 {
407 uint32_t uiData;
408
409 if (!static_cast<const CParameterType*>(getTypeElement())->toBlackboard(value, uiData, parameterAccessContext)) {
410
411 return false;
412 }
413 // Write blackboard
414 CParameterBlackboard* pBlackboard = parameterAccessContext.getParameterBlackboard();
415
416 // Beware this code works on little endian architectures only!
417 pBlackboard->writeInteger(&uiData, getSize(), uiOffset, parameterAccessContext.isBigEndianSubsystem());
418
419 return true;
420 }
421
422 template <typename type>
doGet(type & value,uint32_t uiOffset,CParameterAccessContext & parameterAccessContext) const423 bool CArrayParameter::doGet(type& value, uint32_t uiOffset, CParameterAccessContext& parameterAccessContext) const
424 {
425 uint32_t uiData = 0;
426
427 // Read blackboard
428 const CParameterBlackboard* pBlackboard = parameterAccessContext.getParameterBlackboard();
429
430 // Beware this code works on little endian architectures only!
431 pBlackboard->readInteger(&uiData, getSize(), uiOffset, parameterAccessContext.isBigEndianSubsystem());
432
433 return static_cast<const CParameterType*>(getTypeElement())->fromBlackboard(value, uiData, parameterAccessContext);
434 }
435
436