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 39 CEnumParameterType::CEnumParameterType(const string &strName) : base(strName) 40 { 41 } 42 43 string CEnumParameterType::getKind() const 44 { 45 return "EnumParameter"; 46 } 47 48 bool CEnumParameterType::childrenAreDynamic() const 49 { 50 return true; 51 } 52 53 // Element properties 54 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 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) 93 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 120 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 126 int32_t CEnumParameterType::getMax() const 127 { 128 return getMaxValue<int32_t>(); 129 } 130 131 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 143 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 169 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) 183 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 195 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 215 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 236 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 256 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