1 /*
2 * Copyright (c) 2011-2015, 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 "EnumParameterType.h"
31 #include "EnumValuePair.h"
32 #include "ParameterAccessContext.h"
33 #include "convert.hpp"
34
35 #include <iomanip>
36
37 #define base CParameterType
38
39 using std::string;
40
CEnumParameterType(const string & strName)41 CEnumParameterType::CEnumParameterType(const string &strName) : base(strName)
42 {
43 }
44
getKind() const45 string CEnumParameterType::getKind() const
46 {
47 return "EnumParameter";
48 }
49
childrenAreDynamic() const50 bool CEnumParameterType::childrenAreDynamic() const
51 {
52 return true;
53 }
54
55 // Element properties
showProperties(string & strResult) const56 void CEnumParameterType::showProperties(string &strResult) const
57 {
58 base::showProperties(strResult);
59
60 strResult += "Value Pairs:\n";
61
62 // Show all value pairs
63 size_t uiChild;
64 size_t uiNbChildren = getNbChildren();
65
66 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
67
68 const CEnumValuePair *pValuePair = static_cast<const CEnumValuePair *>(getChild(uiChild));
69
70 strResult += "\tLiteral: \"";
71 strResult += pValuePair->getName();
72 strResult += "\", Numerical: ";
73 strResult += pValuePair->getNumericalAsString();
74 strResult += "\n";
75 }
76 }
77
fromXml(const CXmlElement & xmlElement,CXmlSerializingContext & serializingContext)78 bool CEnumParameterType::fromXml(const CXmlElement &xmlElement,
79 CXmlSerializingContext &serializingContext)
80 {
81 // Size in bits
82 size_t sizeInBits = 0;
83 if (not xmlElement.getAttribute("Size", sizeInBits)) {
84 return false;
85 }
86
87 // Size
88 setSize(sizeInBits / 8);
89
90 // Base
91 return base::fromXml(xmlElement, serializingContext);
92 }
93
94 // Conversion (tuning)
toBlackboard(const string & strValue,uint32_t & uiValue,CParameterAccessContext & parameterAccessContext) const95 bool CEnumParameterType::toBlackboard(const string &strValue, uint32_t &uiValue,
96 CParameterAccessContext ¶meterAccessContext) const
97 {
98 int32_t iParsedUserValue = 0;
99
100 // Try to read the user-provided string as an integer
101 if (not convertTo(strValue, iParsedUserValue)) {
102 // If it fails to parse as an integer, first try to convert it from
103 // lexical to numerical space.
104 int32_t iNumerical;
105 if (not getNumerical(strValue, iNumerical)) {
106
107 parameterAccessContext.setError("Provided value '" + strValue +
108 "' is not part of the lexical space"
109 " or not within the numerical range.");
110
111 return false;
112 }
113 iParsedUserValue = iNumerical;
114 }
115
116 // Once it has been converted to a number (either through parsing or
117 // through lexical->numerical conversion), call the numerical overload of
118 // toBlackboard.
119 return toBlackboard(iParsedUserValue, uiValue, parameterAccessContext);
120 }
121
getMin() const122 int32_t CEnumParameterType::getMin() const
123 {
124 // Enums are always signed, it means we have one less util bit
125 return -getMax() - 1;
126 }
127
getMax() const128 int32_t CEnumParameterType::getMax() const
129 {
130 return getMaxValue<int32_t>();
131 }
132
fromBlackboard(string & userValue,const uint32_t & value,CParameterAccessContext & ctx) const133 bool CEnumParameterType::fromBlackboard(string &userValue, const uint32_t &value,
134 CParameterAccessContext &ctx) const
135 {
136 // Convert the raw value from the blackboard
137 int32_t signedValue = static_cast<int32_t>(value);
138 signExtend(signedValue);
139
140 // Take care of format
141 if (ctx.valueSpaceIsRaw()) {
142
143 // Format
144 std::ostringstream sstream;
145
146 // Numerical format requested
147 if (ctx.outputRawFormatIsHex()) {
148
149 // Hexa display with unecessary bits cleared out
150 sstream << "0x" << std::hex << std::uppercase
151 << std::setw(static_cast<int>(getSize() * 2)) << std::setfill('0')
152 << makeEncodable(value);
153
154 userValue = sstream.str();
155 } else {
156 userValue = std::to_string(value);
157 }
158 } else {
159 // Literal display requested (should succeed)
160 getLiteral(signedValue, userValue);
161 }
162 return true;
163 }
164
165 // Value access
toBlackboard(int32_t userValue,uint32_t & value,CParameterAccessContext & parameterAccessContext) const166 bool CEnumParameterType::toBlackboard(int32_t userValue, uint32_t &value,
167 CParameterAccessContext ¶meterAccessContext) const
168 {
169 // Take care of format
170 if (parameterAccessContext.valueSpaceIsRaw()) {
171 signExtend(userValue);
172 }
173
174 if (!checkValueAgainstSpace(userValue)) {
175
176 parameterAccessContext.setError(std::to_string(userValue) +
177 " is not part of numerical space.");
178
179 return false;
180 }
181
182 if (userValue < getMin() or userValue > getMax()) {
183
184 // FIXME: values provided as hexa (either on command line or in a config
185 // file will appear in decimal base instead of hexa base...
186 parameterAccessContext.setError(
187 "Value " + std::to_string(userValue) + " standing out of admitted range [" +
188 std::to_string(getMin()) + ", " + std::to_string(getMax()) + "] for " + getKind());
189 return false;
190 }
191
192 value = static_cast<uint32_t>(userValue);
193
194 return true;
195 }
196
fromBlackboard(int32_t & userValue,uint32_t value,CParameterAccessContext &) const197 bool CEnumParameterType::fromBlackboard(int32_t &userValue, uint32_t value,
198 CParameterAccessContext & /*ctx*/) const
199 {
200 int32_t signedValue = static_cast<int32_t>(value);
201
202 // Sign extend
203 signExtend(signedValue);
204
205 userValue = signedValue;
206
207 return true;
208 }
209
210 // Default value handling (simulation only)
getDefaultValue() const211 uint32_t CEnumParameterType::getDefaultValue() const
212 {
213 if (!getNbChildren()) {
214
215 return 0;
216 }
217
218 // Return first available numerical
219 return static_cast<const CEnumValuePair *>(getChild(0))->getNumerical();
220 }
221
222 // Literal - numerical conversions
getLiteral(int32_t iNumerical,string & strLiteral) const223 bool CEnumParameterType::getLiteral(int32_t iNumerical, string &strLiteral) const
224 {
225 size_t uiChild;
226 size_t uiNbChildren = getNbChildren();
227
228 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
229
230 const CEnumValuePair *pValuePair = static_cast<const CEnumValuePair *>(getChild(uiChild));
231
232 if (pValuePair->getNumerical() == iNumerical) {
233
234 strLiteral = pValuePair->getName();
235
236 return true;
237 }
238 }
239
240 return false;
241 }
242
getNumerical(const string & strLiteral,int32_t & iNumerical) const243 bool CEnumParameterType::getNumerical(const string &strLiteral, int32_t &iNumerical) const
244 {
245 size_t uiChild;
246 size_t uiNbChildren = getNbChildren();
247
248 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
249
250 const CEnumValuePair *pValuePair = static_cast<const CEnumValuePair *>(getChild(uiChild));
251
252 if (pValuePair->getName() == strLiteral) {
253
254 iNumerical = pValuePair->getNumerical();
255
256 return true;
257 }
258 }
259
260 return false;
261 }
262
263 // Numerical validity of the enum value
checkValueAgainstSpace(int32_t iNumerical) const264 bool CEnumParameterType::checkValueAgainstSpace(int32_t iNumerical) const
265 {
266 // Check that the value is part of the allowed values for this kind of enum
267 size_t uiChild;
268 size_t uiNbChildren = getNbChildren();
269
270 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
271
272 const CEnumValuePair *pValuePair = static_cast<const CEnumValuePair *>(getChild(uiChild));
273
274 if (pValuePair->getNumerical() == iNumerical) {
275
276 return true;
277 }
278 }
279
280 return false;
281 }
282
283 // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const284 void CEnumParameterType::toXml(CXmlElement &xmlElement,
285 CXmlSerializingContext &serializingContext) const
286 {
287 // Size
288 xmlElement.setAttribute("Size", getSize() * 8);
289
290 base::toXml(xmlElement, serializingContext);
291 }
292