blob: ec69191d799991d6e90c7ae306b8db1716e15aea [file] [log] [blame]
David Wagnerb76c9d62014-02-05 18:30:24 +01001/*
2 * Copyright (c) 2011-2014, 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.
Patrick Benavoli68a91282011-08-31 11:23:23 +020029 */
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"
Patrick Benavoli065264a2011-11-20 15:46:41 +010037#include <assert.h>
Patrick Benavoli68a91282011-08-31 11:23:23 +020038
39#define base CParameter
40
Sebastien Gonzalved9526492014-02-20 22:28:03 +010041using std::string;
42
Patrick Benavoli2ecf9002011-08-31 11:23:24 +020043CArrayParameter::CArrayParameter(const string& strName, const CTypeElement* pTypeElement) : base(strName, pTypeElement)
Patrick Benavoli68a91282011-08-31 11:23:23 +020044{
45}
46
47uint32_t CArrayParameter::getFootPrint() const
48{
Patrick Benavoli2ecf9002011-08-31 11:23:24 +020049 return getSize() * getArrayLength();
50}
51
52// Array length
53uint32_t CArrayParameter::getArrayLength() const
54{
55 return getTypeElement()->getArrayLength();
56}
57
58// Element properties
59void CArrayParameter::showProperties(string& strResult) const
60{
61 base::showProperties(strResult);
62
63 // Array length
64 strResult += "Array length: ";
65 strResult += toString(getArrayLength());
66 strResult += "\n";
Patrick Benavoli68a91282011-08-31 11:23:23 +020067}
68
69// XML configuration settings parsing
Patrick Benavoli6ba361d2011-08-31 11:23:24 +020070bool CArrayParameter::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +020071{
72 // Check for value space
Patrick Benavoli6ba361d2011-08-31 11:23:24 +020073 handleValueSpaceAttribute(xmlConfigurationSettingsElementContent, configurationAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +020074
75 // Handle access
76 if (!configurationAccessContext.serializeOut()) {
77
78 // Actually set values to blackboard
Patrick Benavoli6ba361d2011-08-31 11:23:24 +020079 if (!setValues(0, configurationAccessContext.getBaseOffset(), xmlConfigurationSettingsElementContent.getTextContent(), configurationAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +020080
81 return false;
82 }
83 } else {
84
85 // Get string value
86 string strValue;
87
88 // Whole array requested
89 getValues(configurationAccessContext.getBaseOffset(), strValue, configurationAccessContext);
90
91 // Populate value into xml text node
Patrick Benavoli6ba361d2011-08-31 11:23:24 +020092 xmlConfigurationSettingsElementContent.setTextContent(strValue);
Patrick Benavoli68a91282011-08-31 11:23:23 +020093 }
94
95 // Done
96 return true;
97}
98
99// User set/get
Patrick Benavoli065264a2011-11-20 15:46:41 +0100100bool CArrayParameter::accessValue(CPathNavigator& pathNavigator, string& strValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200101{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200102 uint32_t uiIndex;
103
Patrick Benavoli065264a2011-11-20 15:46:41 +0100104 if (!getIndex(pathNavigator, uiIndex, parameterAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200105
106 return false;
107 }
Patrick Benavoli4bed9212011-10-27 14:18:00 +0200108
Patrick Benavoli065264a2011-11-20 15:46:41 +0100109 if (bSet) {
110 // Set
111 if (uiIndex == (uint32_t)-1) {
Patrick Benavoli4bed9212011-10-27 14:18:00 +0200112
Patrick Benavoli065264a2011-11-20 15:46:41 +0100113 // No index provided, start with 0
114 uiIndex = 0;
115 }
Patrick Benavoli4bed9212011-10-27 14:18:00 +0200116
Patrick Benavoli065264a2011-11-20 15:46:41 +0100117 // Actually set values
Frédéric Boisnard6bc17c02013-02-25 15:55:47 +0100118 if (!setValues(uiIndex, parameterAccessContext.getBaseOffset(), strValue, parameterAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200119
Patrick Benavoli065264a2011-11-20 15:46:41 +0100120 return false;
121 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200122
Patrick Benavoli065264a2011-11-20 15:46:41 +0100123 // Synchronize
Francois Gaffie8ab72932014-04-07 13:46:05 +0200124 if (!sync(parameterAccessContext)) {
Patrick Benavoli065264a2011-11-20 15:46:41 +0100125
Francois Gaffiea1258f42014-04-07 13:47:48 +0200126 appendParameterPathToError(parameterAccessContext);
Patrick Benavoli065264a2011-11-20 15:46:41 +0100127 return false;
128 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200129 } else {
Patrick Benavoli065264a2011-11-20 15:46:41 +0100130 // Get
131 if (uiIndex == (uint32_t)-1) {
132
133 // Whole array requested
Frédéric Boisnard6bc17c02013-02-25 15:55:47 +0100134 getValues(parameterAccessContext.getBaseOffset(), strValue, parameterAccessContext);
Patrick Benavoli065264a2011-11-20 15:46:41 +0100135
136 } else {
137 // Scalar requested
138 doGetValue(strValue, getOffset() + uiIndex * getSize(), parameterAccessContext);
139 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200140 }
141
142 return true;
143}
144
Patrick Benavoli065264a2011-11-20 15:46:41 +0100145// Boolean
Sebastien Gonzalved9526492014-02-20 22:28:03 +0100146bool CArrayParameter::accessAsBooleanArray(std::vector<bool>& abValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli065264a2011-11-20 15:46:41 +0100147{
148 return accessValues(abValues, bSet, parameterAccessContext);
149}
150
151// Integer
Sebastien Gonzalved9526492014-02-20 22:28:03 +0100152bool CArrayParameter::accessAsIntegerArray(std::vector<uint32_t>& auiValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli065264a2011-11-20 15:46:41 +0100153{
154 return accessValues(auiValues, bSet, parameterAccessContext);
155}
156
157// Signed Integer Access
Sebastien Gonzalved9526492014-02-20 22:28:03 +0100158bool CArrayParameter::accessAsSignedIntegerArray(std::vector<int32_t>& aiValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli065264a2011-11-20 15:46:41 +0100159{
160 return accessValues(aiValues, bSet, parameterAccessContext);
161}
162
163// Double Access
Sebastien Gonzalved9526492014-02-20 22:28:03 +0100164bool CArrayParameter::accessAsDoubleArray(std::vector<double>& adValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli065264a2011-11-20 15:46:41 +0100165{
166 return accessValues(adValues, bSet, parameterAccessContext);
167}
168
169// String Access
Sebastien Gonzalved9526492014-02-20 22:28:03 +0100170bool CArrayParameter::accessAsStringArray(std::vector<string>& astrValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli065264a2011-11-20 15:46:41 +0100171{
172 return accessValues(astrValues, bSet, parameterAccessContext);
173}
174
175// Dump
Patrick Benavoli68a91282011-08-31 11:23:23 +0200176void CArrayParameter::logValue(string& strValue, CErrorContext& errorContext) const
177{
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200178 // Parameter context
Patrick Benavoli065264a2011-11-20 15:46:41 +0100179 CParameterAccessContext& parameterAccessContext = static_cast<CParameterAccessContext&>(errorContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200180
181 // Dump values
Patrick Benavoli065264a2011-11-20 15:46:41 +0100182 getValues(0, strValue, parameterAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200183}
184
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +0100185// Used for simulation and virtual subsystems
Patrick Benavoli68a91282011-08-31 11:23:23 +0200186void CArrayParameter::setDefaultValues(CParameterAccessContext& parameterAccessContext) const
187{
188 // Get default value from type
189 uint32_t uiDefaultValue = static_cast<const CParameterType*>(getTypeElement())->getDefaultValue();
190
191 // Write blackboard
192 CParameterBlackboard* pBlackboard = parameterAccessContext.getParameterBlackboard();
193
194 // Process
195 uint32_t uiValueIndex;
196 uint32_t uiSize = getSize();
197 uint32_t uiOffset = getOffset();
198 bool bSubsystemIsBigEndian = parameterAccessContext.isBigEndianSubsystem();
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200199 uint32_t uiArrayLength = getArrayLength();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200200
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200201 for (uiValueIndex = 0; uiValueIndex < uiArrayLength; uiValueIndex++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200202
203 // Beware this code works on little endian architectures only!
Patrick Benavoli1352ae52011-10-21 16:48:04 +0200204 pBlackboard->writeInteger(&uiDefaultValue, uiSize, uiOffset, bSubsystemIsBigEndian);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200205
206 uiOffset += uiSize;
207 }
208}
209
210// Index from path
Patrick Benavoli065264a2011-11-20 15:46:41 +0100211bool CArrayParameter::getIndex(CPathNavigator& pathNavigator, uint32_t& uiIndex, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200212{
213 uiIndex = (uint32_t)-1;
214
215 string* pStrChildName = pathNavigator.next();
216
217 if (pStrChildName) {
218
219 // Check index is numeric
Sebastien Gonzalved9526492014-02-20 22:28:03 +0100220 std::istringstream iss(*pStrChildName);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200221
222 iss >> uiIndex;
223
224 if (!iss) {
225
Patrick Benavoli065264a2011-11-20 15:46:41 +0100226 parameterAccessContext.setError("Expected numerical expression as last item in " + pathNavigator.getCurrentPath());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200227
228 return false;
229 }
230
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200231 if (uiIndex >= getArrayLength()) {
Sebastien Gonzalved9526492014-02-20 22:28:03 +0100232 std::ostringstream oss;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200233
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200234 oss << "Provided index out of range (max is " << getArrayLength() - 1 << ")";
Patrick Benavoli68a91282011-08-31 11:23:23 +0200235
Patrick Benavoli065264a2011-11-20 15:46:41 +0100236 parameterAccessContext.setError(oss.str());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200237
238 return false;
239 }
240
241 // Check no other item provided in path
242 pStrChildName = pathNavigator.next();
243
244 if (pStrChildName) {
245
246 // Should be leaf element
Patrick Benavoli065264a2011-11-20 15:46:41 +0100247 parameterAccessContext.setError("Path not found: " + pathNavigator.getCurrentPath());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200248
249 return false;
250 }
251 }
252
253 return true;
254}
255
256// Common set value processing
Patrick Benavoli065264a2011-11-20 15:46:41 +0100257bool CArrayParameter::setValues(uint32_t uiStartIndex, uint32_t uiBaseOffset, const string& strValue, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200258{
259 // Deal with value(s)
David Wagner99b3e852015-03-19 16:35:47 +0100260 Tokenizer tok(strValue, Tokenizer::defaultDelimiters + ",");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200261
Sebastien Gonzalved9526492014-02-20 22:28:03 +0100262 std::vector<string> astrValues = tok.split();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200263 uint32_t uiNbValues = astrValues.size();
264
265 // Check number of provided values
Patrick Benavoli065264a2011-11-20 15:46:41 +0100266 if (uiNbValues + uiStartIndex > getArrayLength()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200267
268 // Out of bounds
Patrick Benavoli065264a2011-11-20 15:46:41 +0100269 parameterAccessContext.setError("Too many values provided");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200270
271 return false;
272 }
273
274 // Process
275 uint32_t uiValueIndex;
276 uint32_t uiSize = getSize();
277 uint32_t uiOffset = getOffset() + uiStartIndex * uiSize - uiBaseOffset;
278
279 for (uiValueIndex = 0; uiValueIndex < uiNbValues; uiValueIndex++) {
280
Patrick Benavoli065264a2011-11-20 15:46:41 +0100281 if (!doSetValue(astrValues[uiValueIndex], uiOffset, parameterAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200282
283 // Append parameter path to error
Patrick Benavoli065264a2011-11-20 15:46:41 +0100284 parameterAccessContext.appendToError(" " + getPath() + "/" + toString(uiValueIndex + uiStartIndex));
Patrick Benavoli68a91282011-08-31 11:23:23 +0200285
286 return false;
287 }
288
289 uiOffset += uiSize;
290 }
291 return true;
292}
293
294// Common get value processing
Patrick Benavoli065264a2011-11-20 15:46:41 +0100295void CArrayParameter::getValues(uint32_t uiBaseOffset, string& strValues, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200296{
297 uint32_t uiValueIndex;
298 uint32_t uiSize = getSize();
299 uint32_t uiOffset = getOffset() - uiBaseOffset;
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200300 uint32_t uiArrayLength = getArrayLength();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200301
Patrick Benavoli4bed9212011-10-27 14:18:00 +0200302 strValues.clear();
303
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200304 bool bFirst = true;
305
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200306 for (uiValueIndex = 0; uiValueIndex < uiArrayLength; uiValueIndex++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200307 string strReadValue;
308
Patrick Benavoli065264a2011-11-20 15:46:41 +0100309 doGetValue(strReadValue, uiOffset, parameterAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200310
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200311 if (!bFirst) {
312
313 strValues += " ";
314 } else {
315
316 bFirst = false;
317 }
318
319 strValues += strReadValue;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200320
321 uiOffset += uiSize;
322 }
323}
Patrick Benavoli065264a2011-11-20 15:46:41 +0100324
325// Generic Access
326template <typename type>
Sebastien Gonzalved9526492014-02-20 22:28:03 +0100327bool CArrayParameter::accessValues(std::vector<type>& values, bool bSet, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli065264a2011-11-20 15:46:41 +0100328{
Patrick Benavoli065264a2011-11-20 15:46:41 +0100329 if (bSet) {
330
Francois Gaffie8ab72932014-04-07 13:46:05 +0200331 // Set Value
332 if (!setValues(values, parameterAccessContext)) {
Patrick Benavoli065264a2011-11-20 15:46:41 +0100333
Francois Gaffiea1258f42014-04-07 13:47:48 +0200334 appendParameterPathToError(parameterAccessContext);
Francois Gaffie8ab72932014-04-07 13:46:05 +0200335 return false;
336 }
337 if (!sync(parameterAccessContext)) {
Patrick Benavoli065264a2011-11-20 15:46:41 +0100338
Francois Gaffiea1258f42014-04-07 13:47:48 +0200339 appendParameterPathToError(parameterAccessContext);
Francois Gaffie8ab72932014-04-07 13:46:05 +0200340 return false;
Patrick Benavoli065264a2011-11-20 15:46:41 +0100341 }
342 } else {
Francois Gaffie8ab72932014-04-07 13:46:05 +0200343 // Get Value
344 if (!getValues(values, parameterAccessContext)) {
Patrick Benavoli065264a2011-11-20 15:46:41 +0100345
Francois Gaffiea1258f42014-04-07 13:47:48 +0200346 appendParameterPathToError(parameterAccessContext);
Francois Gaffie8ab72932014-04-07 13:46:05 +0200347 return false;
348 }
Patrick Benavoli065264a2011-11-20 15:46:41 +0100349 }
Francois Gaffie8ab72932014-04-07 13:46:05 +0200350 return true;
Patrick Benavoli065264a2011-11-20 15:46:41 +0100351}
352
353template <typename type>
Sebastien Gonzalved9526492014-02-20 22:28:03 +0100354bool CArrayParameter::setValues(const std::vector<type>& values, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli065264a2011-11-20 15:46:41 +0100355{
356 uint32_t uiNbValues = getArrayLength();
357 uint32_t uiValueIndex;
358 uint32_t uiSize = getSize();
359 uint32_t uiOffset = getOffset();
360
361 assert(values.size() == uiNbValues);
362
363 // Process
364 for (uiValueIndex = 0; uiValueIndex < uiNbValues; uiValueIndex++) {
365
366 if (!doSet(values[uiValueIndex], uiOffset, parameterAccessContext)) {
367
368 return false;
369 }
370
371 uiOffset += uiSize;
372 }
373
374 return true;
375}
376
377template <typename type>
Sebastien Gonzalved9526492014-02-20 22:28:03 +0100378bool CArrayParameter::getValues(std::vector<type>& values, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli065264a2011-11-20 15:46:41 +0100379{
380 uint32_t uiNbValues = getArrayLength();
381 uint32_t uiValueIndex;
382 uint32_t uiSize = getSize();
383 uint32_t uiOffset = getOffset();
384
385 values.clear();
386
387 for (uiValueIndex = 0; uiValueIndex < uiNbValues; uiValueIndex++) {
388 type readValue;
389
390 if (!doGet(readValue, uiOffset, parameterAccessContext)) {
391
392 return false;
393 }
394
395 values.push_back(readValue);
396
397 uiOffset += uiSize;
398 }
399 return true;
400}
401
402template <typename type>
403bool CArrayParameter::doSet(type value, uint32_t uiOffset, CParameterAccessContext& parameterAccessContext) const
404{
405 uint32_t uiData;
406
407 if (!static_cast<const CParameterType*>(getTypeElement())->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(), uiOffset, parameterAccessContext.isBigEndianSubsystem());
416
417 return true;
418}
419
420template <typename type>
421bool CArrayParameter::doGet(type& value, uint32_t uiOffset, CParameterAccessContext& parameterAccessContext) const
422{
423 uint32_t uiData = 0;
424
425 // Read blackboard
426 const CParameterBlackboard* pBlackboard = parameterAccessContext.getParameterBlackboard();
427
428 // Beware this code works on little endian architectures only!
429 pBlackboard->readInteger(&uiData, getSize(), uiOffset, parameterAccessContext.isBigEndianSubsystem());
430
431 return static_cast<const CParameterType*>(getTypeElement())->fromBlackboard(value, uiData, parameterAccessContext);
432}
433