Home | History | Annotate | Download | only in parameter
      1 /*
      2  * Copyright (c) 2011-2016, 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 #pragma once
     31 
     32 #include "BaseIntegerParameterType.h"
     33 #include "ParameterAdaptation.h"
     34 #include "ParameterAccessContext.h"
     35 
     36 #include <convert.hpp>
     37 
     38 #include <type_traits>
     39 #include <sstream>
     40 #include <string>
     41 #include <limits>
     42 #include <iomanip>
     43 
     44 namespace detail
     45 {
     46 template <bool isSigned, size_t size>
     47 struct IntegerTraits
     48 {
     49     static_assert(size == 8 or size == 16 or size == 32,
     50                   "IntegerParameterType size must be 8, 16 or 32.");
     51 
     52 private:
     53     // Assumes that size is either 8, 16 or 32, which is ensured by the static_assert above.
     54     using Signed = typename std::conditional<
     55         size == 8, int8_t, typename std::conditional<size == 16, int16_t, int32_t>::type>::type;
     56     using Unsigned = typename std::make_unsigned<Signed>::type;
     57 
     58 public:
     59     using CType = typename std::conditional<isSigned, Signed, Unsigned>::type;
     60 };
     61 } // namespace detail
     62 
     63 template <bool isSigned, size_t bitSize>
     64 class CIntegerParameterType : public CBaseIntegerParameterType
     65 {
     66 private:
     67     using Base = CBaseIntegerParameterType;
     68     using CType = typename detail::IntegerTraits<isSigned, bitSize>::CType;
     69 
     70     template <class UserType>
     71     bool doToBlackboard(UserType userValue, uint32_t &uiValue,
     72                         CParameterAccessContext &parameterAccessContext) const
     73     {
     74         {
     75             if (userValue < static_cast<UserType>(_min) ||
     76                 userValue > static_cast<UserType>(_max)) {
     77 
     78                 parameterAccessContext.setError("Value out of range");
     79                 return false;
     80             }
     81             // Do assign
     82             uiValue = userValue;
     83 
     84             return true;
     85         }
     86     }
     87 
     88 public:
     89     CIntegerParameterType(const std::string &name) : Base(name){};
     90 
     91     // From IXmlSink
     92     bool fromXml(const CXmlElement &xmlElement, CXmlSerializingContext &serializingContext) override
     93     {
     94         setSize(bitSize / 8);
     95 
     96         xmlElement.getAttribute("Min", _min);
     97         xmlElement.getAttribute("Max", _max);
     98 
     99         if (_min > _max) {
    100             serializingContext.setError("The range of allowed value is empty (" +
    101                                         std::to_string(_min) + " > " + std::to_string(_max) + ").");
    102             return false;
    103         }
    104 
    105         // Base
    106         return Base::fromXml(xmlElement, serializingContext);
    107     }
    108 
    109     // From IXmlSource
    110     void toXml(CXmlElement &xmlElement, CXmlSerializingContext &serializingContext) const override
    111     {
    112         xmlElement.setAttribute("Signed", isSigned);
    113 
    114         xmlElement.setAttribute("Min", _min);
    115         xmlElement.setAttribute("Max", _max);
    116 
    117         xmlElement.setAttribute("Size", bitSize);
    118 
    119         Base::toXml(xmlElement, serializingContext);
    120     }
    121 
    122     bool fromBlackboard(std::string &strValue, const uint32_t &value,
    123                         CParameterAccessContext &parameterAccessContext) const override
    124     {
    125         // Format
    126         std::ostringstream stream;
    127 
    128         // Take care of format
    129         if (parameterAccessContext.valueSpaceIsRaw() &&
    130             parameterAccessContext.outputRawFormatIsHex()) {
    131 
    132             // Hexa display with unecessary bits cleared out
    133             stream << "0x" << std::hex << std::uppercase
    134                    << std::setw(static_cast<int>(getSize() * 2)) << std::setfill('0') << value;
    135         } else {
    136 
    137             if (isSigned) {
    138 
    139                 int32_t iValue = value;
    140 
    141                 // Sign extend
    142                 signExtend(iValue);
    143 
    144                 stream << iValue;
    145             } else {
    146 
    147                 stream << value;
    148             }
    149         }
    150 
    151         strValue = stream.str();
    152 
    153         return true;
    154     }
    155 
    156     // Value access
    157     // Integer
    158     bool toBlackboard(uint32_t uiUserValue, uint32_t &uiValue,
    159                       CParameterAccessContext &parameterAccessContext) const override
    160     {
    161         return doToBlackboard(uiUserValue, uiValue, parameterAccessContext);
    162     }
    163 
    164     // Signed Integer
    165     bool toBlackboard(int32_t iUserValue, uint32_t &uiValue,
    166                       CParameterAccessContext &parameterAccessContext) const override
    167     {
    168         return doToBlackboard(iUserValue, uiValue, parameterAccessContext);
    169     }
    170 
    171     // Double
    172     bool toBlackboard(double dUserValue, uint32_t &uiValue,
    173                       CParameterAccessContext &parameterAccessContext) const override
    174     {
    175         // Check if there's an adaptation object available
    176         const CParameterAdaptation *pParameterAdaption = getParameterAdaptation();
    177 
    178         if (!pParameterAdaption) {
    179 
    180             // Reject request and let upper class handle the error
    181             return Base::toBlackboard(dUserValue, uiValue, parameterAccessContext);
    182         }
    183 
    184         // Do the conversion
    185         int64_t iConvertedValue = pParameterAdaption->fromUserValue(dUserValue);
    186 
    187         if (iConvertedValue < _min || iConvertedValue > _max) {
    188 
    189             parameterAccessContext.setError("Value out of range");
    190 
    191             return false;
    192         }
    193 
    194         // Do assign
    195         uiValue = (uint32_t)iConvertedValue;
    196 
    197         return true;
    198     }
    199 
    200     template <class T>
    201     bool toBlackboard(const std::string &strValue, uint32_t &uiValue,
    202                       CParameterAccessContext &parameterAccessContext) const
    203     {
    204         T intermediate;
    205         if (not convertTo(strValue, intermediate)) {
    206             std::string strError;
    207             strError = "Impossible to convert value " + strValue + " for " + getKind();
    208 
    209             parameterAccessContext.setError(strError);
    210             return false;
    211         }
    212 
    213         CType value = static_cast<CType>(intermediate);
    214         if (!checkValueAgainstRange(strValue, intermediate, parameterAccessContext,
    215                                     utility::isHexadecimal(strValue))) {
    216             return false;
    217         }
    218         uiValue = (uint32_t)value;
    219 
    220         return true;
    221     }
    222 
    223     // String
    224     bool toBlackboard(const std::string &strValue, uint32_t &uiValue,
    225                       CParameterAccessContext &parameterAccessContext) const override
    226     {
    227         if (isSigned and utility::isHexadecimal(strValue)) {
    228             using Intermediate = typename std::make_unsigned<CType>::type;
    229 
    230             return toBlackboard<Intermediate>(strValue, uiValue, parameterAccessContext);
    231         } else {
    232             return toBlackboard<CType>(strValue, uiValue, parameterAccessContext);
    233         }
    234     }
    235 
    236     bool fromBlackboard(double &dUserValue, uint32_t uiValue,
    237                         CParameterAccessContext &parameterAccessContext) const override
    238     {
    239         // Check if there's an adaptation object available
    240         const CParameterAdaptation *pParameterAdaption = getParameterAdaptation();
    241 
    242         if (!pParameterAdaption) {
    243 
    244             // Reject request and let upper class handle the error
    245             return Base::fromBlackboard(dUserValue, uiValue, parameterAccessContext);
    246         }
    247 
    248         int64_t iValueToConvert;
    249 
    250         // Deal with signed data
    251         if (isSigned) {
    252 
    253             int32_t iValue = uiValue;
    254 
    255             signExtend(iValue);
    256 
    257             iValueToConvert = iValue;
    258         } else {
    259 
    260             iValueToConvert = uiValue;
    261         }
    262 
    263         // Do the conversion
    264         dUserValue = pParameterAdaption->toUserValue(iValueToConvert);
    265 
    266         return true;
    267     }
    268 
    269     // Default value handling (simulation only)
    270     uint32_t getDefaultValue() const override { return _min; }
    271 
    272     // Element properties
    273     void showProperties(std::string &strResult) const override
    274     {
    275         Base::showProperties(strResult);
    276 
    277         std::ostringstream stream;
    278         stream << "Signed: " << (isSigned ? "yes" : "no") << "\n"
    279                << "Min: " << _min << "\n"
    280                << "Max: " << _max << "\n";
    281 
    282         strResult += stream.str();
    283 
    284         // Check if there's an adaptation object available
    285         const CParameterAdaptation *pParameterAdaption = getParameterAdaptation();
    286 
    287         if (pParameterAdaption) {
    288 
    289             // Display adaptation properties
    290             strResult += "Adaptation:\n";
    291 
    292             pParameterAdaption->showProperties(strResult);
    293         }
    294     }
    295 
    296     // Integer conversion
    297     int toPlainInteger(int iSizeOptimizedData) const override
    298     {
    299         if (isSigned) {
    300 
    301             signExtend(iSizeOptimizedData);
    302         }
    303 
    304         return Base::toPlainInteger(iSizeOptimizedData);
    305     }
    306 
    307     // Range checking
    308     bool checkValueAgainstRange(const std::string &strValue, CType value,
    309                                 CParameterAccessContext &parameterAccessContext,
    310                                 bool bHexaValue) const
    311     {
    312         if (value < _min || value > _max) {
    313 
    314             std::ostringstream stream;
    315 
    316             stream << "Value " << strValue << " standing out of admitted range [";
    317 
    318             if (bHexaValue) {
    319 
    320                 stream << "0x" << std::hex << std::uppercase
    321                        << std::setw(static_cast<int>(getSize() * 2)) << std::setfill('0');
    322                 // Format Min
    323                 stream << _min;
    324                 // Format Max
    325                 stream << _max;
    326 
    327             } else {
    328 
    329                 stream << _min << ", " << _max;
    330             }
    331 
    332             stream << "] for " << getKind();
    333 
    334             parameterAccessContext.setError(stream.str());
    335 
    336             return false;
    337         }
    338         return true;
    339     }
    340 
    341 private:
    342     // Range
    343     CType _min{std::numeric_limits<CType>::min()};
    344     CType _max{std::numeric_limits<CType>::max()};
    345 };
    346