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 "ParameterType.h"
31 #include "Parameter.h"
32 #include "ArrayParameter.h"
33 #include "ParameterAccessContext.h"
34 
35 #include <climits>
36 
37 #define base CTypeElement
38 
39 using std::string;
40 
41 const std::string CParameterType::gUnitPropertyName = "Unit";
42 
CParameterType(const string & strName)43 CParameterType::CParameterType(const string &strName) : base(strName)
44 {
45 }
46 
47 // Object creation
populate(CElement *) const48 void CParameterType::populate(CElement * /*elem*/) const
49 {
50     // Prevent further digging for instantiaton since we're leaf on the strcture tree
51 }
52 
53 // Size
setSize(size_t size)54 void CParameterType::setSize(size_t size)
55 {
56     _size = size;
57 }
58 
getSize() const59 size_t CParameterType::getSize() const
60 {
61     return _size;
62 }
63 
64 // Unit
getUnit() const65 string CParameterType::getUnit() const
66 {
67     return _strUnit;
68 }
69 
setUnit(const std::string & strUnit)70 void CParameterType::setUnit(const std::string &strUnit)
71 {
72     _strUnit = strUnit;
73 }
74 
75 // From IXmlSink
fromXml(const CXmlElement & xmlElement,CXmlSerializingContext & serializingContext)76 bool CParameterType::fromXml(const CXmlElement &xmlElement,
77                              CXmlSerializingContext &serializingContext)
78 {
79     xmlElement.getAttribute(gUnitPropertyName, _strUnit);
80     return base::fromXml(xmlElement, serializingContext);
81 }
82 
83 // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const84 void CParameterType::toXml(CXmlElement &xmlElement,
85                            CXmlSerializingContext &serializingContext) const
86 {
87     base::toXml(xmlElement, serializingContext);
88     setXmlUnitAttribute(xmlElement);
89 }
90 
setXmlUnitAttribute(CXmlElement & xmlElement) const91 void CParameterType::setXmlUnitAttribute(CXmlElement &xmlElement) const
92 {
93     const string &unit = getUnit();
94     if (!unit.empty()) {
95         xmlElement.setAttribute(gUnitPropertyName, unit);
96     }
97 }
98 
99 // XML Serialization value space handling
100 // Value space handling for configuration import/export
handleValueSpaceAttribute(CXmlElement &,CConfigurationAccessContext &) const101 void CParameterType::handleValueSpaceAttribute(
102     CXmlElement & /*xmlConfigurableElementSettingsElement*/,
103     CConfigurationAccessContext & /*ctx*/) const
104 {
105     // Do nothing by default
106 }
107 
108 // Element properties
showProperties(string & strResult) const109 void CParameterType::showProperties(string &strResult) const
110 {
111     base::showProperties(strResult);
112 
113     // Add Unit property if found
114     if (!getUnit().empty()) {
115         strResult += gUnitPropertyName + ": " + getUnit() + "\n";
116     }
117 
118     // Scalar size
119     strResult += "Scalar size: " + std::to_string(getSize()) + " byte(s) \n";
120 }
121 
122 // Default value handling (simulation only)
getDefaultValue() const123 uint32_t CParameterType::getDefaultValue() const
124 {
125     return 0;
126 }
127 
128 // Parameter instantiation
doInstantiate() const129 CInstanceConfigurableElement *CParameterType::doInstantiate() const
130 {
131     if (isScalar()) {
132         // Scalar parameter
133         return new CParameter(getName(), this);
134     } else {
135         // Array Parameter
136         return new CArrayParameter(getName(), this);
137     }
138 }
139 
signExtend(int32_t & iData) const140 void CParameterType::signExtend(int32_t &iData) const
141 {
142     doSignExtend(iData);
143 }
144 
signExtend(int64_t & iData) const145 void CParameterType::signExtend(int64_t &iData) const
146 {
147     doSignExtend(iData);
148 }
149 
150 // Generic sign extension
151 template <typename type>
doSignExtend(type & data) const152 void CParameterType::doSignExtend(type &data) const
153 {
154     size_t shift = CHAR_BIT * (sizeof(data) - getSize());
155     // FIXME: If `data` has a signed type and nonnegative value,
156     //        and `data × 2^shift` is representable in the result type,
157     //        then that is the resulting value;
158     //        otherwise, **the behavior is undefined**.
159     //        ISO C99 (6.5.7/4) & ISO C++11 [expr.shift]
160     data = (data << shift) >> shift;
161 }
162 
163 // Check data has no bit set outside available range (32 bits)
isEncodable(uint32_t uiData,bool bIsSigned) const164 bool CParameterType::isEncodable(uint32_t uiData, bool bIsSigned) const
165 {
166     return doIsEncodable(uiData, bIsSigned);
167 }
168 
169 // Check data has no bit set outside available range (64 bits)
isEncodable(uint64_t uiData,bool bIsSigned) const170 bool CParameterType::isEncodable(uint64_t uiData, bool bIsSigned) const
171 {
172     return doIsEncodable(uiData, bIsSigned);
173 }
174 
175 // Generic encodability check
176 template <typename type>
doIsEncodable(type data,bool bIsSigned) const177 bool CParameterType::doIsEncodable(type data, bool bIsSigned) const
178 {
179     if (getSize() == sizeof(data)) {
180         // Prevent inappropriate shifts
181         return true;
182     }
183 
184     size_t shift = getSize() * 8;
185 
186     if (!bIsSigned) {
187 
188         // Check high bits are clean
189         return !(data >> shift);
190 
191     } else {
192 
193         // Negative value?
194         bool bIsValueExpectedNegative = (data & (type(1) << (shift - 1))) != 0;
195 
196         // Check high bits are clean
197         return bIsValueExpectedNegative ? !(~data >> shift) : !(data >> shift);
198     }
199 }
200 
201 // Remove all bits set outside available range
makeEncodable(uint32_t uiData) const202 uint32_t CParameterType::makeEncodable(uint32_t uiData) const
203 {
204     size_t sizeInBits = getSize() * 8;
205 
206     uint32_t uiMask = (1 << sizeInBits) - 1;
207 
208     return uiData & uiMask;
209 }
210 
211 // Conversions (dynamic access)
212 // Value access
213 // Boolean
toBlackboard(bool,uint32_t &,CParameterAccessContext & parameterAccessContext) const214 bool CParameterType::toBlackboard(bool /*bUserValue*/, uint32_t & /*uiValue*/,
215                                   CParameterAccessContext &parameterAccessContext) const
216 {
217     parameterAccessContext.setError("Unsupported conversion");
218     return false;
219 }
220 
fromBlackboard(bool &,uint32_t,CParameterAccessContext & parameterAccessContext) const221 bool CParameterType::fromBlackboard(bool & /*bUserValue*/, uint32_t /*uiValue*/,
222                                     CParameterAccessContext &parameterAccessContext) const
223 {
224     parameterAccessContext.setError("Unsupported conversion");
225     return false;
226 }
227 
228 // Integer
toBlackboard(uint32_t,uint32_t &,CParameterAccessContext & parameterAccessContext) const229 bool CParameterType::toBlackboard(uint32_t /*uiUserValue*/, uint32_t & /*uiValue*/,
230                                   CParameterAccessContext &parameterAccessContext) const
231 {
232     parameterAccessContext.setError("Unsupported conversion");
233     return false;
234 }
235 
fromBlackboard(uint32_t &,uint32_t,CParameterAccessContext & parameterAccessContext) const236 bool CParameterType::fromBlackboard(uint32_t & /*uiUserValue*/, uint32_t /*uiValue*/,
237                                     CParameterAccessContext &parameterAccessContext) const
238 {
239     parameterAccessContext.setError("Unsupported conversion");
240     return false;
241 }
242 
243 // Signed Integer
toBlackboard(int32_t,uint32_t &,CParameterAccessContext & parameterAccessContext) const244 bool CParameterType::toBlackboard(int32_t /*iUserValue*/, uint32_t & /*uiValue*/,
245                                   CParameterAccessContext &parameterAccessContext) const
246 {
247     parameterAccessContext.setError("Unsupported conversion");
248 
249     return false;
250 }
251 
fromBlackboard(int32_t &,uint32_t,CParameterAccessContext & parameterAccessContext) const252 bool CParameterType::fromBlackboard(int32_t & /*iUserValue*/, uint32_t /*uiValue*/,
253                                     CParameterAccessContext &parameterAccessContext) const
254 {
255     parameterAccessContext.setError("Unsupported conversion");
256 
257     return false;
258 }
259 
260 // Double
toBlackboard(double,uint32_t &,CParameterAccessContext & parameterAccessContext) const261 bool CParameterType::toBlackboard(double /*dUserValue*/, uint32_t & /*uiValue*/,
262                                   CParameterAccessContext &parameterAccessContext) const
263 {
264     parameterAccessContext.setError("Unsupported conversion");
265 
266     return false;
267 }
268 
fromBlackboard(double &,uint32_t,CParameterAccessContext & parameterAccessContext) const269 bool CParameterType::fromBlackboard(double & /*dUserValue*/, uint32_t /*uiValue*/,
270                                     CParameterAccessContext &parameterAccessContext) const
271 {
272     parameterAccessContext.setError("Unsupported conversion");
273 
274     return false;
275 }
276