blob: 149dac2de16c3448b8eb0aa3aec9af88addc8a71 [file] [log] [blame]
Kevin Rocard93250d12012-07-19 17:48:30 +02001/*
Patrick Benavoli68a91282011-08-31 11:23:23 +02002 * INTEL CONFIDENTIAL
3 * Copyright © 2011 Intel
4 * Corporation All Rights Reserved.
5 *
6 * The source code contained or described herein and all documents related to
7 * the source code ("Material") are owned by Intel Corporation or its suppliers
8 * or licensors. Title to the Material remains with Intel Corporation or its
9 * suppliers and licensors. The Material contains trade secrets and proprietary
10 * and confidential information of Intel or its suppliers and licensors. The
11 * Material is protected by worldwide copyright and trade secret laws and
12 * treaty provisions. No part of the Material may be used, copied, reproduced,
13 * modified, published, uploaded, posted, transmitted, distributed, or
14 * disclosed in any way without Intel’s prior express written permission.
15 *
16 * No license under any patent, copyright, trade secret or other intellectual
17 * property right is granted to or conferred upon you by disclosure or delivery
18 * of the Materials, either expressly, by implication, inducement, estoppel or
19 * otherwise. Any license under such intellectual property rights must be
20 * express and approved by Intel in writing.
21 *
Patrick Benavoli68a91282011-08-31 11:23:23 +020022 * CREATED: 2011-06-01
23 * UPDATED: 2011-07-27
Patrick Benavoli68a91282011-08-31 11:23:23 +020024 */
25#include "ArrayParameter.h"
26#include <sstream> // for istringstream
27#include "Tokenizer.h"
28#include "ParameterType.h"
29#include "ParameterAccessContext.h"
30#include "ConfigurationAccessContext.h"
31#include "ParameterBlackboard.h"
Patrick Benavoli065264a2011-11-20 15:46:41 +010032#include <assert.h>
Patrick Benavoli68a91282011-08-31 11:23:23 +020033
34#define base CParameter
35
Patrick Benavoli2ecf9002011-08-31 11:23:24 +020036CArrayParameter::CArrayParameter(const string& strName, const CTypeElement* pTypeElement) : base(strName, pTypeElement)
Patrick Benavoli68a91282011-08-31 11:23:23 +020037{
38}
39
40uint32_t CArrayParameter::getFootPrint() const
41{
Patrick Benavoli2ecf9002011-08-31 11:23:24 +020042 return getSize() * getArrayLength();
43}
44
45// Array length
46uint32_t CArrayParameter::getArrayLength() const
47{
48 return getTypeElement()->getArrayLength();
49}
50
51// Element properties
52void CArrayParameter::showProperties(string& strResult) const
53{
54 base::showProperties(strResult);
55
56 // Array length
57 strResult += "Array length: ";
58 strResult += toString(getArrayLength());
59 strResult += "\n";
Patrick Benavoli68a91282011-08-31 11:23:23 +020060}
61
62// XML configuration settings parsing
Patrick Benavoli6ba361d2011-08-31 11:23:24 +020063bool CArrayParameter::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +020064{
65 // Check for value space
Patrick Benavoli6ba361d2011-08-31 11:23:24 +020066 handleValueSpaceAttribute(xmlConfigurationSettingsElementContent, configurationAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +020067
68 // Handle access
69 if (!configurationAccessContext.serializeOut()) {
70
71 // Actually set values to blackboard
Patrick Benavoli6ba361d2011-08-31 11:23:24 +020072 if (!setValues(0, configurationAccessContext.getBaseOffset(), xmlConfigurationSettingsElementContent.getTextContent(), configurationAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +020073
74 return false;
75 }
76 } else {
77
78 // Get string value
79 string strValue;
80
81 // Whole array requested
82 getValues(configurationAccessContext.getBaseOffset(), strValue, configurationAccessContext);
83
84 // Populate value into xml text node
Patrick Benavoli6ba361d2011-08-31 11:23:24 +020085 xmlConfigurationSettingsElementContent.setTextContent(strValue);
Patrick Benavoli68a91282011-08-31 11:23:23 +020086 }
87
88 // Done
89 return true;
90}
91
92// User set/get
Patrick Benavoli065264a2011-11-20 15:46:41 +010093bool CArrayParameter::accessValue(CPathNavigator& pathNavigator, string& strValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +020094{
Patrick Benavoli68a91282011-08-31 11:23:23 +020095 uint32_t uiIndex;
96
Patrick Benavoli065264a2011-11-20 15:46:41 +010097 if (!getIndex(pathNavigator, uiIndex, parameterAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +020098
99 return false;
100 }
Patrick Benavoli4bed9212011-10-27 14:18:00 +0200101
Patrick Benavoli065264a2011-11-20 15:46:41 +0100102 if (bSet) {
103 // Set
104 if (uiIndex == (uint32_t)-1) {
Patrick Benavoli4bed9212011-10-27 14:18:00 +0200105
Patrick Benavoli065264a2011-11-20 15:46:41 +0100106 // No index provided, start with 0
107 uiIndex = 0;
108 }
Patrick Benavoli4bed9212011-10-27 14:18:00 +0200109
Patrick Benavoli065264a2011-11-20 15:46:41 +0100110 // Actually set values
Frédéric Boisnard6bc17c02013-02-25 15:55:47 +0100111 if (!setValues(uiIndex, parameterAccessContext.getBaseOffset(), strValue, parameterAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200112
Patrick Benavoli065264a2011-11-20 15:46:41 +0100113 return false;
114 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200115
Patrick Benavoli065264a2011-11-20 15:46:41 +0100116 // Synchronize
117 if (parameterAccessContext.getAutoSync() && !sync(parameterAccessContext)) {
118
119 // Append parameter path to error
120 parameterAccessContext.appendToError(" " + getPath());
121
122 return false;
123 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200124 } else {
Patrick Benavoli065264a2011-11-20 15:46:41 +0100125 // Get
126 if (uiIndex == (uint32_t)-1) {
127
128 // Whole array requested
Frédéric Boisnard6bc17c02013-02-25 15:55:47 +0100129 getValues(parameterAccessContext.getBaseOffset(), strValue, parameterAccessContext);
Patrick Benavoli065264a2011-11-20 15:46:41 +0100130
131 } else {
132 // Scalar requested
133 doGetValue(strValue, getOffset() + uiIndex * getSize(), parameterAccessContext);
134 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200135 }
136
137 return true;
138}
139
Patrick Benavoli065264a2011-11-20 15:46:41 +0100140// Boolean
141bool CArrayParameter::accessAsBooleanArray(vector<bool>& abValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
142{
143 return accessValues(abValues, bSet, parameterAccessContext);
144}
145
146// Integer
147bool CArrayParameter::accessAsIntegerArray(vector<uint32_t>& auiValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
148{
149 return accessValues(auiValues, bSet, parameterAccessContext);
150}
151
152// Signed Integer Access
153bool CArrayParameter::accessAsSignedIntegerArray(vector<int32_t>& aiValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
154{
155 return accessValues(aiValues, bSet, parameterAccessContext);
156}
157
158// Double Access
159bool CArrayParameter::accessAsDoubleArray(vector<double>& adValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
160{
161 return accessValues(adValues, bSet, parameterAccessContext);
162}
163
164// String Access
165bool CArrayParameter::accessAsStringArray(vector<string>& astrValues, bool bSet, CParameterAccessContext& parameterAccessContext) const
166{
167 return accessValues(astrValues, bSet, parameterAccessContext);
168}
169
170// Dump
Patrick Benavoli68a91282011-08-31 11:23:23 +0200171void CArrayParameter::logValue(string& strValue, CErrorContext& errorContext) const
172{
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200173 // Parameter context
Patrick Benavoli065264a2011-11-20 15:46:41 +0100174 CParameterAccessContext& parameterAccessContext = static_cast<CParameterAccessContext&>(errorContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200175
176 // Dump values
Patrick Benavoli065264a2011-11-20 15:46:41 +0100177 getValues(0, strValue, parameterAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200178}
179
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +0100180// Used for simulation and virtual subsystems
Patrick Benavoli68a91282011-08-31 11:23:23 +0200181void CArrayParameter::setDefaultValues(CParameterAccessContext& parameterAccessContext) const
182{
183 // Get default value from type
184 uint32_t uiDefaultValue = static_cast<const CParameterType*>(getTypeElement())->getDefaultValue();
185
186 // Write blackboard
187 CParameterBlackboard* pBlackboard = parameterAccessContext.getParameterBlackboard();
188
189 // Process
190 uint32_t uiValueIndex;
191 uint32_t uiSize = getSize();
192 uint32_t uiOffset = getOffset();
193 bool bSubsystemIsBigEndian = parameterAccessContext.isBigEndianSubsystem();
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200194 uint32_t uiArrayLength = getArrayLength();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200195
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200196 for (uiValueIndex = 0; uiValueIndex < uiArrayLength; uiValueIndex++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200197
198 // Beware this code works on little endian architectures only!
Patrick Benavoli1352ae52011-10-21 16:48:04 +0200199 pBlackboard->writeInteger(&uiDefaultValue, uiSize, uiOffset, bSubsystemIsBigEndian);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200200
201 uiOffset += uiSize;
202 }
203}
204
205// Index from path
Patrick Benavoli065264a2011-11-20 15:46:41 +0100206bool CArrayParameter::getIndex(CPathNavigator& pathNavigator, uint32_t& uiIndex, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200207{
208 uiIndex = (uint32_t)-1;
209
210 string* pStrChildName = pathNavigator.next();
211
212 if (pStrChildName) {
213
214 // Check index is numeric
215 istringstream iss(*pStrChildName);
216
217 iss >> uiIndex;
218
219 if (!iss) {
220
Patrick Benavoli065264a2011-11-20 15:46:41 +0100221 parameterAccessContext.setError("Expected numerical expression as last item in " + pathNavigator.getCurrentPath());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200222
223 return false;
224 }
225
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200226 if (uiIndex >= getArrayLength()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200227 ostringstream oss;
228
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200229 oss << "Provided index out of range (max is " << getArrayLength() - 1 << ")";
Patrick Benavoli68a91282011-08-31 11:23:23 +0200230
Patrick Benavoli065264a2011-11-20 15:46:41 +0100231 parameterAccessContext.setError(oss.str());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200232
233 return false;
234 }
235
236 // Check no other item provided in path
237 pStrChildName = pathNavigator.next();
238
239 if (pStrChildName) {
240
241 // Should be leaf element
Patrick Benavoli065264a2011-11-20 15:46:41 +0100242 parameterAccessContext.setError("Path not found: " + pathNavigator.getCurrentPath());
Patrick Benavoli68a91282011-08-31 11:23:23 +0200243
244 return false;
245 }
246 }
247
248 return true;
249}
250
251// Common set value processing
Patrick Benavoli065264a2011-11-20 15:46:41 +0100252bool CArrayParameter::setValues(uint32_t uiStartIndex, uint32_t uiBaseOffset, const string& strValue, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200253{
254 // Deal with value(s)
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200255 Tokenizer tok(strValue, DEFAULT_DELIMITER + ",");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200256
257 vector<string> astrValues = tok.split();
258 uint32_t uiNbValues = astrValues.size();
259
260 // Check number of provided values
Patrick Benavoli065264a2011-11-20 15:46:41 +0100261 if (uiNbValues + uiStartIndex > getArrayLength()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200262
263 // Out of bounds
Patrick Benavoli065264a2011-11-20 15:46:41 +0100264 parameterAccessContext.setError("Too many values provided");
Patrick Benavoli68a91282011-08-31 11:23:23 +0200265
266 return false;
267 }
268
269 // Process
270 uint32_t uiValueIndex;
271 uint32_t uiSize = getSize();
272 uint32_t uiOffset = getOffset() + uiStartIndex * uiSize - uiBaseOffset;
273
274 for (uiValueIndex = 0; uiValueIndex < uiNbValues; uiValueIndex++) {
275
Patrick Benavoli065264a2011-11-20 15:46:41 +0100276 if (!doSetValue(astrValues[uiValueIndex], uiOffset, parameterAccessContext)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200277
278 // Append parameter path to error
Patrick Benavoli065264a2011-11-20 15:46:41 +0100279 parameterAccessContext.appendToError(" " + getPath() + "/" + toString(uiValueIndex + uiStartIndex));
Patrick Benavoli68a91282011-08-31 11:23:23 +0200280
281 return false;
282 }
283
284 uiOffset += uiSize;
285 }
286 return true;
287}
288
289// Common get value processing
Patrick Benavoli065264a2011-11-20 15:46:41 +0100290void CArrayParameter::getValues(uint32_t uiBaseOffset, string& strValues, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200291{
292 uint32_t uiValueIndex;
293 uint32_t uiSize = getSize();
294 uint32_t uiOffset = getOffset() - uiBaseOffset;
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200295 uint32_t uiArrayLength = getArrayLength();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200296
Patrick Benavoli4bed9212011-10-27 14:18:00 +0200297 strValues.clear();
298
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200299 bool bFirst = true;
300
Patrick Benavoli2ecf9002011-08-31 11:23:24 +0200301 for (uiValueIndex = 0; uiValueIndex < uiArrayLength; uiValueIndex++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200302 string strReadValue;
303
Patrick Benavoli065264a2011-11-20 15:46:41 +0100304 doGetValue(strReadValue, uiOffset, parameterAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200305
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200306 if (!bFirst) {
307
308 strValues += " ";
309 } else {
310
311 bFirst = false;
312 }
313
314 strValues += strReadValue;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200315
316 uiOffset += uiSize;
317 }
318}
Patrick Benavoli065264a2011-11-20 15:46:41 +0100319
320// Generic Access
321template <typename type>
322bool CArrayParameter::accessValues(vector<type>& values, bool bSet, CParameterAccessContext& parameterAccessContext) const
323{
324 bool bSuccess;
325
326 if (bSet) {
327
328 if (setValues(values, parameterAccessContext)) {
329
330 // Synchronize
331 bSuccess = sync(parameterAccessContext);
332 } else {
333
334 bSuccess = false;
335 }
336 } else {
337
338 bSuccess = getValues(values, parameterAccessContext);
339 }
340 if (!bSuccess) {
341
342 // Append parameter path to error
343 parameterAccessContext.appendToError(" " + getPath());
344 }
345 return bSuccess;
346}
347
348template <typename type>
349bool CArrayParameter::setValues(const vector<type>& values, CParameterAccessContext& parameterAccessContext) const
350{
351 uint32_t uiNbValues = getArrayLength();
352 uint32_t uiValueIndex;
353 uint32_t uiSize = getSize();
354 uint32_t uiOffset = getOffset();
355
356 assert(values.size() == uiNbValues);
357
358 // Process
359 for (uiValueIndex = 0; uiValueIndex < uiNbValues; uiValueIndex++) {
360
361 if (!doSet(values[uiValueIndex], uiOffset, parameterAccessContext)) {
362
363 return false;
364 }
365
366 uiOffset += uiSize;
367 }
368
369 return true;
370}
371
372template <typename type>
373bool CArrayParameter::getValues(vector<type>& values, CParameterAccessContext& parameterAccessContext) const
374{
375 uint32_t uiNbValues = getArrayLength();
376 uint32_t uiValueIndex;
377 uint32_t uiSize = getSize();
378 uint32_t uiOffset = getOffset();
379
380 values.clear();
381
382 for (uiValueIndex = 0; uiValueIndex < uiNbValues; uiValueIndex++) {
383 type readValue;
384
385 if (!doGet(readValue, uiOffset, parameterAccessContext)) {
386
387 return false;
388 }
389
390 values.push_back(readValue);
391
392 uiOffset += uiSize;
393 }
394 return true;
395}
396
397template <typename type>
398bool CArrayParameter::doSet(type value, uint32_t uiOffset, CParameterAccessContext& parameterAccessContext) const
399{
400 uint32_t uiData;
401
402 if (!static_cast<const CParameterType*>(getTypeElement())->toBlackboard(value, uiData, parameterAccessContext)) {
403
404 return false;
405 }
406 // Write blackboard
407 CParameterBlackboard* pBlackboard = parameterAccessContext.getParameterBlackboard();
408
409 // Beware this code works on little endian architectures only!
410 pBlackboard->writeInteger(&uiData, getSize(), uiOffset, parameterAccessContext.isBigEndianSubsystem());
411
412 return true;
413}
414
415template <typename type>
416bool CArrayParameter::doGet(type& value, uint32_t uiOffset, CParameterAccessContext& parameterAccessContext) const
417{
418 uint32_t uiData = 0;
419
420 // Read blackboard
421 const CParameterBlackboard* pBlackboard = parameterAccessContext.getParameterBlackboard();
422
423 // Beware this code works on little endian architectures only!
424 pBlackboard->readInteger(&uiData, getSize(), uiOffset, parameterAccessContext.isBigEndianSubsystem());
425
426 return static_cast<const CParameterType*>(getTypeElement())->fromBlackboard(value, uiData, parameterAccessContext);
427}
428