blob: 47000a711665ce528388aeb3fe68addd16029006 [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
Francois Gaffie8ab72932014-04-07 13:46:05 +0200122 if (!sync(parameterAccessContext)) {
Patrick Benavoli065264a2011-11-20 15:46:41 +0100123
124 // Append parameter path to error
125 parameterAccessContext.appendToError(" " + getPath());
Patrick Benavoli065264a2011-11-20 15:46:41 +0100126 return false;
127 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200128 } else {
Patrick Benavoli065264a2011-11-20 15:46:41 +0100129 // Get
130 if (uiIndex == (uint32_t)-1) {
131
132 // Whole array requested
Frédéric Boisnard6bc17c02013-02-25 15:55:47 +0100133 getValues(parameterAccessContext.getBaseOffset(), strValue, parameterAccessContext);
Patrick Benavoli065264a2011-11-20 15:46:41 +0100134
135 } else {
136 // Scalar requested
137 doGetValue(strValue, getOffset() + uiIndex * getSize(), parameterAccessContext);
138 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200139 }
140
141 return true;
142}
143
Patrick Benavoli065264a2011-11-20 15:46:41 +0100144// Boolean
145bool CArrayParameter::accessAsBooleanArray(vector<bool>& abValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
146{
147 return accessValues(abValues, bSet, parameterAccessContext);
148}
149
150// Integer
151bool CArrayParameter::accessAsIntegerArray(vector<uint32_t>& auiValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
152{
153 return accessValues(auiValues, bSet, parameterAccessContext);
154}
155
156// Signed Integer Access
157bool CArrayParameter::accessAsSignedIntegerArray(vector<int32_t>& aiValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
158{
159 return accessValues(aiValues, bSet, parameterAccessContext);
160}
161
162// Double Access
163bool CArrayParameter::accessAsDoubleArray(vector<double>& adValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
164{
165 return accessValues(adValues, bSet, parameterAccessContext);
166}
167
168// String Access
169bool CArrayParameter::accessAsStringArray(vector<string>& astrValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
170{
171 return accessValues(astrValues, bSet, parameterAccessContext);
172}
173
174// Dump
Patrick Benavoli68a91282011-08-31 11:23:23 +0200175void CArrayParameter::logValue(string& strValue, CErrorContext& errorContext) const
176{
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200177 // Parameter context
Patrick Benavoli065264a2011-11-20 15:46:41 +0100178 CParameterAccessContext& parameterAccessContext = static_cast<CParameterAccessContext&>(errorContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200179
180 // Dump values
Patrick Benavoli065264a2011-11-20 15:46:41 +0100181 getValues(0, strValue, parameterAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200182}
183
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +0100184// Used for simulation and virtual subsystems
Patrick Benavoli68a91282011-08-31 11:23:23 +0200185void CArrayParameter::setDefaultValues(CParameterAccessContext& parameterAccessContext) const
186{
187 // Get default value from type
188 uint32_t uiDefaultValue = static_cast<const CParameterType*>(getTypeElement())->getDefaultValue();
189
190 // Write blackboard
191 CParameterBlackboard* pBlackboard = parameterAccessContext.getParameterBlackboard();
192
193 // Process
194 uint32_t uiValueIndex;
195 uint32_t uiSize = getSize();
196 uint32_t uiOffset = getOffset();
197 bool bSubsystemIsBigEndian = parameterAccessContext.isBigEndianSubsystem();
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200198 uint32_t uiArrayLength = getArrayLength();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200199
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200200 for (uiValueIndex = 0; uiValueIndex < uiArrayLength; uiValueIndex++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200201
202 // Beware this code works on little endian architectures only!
Patrick Benavoli1352ae52011-10-21 16:48:04 +0200203 pBlackboard->writeInteger(&uiDefaultValue, uiSize, uiOffset, bSubsystemIsBigEndian);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200204
205 uiOffset += uiSize;
206 }
207}
208
209// Index from path
Patrick Benavoli065264a2011-11-20 15:46:41 +0100210bool CArrayParameter::getIndex(CPathNavigator& pathNavigator, uint32_t& uiIndex, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200211{
212 uiIndex = (uint32_t)-1;
213
214 string* pStrChildName = pathNavigator.next();
215
216 if (pStrChildName) {
217
218 // Check index is numeric
219 istringstream iss(*pStrChildName);
220
221 iss >> uiIndex;
222
223 if (!iss) {
224
Patrick Benavoli065264a2011-11-20 15:46:41 +0100225 parameterAccessContext.setError("Expected numerical expression as last item in " + pathNavigator.getCurrentPath());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200226
227 return false;
228 }
229
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200230 if (uiIndex >= getArrayLength()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200231 ostringstream oss;
232
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200233 oss << "Provided index out of range (max is " << getArrayLength() - 1 << ")";
Patrick Benavoli68a91282011-08-31 11:23:23 +0200234
Patrick Benavoli065264a2011-11-20 15:46:41 +0100235 parameterAccessContext.setError(oss.str());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200236
237 return false;
238 }
239
240 // Check no other item provided in path
241 pStrChildName = pathNavigator.next();
242
243 if (pStrChildName) {
244
245 // Should be leaf element
Patrick Benavoli065264a2011-11-20 15:46:41 +0100246 parameterAccessContext.setError("Path not found: " + pathNavigator.getCurrentPath());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200247
248 return false;
249 }
250 }
251
252 return true;
253}
254
255// Common set value processing
Patrick Benavoli065264a2011-11-20 15:46:41 +0100256bool CArrayParameter::setValues(uint32_t uiStartIndex, uint32_t uiBaseOffset, const string& strValue, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200257{
258 // Deal with value(s)
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200259 Tokenizer tok(strValue, DEFAULT_DELIMITER + ",");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200260
261 vector<string> astrValues = tok.split();
262 uint32_t uiNbValues = astrValues.size();
263
264 // Check number of provided values
Patrick Benavoli065264a2011-11-20 15:46:41 +0100265 if (uiNbValues + uiStartIndex > getArrayLength()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200266
267 // Out of bounds
Patrick Benavoli065264a2011-11-20 15:46:41 +0100268 parameterAccessContext.setError("Too many values provided");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200269
270 return false;
271 }
272
273 // Process
274 uint32_t uiValueIndex;
275 uint32_t uiSize = getSize();
276 uint32_t uiOffset = getOffset() + uiStartIndex * uiSize - uiBaseOffset;
277
278 for (uiValueIndex = 0; uiValueIndex < uiNbValues; uiValueIndex++) {
279
Patrick Benavoli065264a2011-11-20 15:46:41 +0100280 if (!doSetValue(astrValues[uiValueIndex], uiOffset, parameterAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200281
282 // Append parameter path to error
Patrick Benavoli065264a2011-11-20 15:46:41 +0100283 parameterAccessContext.appendToError(" " + getPath() + "/" + toString(uiValueIndex + uiStartIndex));
Patrick Benavoli68a91282011-08-31 11:23:23 +0200284
285 return false;
286 }
287
288 uiOffset += uiSize;
289 }
290 return true;
291}
292
293// Common get value processing
Patrick Benavoli065264a2011-11-20 15:46:41 +0100294void CArrayParameter::getValues(uint32_t uiBaseOffset, string& strValues, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200295{
296 uint32_t uiValueIndex;
297 uint32_t uiSize = getSize();
298 uint32_t uiOffset = getOffset() - uiBaseOffset;
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200299 uint32_t uiArrayLength = getArrayLength();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200300
Patrick Benavoli4bed9212011-10-27 14:18:00 +0200301 strValues.clear();
302
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200303 bool bFirst = true;
304
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200305 for (uiValueIndex = 0; uiValueIndex < uiArrayLength; uiValueIndex++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200306 string strReadValue;
307
Patrick Benavoli065264a2011-11-20 15:46:41 +0100308 doGetValue(strReadValue, uiOffset, parameterAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200309
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200310 if (!bFirst) {
311
312 strValues += " ";
313 } else {
314
315 bFirst = false;
316 }
317
318 strValues += strReadValue;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200319
320 uiOffset += uiSize;
321 }
322}
Patrick Benavoli065264a2011-11-20 15:46:41 +0100323
324// Generic Access
325template <typename type>
326bool CArrayParameter::accessValues(vector<type>& values, bool bSet, CParameterAccessContext& parameterAccessContext) const
327{
Patrick Benavoli065264a2011-11-20 15:46:41 +0100328 if (bSet) {
329
Francois Gaffie8ab72932014-04-07 13:46:05 +0200330 // Set Value
331 if (!setValues(values, parameterAccessContext)) {
Patrick Benavoli065264a2011-11-20 15:46:41 +0100332
Francois Gaffie8ab72932014-04-07 13:46:05 +0200333 // Append parameter path to error
334 parameterAccessContext.appendToError(" " + getPath());
335 return false;
336 }
337 if (!sync(parameterAccessContext)) {
Patrick Benavoli065264a2011-11-20 15:46:41 +0100338
Francois Gaffie8ab72932014-04-07 13:46:05 +0200339 // Append parameter path to error
340 parameterAccessContext.appendToError(" " + getPath());
341 return false;
Patrick Benavoli065264a2011-11-20 15:46:41 +0100342 }
343 } else {
Francois Gaffie8ab72932014-04-07 13:46:05 +0200344 // Get Value
345 if (!getValues(values, parameterAccessContext)) {
Patrick Benavoli065264a2011-11-20 15:46:41 +0100346
Francois Gaffie8ab72932014-04-07 13:46:05 +0200347 // Append parameter path to error
348 parameterAccessContext.appendToError(" " + getPath());
349 return false;
350 }
Patrick Benavoli065264a2011-11-20 15:46:41 +0100351 }
Francois Gaffie8ab72932014-04-07 13:46:05 +0200352 return true;
Patrick Benavoli065264a2011-11-20 15:46:41 +0100353}
354
355template <typename type>
356bool CArrayParameter::setValues(const 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
379template <typename type>
380bool CArrayParameter::getValues(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
404template <typename type>
405bool 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
422template <typename type>
423bool 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