Home | History | Annotate | Download | only in parameter
      1 /*
      2  * Copyright (c) 2014-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, Value, 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 "FloatingPointParameterType.h"
     31 #include <sstream>
     32 #include <iomanip>
     33 #include "ParameterAccessContext.h"
     34 #include "ConfigurationAccessContext.h"
     35 #include <limits>
     36 #include <climits>
     37 #include "convert.hpp"
     38 #include "Utility.h"
     39 #include "BinaryCopy.hpp"
     40 
     41 using std::string;
     42 
     43 CFloatingPointParameterType::CFloatingPointParameterType(const string &strName) : base(strName)
     44 {
     45 }
     46 
     47 string CFloatingPointParameterType::getKind() const
     48 {
     49     return "FloatingPointParameter";
     50 }
     51 
     52 // Element properties
     53 void CFloatingPointParameterType::showProperties(string &strResult) const
     54 {
     55     base::showProperties(strResult);
     56 
     57     strResult += "Min:" + std::to_string(_fMin) + "\n" + "Max:" + std::to_string(_fMax) + "\n";
     58 }
     59 
     60 void CFloatingPointParameterType::handleValueSpaceAttribute(
     61     CXmlElement &xmlConfigurableElementSettingsElement,
     62     CConfigurationAccessContext &configurationAccessContext) const
     63 {
     64     if (!configurationAccessContext.serializeOut()) {
     65 
     66         string strValueSpace;
     67 
     68         if (xmlConfigurableElementSettingsElement.getAttribute("ValueSpace", strValueSpace)) {
     69 
     70             configurationAccessContext.setValueSpaceRaw(strValueSpace == "Raw");
     71         } else {
     72 
     73             configurationAccessContext.setValueSpaceRaw(false);
     74         }
     75     } else {
     76         // Set the value space only if it is raw (i.e. not the default one)
     77         if (configurationAccessContext.valueSpaceIsRaw()) {
     78 
     79             xmlConfigurableElementSettingsElement.setAttribute("ValueSpace", "Raw");
     80         }
     81     }
     82 }
     83 
     84 bool CFloatingPointParameterType::fromXml(const CXmlElement &xmlElement,
     85                                           CXmlSerializingContext &serializingContext)
     86 {
     87     // Size. The XSD fixes it to 32
     88     size_t sizeInBits = 32;
     89     xmlElement.getAttribute("Size", sizeInBits);
     90 
     91     // Size support check: only floats are supported
     92     // (e.g. doubles are not supported)
     93     if (sizeInBits != sizeof(float) * CHAR_BIT) {
     94 
     95         serializingContext.setError("Unsupported size (" + std::to_string(sizeInBits) + ") for " +
     96                                     getKind() + " " + xmlElement.getPath() +
     97                                     ". For now, only 32 is supported.");
     98 
     99         return false;
    100     }
    101 
    102     setSize(sizeInBits / CHAR_BIT);
    103 
    104     xmlElement.getAttribute("Min", _fMin);
    105     xmlElement.getAttribute("Max", _fMax);
    106 
    107     if (_fMin > _fMax) {
    108         serializingContext.setError("Min (" + std::to_string(_fMin) +
    109                                     ") can't be greater than Max (" + std::to_string(_fMax) + ")");
    110         return false;
    111     }
    112 
    113     return base::fromXml(xmlElement, serializingContext);
    114 }
    115 
    116 bool CFloatingPointParameterType::toBlackboard(
    117     const string &strValue, uint32_t &uiValue,
    118     CParameterAccessContext &parameterAccessContext) const
    119 {
    120     // Check Value integrity
    121     if (utility::isHexadecimal(strValue) && !parameterAccessContext.valueSpaceIsRaw()) {
    122 
    123         parameterAccessContext.setError("Hexadecimal values are not supported for " + getKind() +
    124                                         " when selected value space is real: " + strValue);
    125 
    126         return false;
    127     }
    128 
    129     if (parameterAccessContext.valueSpaceIsRaw()) {
    130         // Raw value: interpret the user input as the memory content of the
    131         // parameter
    132         if (!convertTo(strValue, uiValue)) {
    133 
    134             parameterAccessContext.setError("Value '" + strValue + "' is invalid");
    135             return false;
    136         }
    137 
    138         auto fData = utility::binaryCopy<float>(uiValue);
    139 
    140         // Check against NaN or infinity
    141         if (!std::isfinite(fData)) {
    142 
    143             parameterAccessContext.setError("Value " + strValue + " is not a finite number");
    144             return false;
    145         }
    146 
    147         if (!checkValueAgainstRange(fData)) {
    148 
    149             setOutOfRangeError(strValue, parameterAccessContext);
    150             return false;
    151         }
    152         return true;
    153     } else {
    154 
    155         float fValue = 0.0f;
    156 
    157         // Interpret the user input as float
    158         if (!convertTo(strValue, fValue)) {
    159 
    160             parameterAccessContext.setError("Value " + strValue + " is invalid");
    161             return false;
    162         }
    163 
    164         if (!checkValueAgainstRange(fValue)) {
    165 
    166             setOutOfRangeError(strValue, parameterAccessContext);
    167             return false;
    168         }
    169 
    170         // Move to the "raw memory" value space
    171         uiValue = utility::binaryCopy<decltype(uiValue)>(fValue);
    172         return true;
    173     }
    174 }
    175 
    176 void CFloatingPointParameterType::setOutOfRangeError(
    177     const string &strValue, CParameterAccessContext &parameterAccessContext) const
    178 {
    179     // error message buffer
    180     std::ostringstream ostrStream;
    181 
    182     ostrStream << "Value " << strValue << " standing out of admitted ";
    183 
    184     if (!parameterAccessContext.valueSpaceIsRaw()) {
    185 
    186         ostrStream << "real range [" << _fMin << ", " << _fMax << "]";
    187     } else {
    188 
    189         auto uiMin = utility::binaryCopy<uint32_t>(_fMin);
    190         auto uiMax = utility::binaryCopy<uint32_t>(_fMax);
    191 
    192         if (utility::isHexadecimal(strValue)) {
    193 
    194             ostrStream << std::showbase << std::hex << std::setw(static_cast<int>(getSize() * 2))
    195                        << std::setfill('0');
    196         }
    197 
    198         ostrStream << "raw range [" << uiMin << ", " << uiMax << "]";
    199     }
    200     ostrStream << " for " << getKind();
    201 
    202     parameterAccessContext.setError(ostrStream.str());
    203 }
    204 
    205 bool CFloatingPointParameterType::fromBlackboard(
    206     string &strValue, const uint32_t &uiValue,
    207     CParameterAccessContext &parameterAccessContext) const
    208 {
    209     std::ostringstream ostrStream;
    210 
    211     if (parameterAccessContext.valueSpaceIsRaw()) {
    212 
    213         if (parameterAccessContext.outputRawFormatIsHex()) {
    214 
    215             ostrStream << std::showbase << std::hex << std::setw(static_cast<int>(getSize() * 2))
    216                        << std::setfill('0');
    217         }
    218 
    219         ostrStream << uiValue;
    220     } else {
    221 
    222         // Move from "raw memory" value space to real space
    223         auto fValue = utility::binaryCopy<float>(uiValue);
    224 
    225         ostrStream << fValue;
    226     }
    227 
    228     strValue = ostrStream.str();
    229 
    230     return true;
    231 }
    232 
    233 // Value access
    234 bool CFloatingPointParameterType::toBlackboard(
    235     double dUserValue, uint32_t &uiValue, CParameterAccessContext &parameterAccessContext) const
    236 {
    237     if (!checkValueAgainstRange(dUserValue)) {
    238 
    239         parameterAccessContext.setError("Value out of range");
    240         return false;
    241     }
    242 
    243     // Cast is fine because dValue has been checked against the value range
    244     float fValue = static_cast<float>(dUserValue);
    245     uiValue = utility::binaryCopy<decltype(uiValue)>(fValue);
    246     return true;
    247 }
    248 
    249 bool CFloatingPointParameterType::fromBlackboard(double &dUserValue, uint32_t uiValue,
    250                                                  CParameterAccessContext & /*ctx*/) const
    251 {
    252     // Move from "raw memory" value space to real space
    253     auto fValue = utility::binaryCopy<float>(uiValue);
    254 
    255     dUserValue = fValue;
    256     return true;
    257 }
    258 
    259 bool CFloatingPointParameterType::checkValueAgainstRange(double dValue) const
    260 {
    261     // Check that dValue can safely be cast to a float
    262     // (otherwise, behaviour is undefined)
    263     if ((dValue < -std::numeric_limits<float>::max()) ||
    264         (dValue > std::numeric_limits<float>::max())) {
    265         return false;
    266     }
    267 
    268     return checkValueAgainstRange(static_cast<float>(dValue));
    269 }
    270 
    271 bool CFloatingPointParameterType::checkValueAgainstRange(float fValue) const
    272 {
    273     return fValue <= _fMax && fValue >= _fMin;
    274 }
    275 
    276 void CFloatingPointParameterType::toXml(CXmlElement &xmlElement,
    277                                         CXmlSerializingContext &serializingContext) const
    278 {
    279     xmlElement.setAttribute("Size", getSize() * CHAR_BIT);
    280     xmlElement.setAttribute("Min", _fMin);
    281     xmlElement.setAttribute("Max", _fMax);
    282 
    283     base::toXml(xmlElement, serializingContext);
    284 }
    285