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 #define base CParameterType
36
37 using std::string;
38
CEnumParameterType(const string & strName)39 CEnumParameterType::CEnumParameterType(const string &strName) : base(strName)
40 {
41 }
42
getKind() const43 string CEnumParameterType::getKind() const
44 {
45 return "EnumParameter";
46 }
47
childrenAreDynamic() const48 bool CEnumParameterType::childrenAreDynamic() const
49 {
50 return true;
51 }
52
53 // Element properties
showProperties(string & strResult) const54 void CEnumParameterType::showProperties(string &strResult) const
55 {
56 base::showProperties(strResult);
57
58 strResult += "Value Pairs:\n";
59
60 // Show all value pairs
61 size_t uiChild;
62 size_t uiNbChildren = getNbChildren();
63
64 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
65
66 const CEnumValuePair *pValuePair = static_cast<const CEnumValuePair *>(getChild(uiChild));
67
68 strResult += "\tLiteral: \"";
69 strResult += pValuePair->getName();
70 strResult += "\", Numerical: ";
71 strResult += pValuePair->getNumericalAsString();
72 strResult += "\n";
73 }
74 }
75
fromXml(const CXmlElement & xmlElement,CXmlSerializingContext & serializingContext)76 bool CEnumParameterType::fromXml(const CXmlElement &xmlElement,
77 CXmlSerializingContext &serializingContext)
78 {
79 // Size in bits
80 size_t sizeInBits = 0;
81 if (not xmlElement.getAttribute("Size", sizeInBits)) {
82 return false;
83 }
84
85 // Size
86 setSize(sizeInBits / 8);
87
88 // Base
89 return base::fromXml(xmlElement, serializingContext);
90 }
91
92 // Conversion (tuning)
toBlackboard(const string & strValue,uint32_t & uiValue,CParameterAccessContext & parameterAccessContext) const93 bool CEnumParameterType::toBlackboard(const string &strValue, uint32_t &uiValue,
94 CParameterAccessContext ¶meterAccessContext) const
95 {
96 int32_t iParsedUserValue = 0;
97
98 // Try to read the user-provided string as an integer
99 if (not convertTo(strValue, iParsedUserValue)) {
100 // If it fails to parse as an integer, first try to convert it from
101 // lexical to numerical space.
102 int32_t iNumerical;
103 if (not getNumerical(strValue, iNumerical)) {
104
105 parameterAccessContext.setError("Provided value '" + strValue +
106 "' is not part of the lexical space"
107 " or not within the numerical range.");
108
109 return false;
110 }
111 iParsedUserValue = iNumerical;
112 }
113
114 // Once it has been converted to a number (either through parsing or
115 // through lexical->numerical conversion), call the numerical overload of
116 // toBlackboard.
117 return toBlackboard(iParsedUserValue, uiValue, parameterAccessContext);
118 }
119
getMin() const120 int32_t CEnumParameterType::getMin() const
121 {
122 // Enums are always signed, it means we have one less util bit
123 return -getMax() - 1;
124 }
125
getMax() const126 int32_t CEnumParameterType::getMax() const
127 {
128 return getMaxValue<int32_t>();
129 }
130
fromBlackboard(string & userValue,const uint32_t & value,CParameterAccessContext &) const131 bool CEnumParameterType::fromBlackboard(string &userValue, const uint32_t &value,
132 CParameterAccessContext & /*ctx*/) const
133 {
134 // Convert the raw value from the blackboard
135 int32_t signedValue = static_cast<int32_t>(value);
136 signExtend(signedValue);
137
138 // Convert from numerical space to literal space
139 return getLiteral(signedValue, userValue);
140 }
141
142 // Value access
toBlackboard(int32_t userValue,uint32_t & value,CParameterAccessContext & parameterAccessContext) const143 bool CEnumParameterType::toBlackboard(int32_t userValue, uint32_t &value,
144 CParameterAccessContext ¶meterAccessContext) const
145 {
146 if (!checkValueAgainstSpace(userValue)) {
147
148 parameterAccessContext.setError(std::to_string(userValue) +
149 " is not part of numerical space.");
150
151 return false;
152 }
153
154 if (userValue < getMin() or userValue > getMax()) {
155
156 // FIXME: values provided as hexa (either on command line or in a config
157 // file will appear in decimal base instead of hexa base...
158 parameterAccessContext.setError(
159 "Value " + std::to_string(userValue) + " standing out of admitted range [" +
160 std::to_string(getMin()) + ", " + std::to_string(getMax()) + "] for " + getKind());
161 return false;
162 }
163
164 value = static_cast<uint32_t>(userValue);
165
166 return true;
167 }
168
fromBlackboard(int32_t & userValue,uint32_t value,CParameterAccessContext &) const169 bool CEnumParameterType::fromBlackboard(int32_t &userValue, uint32_t value,
170 CParameterAccessContext & /*ctx*/) const
171 {
172 int32_t signedValue = static_cast<int32_t>(value);
173
174 // Sign extend
175 signExtend(signedValue);
176
177 userValue = signedValue;
178
179 return true;
180 }
181
182 // Default value handling (simulation only)
getDefaultValue() const183 uint32_t CEnumParameterType::getDefaultValue() const
184 {
185 if (!getNbChildren()) {
186
187 return 0;
188 }
189
190 // Return first available numerical
191 return static_cast<const CEnumValuePair *>(getChild(0))->getNumerical();
192 }
193
194 // Literal - numerical conversions
getLiteral(int32_t iNumerical,string & strLiteral) const195 bool CEnumParameterType::getLiteral(int32_t iNumerical, string &strLiteral) const
196 {
197 size_t uiChild;
198 size_t uiNbChildren = getNbChildren();
199
200 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
201
202 const CEnumValuePair *pValuePair = static_cast<const CEnumValuePair *>(getChild(uiChild));
203
204 if (pValuePair->getNumerical() == iNumerical) {
205
206 strLiteral = pValuePair->getName();
207
208 return true;
209 }
210 }
211
212 return false;
213 }
214
getNumerical(const string & strLiteral,int32_t & iNumerical) const215 bool CEnumParameterType::getNumerical(const string &strLiteral, int32_t &iNumerical) const
216 {
217 size_t uiChild;
218 size_t uiNbChildren = getNbChildren();
219
220 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
221
222 const CEnumValuePair *pValuePair = static_cast<const CEnumValuePair *>(getChild(uiChild));
223
224 if (pValuePair->getName() == strLiteral) {
225
226 iNumerical = pValuePair->getNumerical();
227
228 return true;
229 }
230 }
231
232 return false;
233 }
234
235 // Numerical validity of the enum value
checkValueAgainstSpace(int32_t iNumerical) const236 bool CEnumParameterType::checkValueAgainstSpace(int32_t iNumerical) const
237 {
238 // Check that the value is part of the allowed values for this kind of enum
239 size_t uiChild;
240 size_t uiNbChildren = getNbChildren();
241
242 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
243
244 const CEnumValuePair *pValuePair = static_cast<const CEnumValuePair *>(getChild(uiChild));
245
246 if (pValuePair->getNumerical() == iNumerical) {
247
248 return true;
249 }
250 }
251
252 return false;
253 }
254
255 // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const256 void CEnumParameterType::toXml(CXmlElement &xmlElement,
257 CXmlSerializingContext &serializingContext) const
258 {
259 // Size
260 xmlElement.setAttribute("Size", getSize() * 8);
261
262 base::toXml(xmlElement, serializingContext);
263 }
264