blob: dedb5da53bf2cbf2d9a7160c8b0b041f04f4519e [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
Patrick Benavoli2ecf9002011-08-31 11:23:24 +020041CArrayParameter::CArrayParameter(const string& strName, const CTypeElement* pTypeElement) : base(strName, pTypeElement)
Patrick Benavoli68a91282011-08-31 11:23:23 +020042{
43}
44
45uint32_t CArrayParameter::getFootPrint() const
46{
Patrick Benavoli2ecf9002011-08-31 11:23:24 +020047 return getSize() * getArrayLength();
48}
49
50// Array length
51uint32_t CArrayParameter::getArrayLength() const
52{
53 return getTypeElement()->getArrayLength();
54}
55
56// Element properties
57void CArrayParameter::showProperties(string& strResult) const
58{
59 base::showProperties(strResult);
60
61 // Array length
62 strResult += "Array length: ";
63 strResult += toString(getArrayLength());
64 strResult += "\n";
Patrick Benavoli68a91282011-08-31 11:23:23 +020065}
66
67// XML configuration settings parsing
Patrick Benavoli6ba361d2011-08-31 11:23:24 +020068bool CArrayParameter::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +020069{
70 // Check for value space
Patrick Benavoli6ba361d2011-08-31 11:23:24 +020071 handleValueSpaceAttribute(xmlConfigurationSettingsElementContent, configurationAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +020072
73 // Handle access
74 if (!configurationAccessContext.serializeOut()) {
75
76 // Actually set values to blackboard
Patrick Benavoli6ba361d2011-08-31 11:23:24 +020077 if (!setValues(0, configurationAccessContext.getBaseOffset(), xmlConfigurationSettingsElementContent.getTextContent(), configurationAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +020078
79 return false;
80 }
81 } else {
82
83 // Get string value
84 string strValue;
85
86 // Whole array requested
87 getValues(configurationAccessContext.getBaseOffset(), strValue, configurationAccessContext);
88
89 // Populate value into xml text node
Patrick Benavoli6ba361d2011-08-31 11:23:24 +020090 xmlConfigurationSettingsElementContent.setTextContent(strValue);
Patrick Benavoli68a91282011-08-31 11:23:23 +020091 }
92
93 // Done
94 return true;
95}
96
97// User set/get
Patrick Benavoli065264a2011-11-20 15:46:41 +010098bool CArrayParameter::accessValue(CPathNavigator& pathNavigator, string& strValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +020099{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200100 uint32_t uiIndex;
101
Patrick Benavoli065264a2011-11-20 15:46:41 +0100102 if (!getIndex(pathNavigator, uiIndex, parameterAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200103
104 return false;
105 }
Patrick Benavoli4bed9212011-10-27 14:18:00 +0200106
Patrick Benavoli065264a2011-11-20 15:46:41 +0100107 if (bSet) {
108 // Set
109 if (uiIndex == (uint32_t)-1) {
Patrick Benavoli4bed9212011-10-27 14:18:00 +0200110
Patrick Benavoli065264a2011-11-20 15:46:41 +0100111 // No index provided, start with 0
112 uiIndex = 0;
113 }
Patrick Benavoli4bed9212011-10-27 14:18:00 +0200114
Patrick Benavoli065264a2011-11-20 15:46:41 +0100115 // Actually set values
Frédéric Boisnard6bc17c02013-02-25 15:55:47 +0100116 if (!setValues(uiIndex, parameterAccessContext.getBaseOffset(), strValue, parameterAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200117
Patrick Benavoli065264a2011-11-20 15:46:41 +0100118 return false;
119 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200120
Patrick Benavoli065264a2011-11-20 15:46:41 +0100121 // Synchronize
122 if (parameterAccessContext.getAutoSync() && !sync(parameterAccessContext)) {
123
124 // Append parameter path to error
125 parameterAccessContext.appendToError(" " + getPath());
126
127 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
146bool CArrayParameter::accessAsBooleanArray(vector<bool>& abValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
147{
148 return accessValues(abValues, bSet, parameterAccessContext);
149}
150
151// Integer
152bool CArrayParameter::accessAsIntegerArray(vector<uint32_t>& auiValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
153{
154 return accessValues(auiValues, bSet, parameterAccessContext);
155}
156
157// Signed Integer Access
158bool CArrayParameter::accessAsSignedIntegerArray(vector<int32_t>& aiValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
159{
160 return accessValues(aiValues, bSet, parameterAccessContext);
161}
162
163// Double Access
164bool CArrayParameter::accessAsDoubleArray(vector<double>& adValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
165{
166 return accessValues(adValues, bSet, parameterAccessContext);
167}
168
169// String Access
170bool CArrayParameter::accessAsStringArray(vector<string>& astrValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
171{
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
220 istringstream iss(*pStrChildName);
221
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()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200232 ostringstream oss;
233
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)
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200260 Tokenizer tok(strValue, DEFAULT_DELIMITER + ",");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200261
262 vector<string> astrValues = tok.split();
263 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>
327bool CArrayParameter::accessValues(vector<type>& values, bool bSet, CParameterAccessContext& parameterAccessContext) const
328{
329 bool bSuccess;
330
331 if (bSet) {
332
333 if (setValues(values, parameterAccessContext)) {
334
335 // Synchronize
336 bSuccess = sync(parameterAccessContext);
337 } else {
338
339 bSuccess = false;
340 }
341 } else {
342
343 bSuccess = getValues(values, parameterAccessContext);
344 }
345 if (!bSuccess) {
346
347 // Append parameter path to error
348 parameterAccessContext.appendToError(" " + getPath());
349 }
350 return bSuccess;
351}
352
353template <typename type>
354bool CArrayParameter::setValues(const vector<type>& values, CParameterAccessContext& parameterAccessContext) const
355{
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>
378bool CArrayParameter::getValues(vector<type>& values, CParameterAccessContext& parameterAccessContext) const
379{
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