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 <stdlib.h>
32 #include <sstream>
33 #include <iomanip>
34 #include <ctype.h>
35 #include <assert.h>
36 #include "ParameterAccessContext.h"
37 #include "EnumValuePair.h"
38 #include "Utility.h"
39 #include <errno.h>
40
41 #define base CParameterType
42
43 using std::string;
44
CEnumParameterType(const string & strName)45 CEnumParameterType::CEnumParameterType(const string& strName) : base(strName)
46 {
47 }
48
getKind() const49 string CEnumParameterType::getKind() const
50 {
51 return "EnumParameter";
52 }
53
childrenAreDynamic() const54 bool CEnumParameterType::childrenAreDynamic() const
55 {
56 return true;
57 }
58
59 // Element properties
showProperties(string & strResult) const60 void CEnumParameterType::showProperties(string& strResult) const
61 {
62 base::showProperties(strResult);
63
64 strResult += "Value Pairs:\n";
65
66 // Show all value pairs
67 size_t uiChild;
68 size_t uiNbChildren = getNbChildren();
69
70 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
71
72 const CEnumValuePair* pValuePair = static_cast<const CEnumValuePair*>(getChild(uiChild));
73
74 strResult += "\tLiteral: \"";
75 strResult += pValuePair->getName();
76 strResult += "\", Numerical: ";
77 strResult += pValuePair->getNumericalAsString();
78 strResult += "\n";
79 }
80 }
81
fromXml(const CXmlElement & xmlElement,CXmlSerializingContext & serializingContext)82 bool CEnumParameterType::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
83 {
84 // Size in bits
85 uint32_t uiSizeInBits = xmlElement.getAttributeInteger("Size");
86
87 // Size
88 setSize(uiSizeInBits / 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, CParameterAccessContext& parameterAccessContext) const
96 {
97 int64_t iData;
98
99 if (isNumber(strValue)) {
100
101 /// Numerical value provided
102
103 // Hexa
104 bool bValueProvidedAsHexa = !strValue.compare(0, 2, "0x");
105
106 errno = 0;
107 char *pcStrEnd;
108
109 // Get value
110 iData = strtoll(strValue.c_str(), &pcStrEnd, 0);
111
112 // Conversion error when the input string does not contain any digit or the number is out of range (int32_t type)
113 bool bConversionSucceeded = !errno && (strValue.c_str() != pcStrEnd);
114
115 // Check validity against type
116 if (!checkValueAgainstRange(strValue, iData, parameterAccessContext, bValueProvidedAsHexa, bConversionSucceeded)) {
117
118 return false;
119 }
120
121 if (bValueProvidedAsHexa) {
122
123 // Sign extend
124 signExtend(iData);
125 }
126
127 // Check validity against lexical space
128 string strError;
129 if (!isValid(iData, parameterAccessContext)) {
130
131 parameterAccessContext.setError(strError);
132
133 return false;
134 }
135 } else {
136 /// Literal value provided
137
138 // Check validity against lexical space
139 int iNumerical;
140 if (!getNumerical(strValue, iNumerical)) {
141
142 parameterAccessContext.setError("Provided value not part of lexical space");
143
144 return false;
145 }
146 iData = iNumerical;
147
148 // Check validity against type
149 if (!checkValueAgainstRange(strValue, iData, parameterAccessContext, false, isEncodable((uint64_t)iData, true))) {
150
151 return false;
152 }
153 }
154
155 // Return data
156 uiValue = (uint32_t)iData;
157
158 return true;
159 }
160
161 // Range checking
checkValueAgainstRange(const string & strValue,int64_t value,CParameterAccessContext & parameterAccessContext,bool bHexaValue,bool bConversionSucceeded) const162 bool CEnumParameterType::checkValueAgainstRange(const string& strValue, int64_t value, CParameterAccessContext& parameterAccessContext, bool bHexaValue, bool bConversionSucceeded) const
163 {
164 // Enums are always signed, it means we have one less util bit
165 int64_t maxValue = getMaxValue<uint64_t>();
166 int64_t minValue = -maxValue - 1;
167
168 if (!bConversionSucceeded || value < minValue || value > maxValue) {
169
170 std::ostringstream strStream;
171
172 strStream << "Value " << strValue << " standing out of admitted range [";
173
174 if (bHexaValue) {
175
176 // Format Min
177 strStream << "0x" << std::hex << std::uppercase << std::setw(getSize()*2) << std::setfill('0') << makeEncodable(minValue);
178 // Format Max
179 strStream << ", 0x" << std::hex << std::uppercase << std::setw(getSize()*2) << std::setfill('0') << makeEncodable(maxValue);
180
181 } else {
182
183 strStream << minValue << ", " << maxValue;
184 }
185
186 strStream << "] for " << getKind();
187
188 parameterAccessContext.setError(strStream.str());
189
190 return false;
191 }
192 return true;
193 }
194
fromBlackboard(string & strValue,const uint32_t & uiValue,CParameterAccessContext & parameterAccessContext) const195 bool CEnumParameterType::fromBlackboard(string& strValue, const uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
196 {
197 // Take care of format
198 if (parameterAccessContext.valueSpaceIsRaw()) {
199
200 // Format
201 std::ostringstream strStream;
202
203 // Numerical format requested
204 if (parameterAccessContext.outputRawFormatIsHex()) {
205
206 // Hexa display with unecessary bits cleared out
207 strStream << "0x" << std::hex << std::uppercase << std::setw(getSize()*2) << std::setfill('0') << makeEncodable(uiValue);
208
209 strValue = strStream.str();
210 } else {
211
212 // Integer display
213 int32_t iValue = uiValue;
214
215 // Sign extend
216 signExtend(iValue);
217
218 strStream << iValue;
219
220 strValue = strStream.str();
221 }
222 } else {
223
224 // Integer display
225 int32_t iValue = uiValue;
226
227 // Sign extend
228 signExtend(iValue);
229
230 // Literal display requested (should succeed)
231 getLiteral(iValue, strValue);
232 }
233 return true;
234 }
235
236 // Value access
toBlackboard(int32_t iUserValue,uint32_t & uiValue,CParameterAccessContext & parameterAccessContext) const237 bool CEnumParameterType::toBlackboard(int32_t iUserValue, uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
238 {
239 if (!isValid(iUserValue, parameterAccessContext)) {
240
241 return false;
242 }
243 uiValue = iUserValue;
244
245 return true;
246 }
247
fromBlackboard(int32_t & iUserValue,uint32_t uiValue,CParameterAccessContext & parameterAccessContext) const248 bool CEnumParameterType::fromBlackboard(int32_t& iUserValue, uint32_t uiValue, CParameterAccessContext& parameterAccessContext) const
249 {
250 (void)parameterAccessContext;
251
252 int32_t iValue = uiValue;
253
254 // Sign extend
255 signExtend(iValue);
256
257 iUserValue = iValue;
258
259 return true;
260 }
261
262 // Default value handling (simulation only)
getDefaultValue() const263 uint32_t CEnumParameterType::getDefaultValue() const
264 {
265 if (!getNbChildren()) {
266
267 return 0;
268 }
269
270 // Return first available numerical
271 return static_cast<const CEnumValuePair*>(getChild(0))->getNumerical();
272 }
273
274 // Check string is a number
isNumber(const string & strValue)275 bool CEnumParameterType::isNumber(const string& strValue)
276 {
277 char cFirst = strValue[0];
278
279 return isdigit(cFirst) || cFirst == '+' || cFirst == '-';
280 }
281
282 // Literal - numerical conversions
getLiteral(int32_t iNumerical,string & strLiteral) const283 bool CEnumParameterType::getLiteral(int32_t iNumerical, string& strLiteral) const
284 {
285 size_t uiChild;
286 size_t uiNbChildren = getNbChildren();
287
288 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
289
290 const CEnumValuePair* pValuePair = static_cast<const CEnumValuePair*>(getChild(uiChild));
291
292 if (pValuePair->getNumerical() == iNumerical) {
293
294 strLiteral = pValuePair->getName();
295
296 return true;
297 }
298 }
299
300 return false;
301 }
302
getNumerical(const string & strLiteral,int & iNumerical) const303 bool CEnumParameterType::getNumerical(const string& strLiteral, int& iNumerical) const
304 {
305 size_t uiChild;
306 size_t uiNbChildren = getNbChildren();
307
308 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
309
310 const CEnumValuePair* pValuePair = static_cast<const CEnumValuePair*>(getChild(uiChild));
311
312 if (pValuePair->getName() == strLiteral) {
313
314 iNumerical = pValuePair->getNumerical();
315
316 return true;
317 }
318 }
319
320 return false;
321 }
322
323 // Numerical validity of the enum value
isValid(int iNumerical,CParameterAccessContext & parameterAccessContext) const324 bool CEnumParameterType::isValid(int iNumerical, CParameterAccessContext& parameterAccessContext) const
325 {
326 // Check that the value is part of the allowed values for this kind of enum
327 size_t uiChild;
328 size_t uiNbChildren = getNbChildren();
329
330 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
331
332 const CEnumValuePair* pValuePair = static_cast<const CEnumValuePair*>(getChild(uiChild));
333
334 if (pValuePair->getNumerical() == iNumerical) {
335
336 return true;
337 }
338 }
339
340 parameterAccessContext.setError("Provided value not part of numerical space");
341
342 return false;
343 }
344 // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const345 void CEnumParameterType::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
346 {
347 // Size
348 xmlElement.setAttributeString("Size", CUtility::toString(getSize() * 8));
349
350 base::toXml(xmlElement, serializingContext);
351 }
352