1/*
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.
29 */
30#include "Parameter.h"
31#include "ParameterType.h"
32#include "ParameterAccessContext.h"
33#include "ConfigurationAccessContext.h"
34#include "ParameterBlackboard.h"
35
36#define base CBaseParameter
37
38using std::string;
39
40CParameter::CParameter(const string& strName, const CTypeElement* pTypeElement) : base(strName, pTypeElement)
41{
42}
43
44CInstanceConfigurableElement::Type CParameter::getType() const
45{
46    return EParameter;
47}
48
49// XML configuration settings parsing/composing
50bool CParameter::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const
51{
52    // Check for value space
53    handleValueSpaceAttribute(xmlConfigurationSettingsElementContent, configurationAccessContext);
54
55    // Base
56    return base::serializeXmlSettings(xmlConfigurationSettingsElementContent, configurationAccessContext);
57}
58
59// Value space handling for configuration import
60void CParameter::handleValueSpaceAttribute(CXmlElement& xmlConfigurableElementSettingsElement, CConfigurationAccessContext& configurationAccessContext) const
61{
62    // Delegate to type
63    static_cast<const CParameterType*>(getTypeElement())->handleValueSpaceAttribute(xmlConfigurableElementSettingsElement, configurationAccessContext);
64}
65
66uint32_t CParameter::getFootPrint() const
67{
68    return getSize();
69}
70
71uint32_t CParameter::getSize() const
72{
73    return static_cast<const CParameterType*>(getTypeElement())->getSize();
74}
75
76// Used for simulation and virtual subsystems
77void CParameter::setDefaultValues(CParameterAccessContext& parameterAccessContext) const
78{
79    // Get default value from type
80    uint32_t uiDefaultValue = static_cast<const CParameterType*>(getTypeElement())->getDefaultValue();
81
82    // Write blackboard
83    CParameterBlackboard* pBlackboard = parameterAccessContext.getParameterBlackboard();
84
85    // Beware this code works on little endian architectures only!
86    pBlackboard->writeInteger(&uiDefaultValue, getSize(), getOffset() - parameterAccessContext.getBaseOffset(), parameterAccessContext.isBigEndianSubsystem());
87}
88
89/// Actual parameter access
90// String access
91bool CParameter::doSetValue(const string& strValue, uint32_t uiOffset, CParameterAccessContext& parameterAccessContext) const
92{
93    return doSet(strValue, uiOffset, parameterAccessContext);
94}
95
96void CParameter::doGetValue(string& strValue, uint32_t uiOffset, CParameterAccessContext& parameterAccessContext) const
97{
98    doGet(strValue, uiOffset, parameterAccessContext);
99}
100
101// Boolean access
102bool CParameter::accessAsBoolean(bool& bValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
103{
104    return doAccess(bValue, bSet, parameterAccessContext);
105}
106
107// Integer Access
108bool CParameter::accessAsInteger(uint32_t& uiValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
109{
110    return doAccess(uiValue, bSet, parameterAccessContext);
111}
112
113// Signed Integer Access
114bool CParameter::accessAsSignedInteger(int32_t& iValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
115{
116    return doAccess(iValue, bSet, parameterAccessContext);
117}
118
119// Double Access
120bool CParameter::accessAsDouble(double& dValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
121{
122    return doAccess(dValue, bSet, parameterAccessContext);
123}
124
125// Generic Access
126template <typename type>
127bool CParameter::doAccess(type& value, bool bSet,
128                          CParameterAccessContext& parameterAccessContext) const
129{
130    if (bSet) {
131        // set value
132        if (!doSet(value, getOffset() - parameterAccessContext.getBaseOffset(),
133                   parameterAccessContext)) {
134
135            appendParameterPathToError(parameterAccessContext);
136            return false;
137
138        }
139        // Synchronize
140        if (!sync(parameterAccessContext)){
141
142            appendParameterPathToError(parameterAccessContext);
143            return false;
144        }
145    } else {
146        // get value
147        if (!doGet(value, getOffset() - parameterAccessContext.getBaseOffset(),
148                   parameterAccessContext)) {
149
150            appendParameterPathToError(parameterAccessContext);
151            return false;
152        }
153    }
154    return true;
155}
156
157template <typename type>
158bool CParameter::doSet(type value, uint32_t uiOffset, CParameterAccessContext& parameterAccessContext) const
159{
160    uint32_t uiData;
161
162    if (!static_cast<const CParameterType*>(getTypeElement())->toBlackboard(value, uiData, parameterAccessContext)) {
163
164        return false;
165    }
166    // Write blackboard
167    CParameterBlackboard* pBlackboard = parameterAccessContext.getParameterBlackboard();
168
169    // Beware this code works on little endian architectures only!
170    pBlackboard->writeInteger(&uiData, getSize(), uiOffset, parameterAccessContext.isBigEndianSubsystem());
171
172    return true;
173}
174
175template <typename type>
176bool CParameter::doGet(type& value, uint32_t uiOffset, CParameterAccessContext& parameterAccessContext) const
177{
178    uint32_t uiData = 0;
179
180    // Read blackboard
181    const CParameterBlackboard* pBlackboard = parameterAccessContext.getParameterBlackboard();
182
183    // Beware this code works on little endian architectures only!
184    pBlackboard->readInteger(&uiData, getSize(), uiOffset, parameterAccessContext.isBigEndianSubsystem());
185
186    return static_cast<const CParameterType*>(getTypeElement())->fromBlackboard(value, uiData, parameterAccessContext);
187}
188