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 43 CParameterType::CParameterType(const string &strName) : base(strName) 44 { 45 } 46 47 // Object creation 48 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 54 void CParameterType::setSize(size_t size) 55 { 56 _size = size; 57 } 58 59 size_t CParameterType::getSize() const 60 { 61 return _size; 62 } 63 64 // Unit 65 string CParameterType::getUnit() const 66 { 67 return _strUnit; 68 } 69 70 void CParameterType::setUnit(const std::string &strUnit) 71 { 72 _strUnit = strUnit; 73 } 74 75 // From IXmlSink 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 84 void CParameterType::toXml(CXmlElement &xmlElement, 85 CXmlSerializingContext &serializingContext) const 86 { 87 base::toXml(xmlElement, serializingContext); 88 setXmlUnitAttribute(xmlElement); 89 } 90 91 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 101 void CParameterType::handleValueSpaceAttribute( 102 CXmlElement & /*xmlConfigurableElementSettingsElement*/, 103 CConfigurationAccessContext & /*ctx*/) const 104 { 105 // Do nothing by default 106 } 107 108 // Element properties 109 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) 123 uint32_t CParameterType::getDefaultValue() const 124 { 125 return 0; 126 } 127 128 // Parameter instantiation 129 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 140 void CParameterType::signExtend(int32_t &iData) const 141 { 142 doSignExtend(iData); 143 } 144 145 void CParameterType::signExtend(int64_t &iData) const 146 { 147 doSignExtend(iData); 148 } 149 150 // Generic sign extension 151 template <typename type> 152 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 undened**. 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) 164 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) 170 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> 177 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 202 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 214 bool CParameterType::toBlackboard(bool /*bUserValue*/, uint32_t & /*uiValue*/, 215 CParameterAccessContext ¶meterAccessContext) const 216 { 217 parameterAccessContext.setError("Unsupported conversion"); 218 return false; 219 } 220 221 bool CParameterType::fromBlackboard(bool & /*bUserValue*/, uint32_t /*uiValue*/, 222 CParameterAccessContext ¶meterAccessContext) const 223 { 224 parameterAccessContext.setError("Unsupported conversion"); 225 return false; 226 } 227 228 // Integer 229 bool CParameterType::toBlackboard(uint32_t /*uiUserValue*/, uint32_t & /*uiValue*/, 230 CParameterAccessContext ¶meterAccessContext) const 231 { 232 parameterAccessContext.setError("Unsupported conversion"); 233 return false; 234 } 235 236 bool CParameterType::fromBlackboard(uint32_t & /*uiUserValue*/, uint32_t /*uiValue*/, 237 CParameterAccessContext ¶meterAccessContext) const 238 { 239 parameterAccessContext.setError("Unsupported conversion"); 240 return false; 241 } 242 243 // Signed Integer 244 bool CParameterType::toBlackboard(int32_t /*iUserValue*/, uint32_t & /*uiValue*/, 245 CParameterAccessContext ¶meterAccessContext) const 246 { 247 parameterAccessContext.setError("Unsupported conversion"); 248 249 return false; 250 } 251 252 bool CParameterType::fromBlackboard(int32_t & /*iUserValue*/, uint32_t /*uiValue*/, 253 CParameterAccessContext ¶meterAccessContext) const 254 { 255 parameterAccessContext.setError("Unsupported conversion"); 256 257 return false; 258 } 259 260 // Double 261 bool CParameterType::toBlackboard(double /*dUserValue*/, uint32_t & /*uiValue*/, 262 CParameterAccessContext ¶meterAccessContext) const 263 { 264 parameterAccessContext.setError("Unsupported conversion"); 265 266 return false; 267 } 268 269 bool CParameterType::fromBlackboard(double & /*dUserValue*/, uint32_t /*uiValue*/, 270 CParameterAccessContext ¶meterAccessContext) const 271 { 272 parameterAccessContext.setError("Unsupported conversion"); 273 274 return false; 275 } 276