Home | History | Annotate | Download | only in parameter
      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 "IntegerParameterType.h"
     31 #include <stdlib.h>
     32 #include <sstream>
     33 #include <iomanip>
     34 #include "ParameterAccessContext.h"
     35 #include <assert.h>
     36 #include "ParameterAdaptation.h"
     37 #include "Utility.h"
     38 #include <errno.h>
     39 
     40 #define base CParameterType
     41 
     42 using std::string;
     43 using std::ostringstream;
     44 
     45 CIntegerParameterType::CIntegerParameterType(const string& strName) : base(strName), _uiMin(0), _uiMax(uint32_t(-1))
     46 {
     47 }
     48 
     49 // Kind
     50 string CIntegerParameterType::getKind() const
     51 {
     52     return "IntegerParameter";
     53 }
     54 
     55 // Deal with adaption node
     56 bool CIntegerParameterType::childrenAreDynamic() const
     57 {
     58     return true;
     59 }
     60 
     61 // Element properties
     62 void CIntegerParameterType::showProperties(string& strResult) const
     63 {
     64     base::showProperties(strResult);
     65 
     66     // Sign
     67     strResult += "Signed: ";
     68     strResult += _bSigned ? "yes" : "no";
     69     strResult += "\n";
     70 
     71     // Min
     72     strResult += "Min: ";
     73     strResult += _bSigned ? CUtility::toString((int32_t)_uiMin) : CUtility::toString(_uiMin);
     74     strResult += "\n";
     75 
     76     // Max
     77     strResult += "Max: ";
     78     strResult += _bSigned ? CUtility::toString((int32_t)_uiMax) : CUtility::toString(_uiMax);
     79     strResult += "\n";
     80 
     81     // Check if there's an adaptation object available
     82     const CParameterAdaptation* pParameterAdaption = getParameterAdaptation();
     83 
     84     if (pParameterAdaption) {
     85 
     86         // Display adaptation properties
     87         strResult += "Adaptation:\n";
     88 
     89         pParameterAdaption->showProperties(strResult);
     90     }
     91 }
     92 
     93 bool CIntegerParameterType::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
     94 {
     95     // Sign
     96     _bSigned = xmlElement.getAttributeBoolean("Signed");
     97 
     98     // Size in bits
     99     uint32_t uiSizeInBits = xmlElement.getAttributeInteger("Size");
    100 
    101     // Size
    102     setSize(uiSizeInBits / 8);
    103 
    104     // Min / Max
    105     if (_bSigned) {
    106 
    107         // Signed means we have one less util bit
    108         uiSizeInBits--;
    109 
    110         if (xmlElement.hasAttribute("Min")) {
    111 
    112             _uiMin = (uint32_t)xmlElement.getAttributeSignedInteger("Min");
    113         } else {
    114 
    115             _uiMin = 1UL << uiSizeInBits;
    116 
    117         }
    118         signExtend((int32_t&)_uiMin);
    119 
    120         if (xmlElement.hasAttribute("Max")) {
    121 
    122             _uiMax = (uint32_t)xmlElement.getAttributeSignedInteger("Max");
    123 
    124             signExtend((int32_t&)_uiMax);
    125         } else {
    126 
    127             _uiMax = (1UL << uiSizeInBits) - 1;
    128         }
    129     } else {
    130         if (xmlElement.hasAttribute("Min")) {
    131 
    132             _uiMin = xmlElement.getAttributeInteger("Min");
    133         } else {
    134 
    135             _uiMin = 0;
    136         }
    137         if (xmlElement.hasAttribute("Max")) {
    138 
    139             _uiMax = xmlElement.getAttributeInteger("Max");
    140         } else {
    141 
    142             _uiMax = (uint32_t)-1L >> (8 * sizeof(uint32_t) - uiSizeInBits);
    143         }
    144     }
    145 
    146     // Base
    147     return base::fromXml(xmlElement, serializingContext);
    148 }
    149 
    150 // Conversion (tuning)
    151 bool CIntegerParameterType::toBlackboard(const string& strValue, uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
    152 {
    153     // Hexa
    154     bool bValueProvidedAsHexa = !strValue.compare(0, 2, "0x");
    155 
    156     // Get integer value from the string provided
    157     int64_t iData;
    158 
    159     if (!convertValueFromString(strValue, iData, parameterAccessContext)) {
    160 
    161         return false;
    162     }
    163 
    164     // Check against Min / Max
    165     if (_bSigned) {
    166 
    167         if (bValueProvidedAsHexa && isEncodable((uint64_t)iData, !bValueProvidedAsHexa)) {
    168 
    169             // Sign extend
    170             signExtend(iData);
    171         }
    172 
    173         if (!checkValueAgainstRange<int64_t>(strValue, iData, (int32_t)_uiMin, (int32_t)_uiMax, parameterAccessContext, bValueProvidedAsHexa)) {
    174 
    175             return false;
    176         }
    177     } else {
    178 
    179         if (!checkValueAgainstRange<uint64_t>(strValue, iData, _uiMin, _uiMax, parameterAccessContext, bValueProvidedAsHexa)) {
    180 
    181             return false;
    182         }
    183     }
    184 
    185     uiValue = (uint32_t)iData;
    186 
    187     return true;
    188 }
    189 
    190 bool CIntegerParameterType::fromBlackboard(string& strValue, const uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
    191 {
    192     // Check unsigned value is encodable
    193     assert(isEncodable(uiValue, false));
    194 
    195     // Format
    196     ostringstream strStream;
    197 
    198     // Take care of format
    199     if (parameterAccessContext.valueSpaceIsRaw() && parameterAccessContext.outputRawFormatIsHex()) {
    200 
    201         // Hexa display with unecessary bits cleared out
    202         strStream << "0x" << std::hex << std::uppercase << std::setw(getSize()*2) << std::setfill('0') << uiValue;
    203     } else {
    204 
    205         if (_bSigned) {
    206 
    207             int32_t iValue = uiValue;
    208 
    209             // Sign extend
    210             signExtend(iValue);
    211 
    212             strStream << iValue;
    213         } else {
    214 
    215             strStream << uiValue;
    216         }
    217     }
    218 
    219     strValue = strStream.str();
    220 
    221     return true;
    222 }
    223 
    224 // Value access
    225 // Integer
    226 bool CIntegerParameterType::toBlackboard(uint32_t uiUserValue, uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
    227 {
    228     if (uiUserValue < _uiMin || uiUserValue > _uiMax) {
    229 
    230         parameterAccessContext.setError("Value out of range");
    231 
    232         return false;
    233     }
    234     // Do assign
    235     uiValue = uiUserValue;
    236 
    237     return true;
    238 }
    239 
    240 bool CIntegerParameterType::fromBlackboard(uint32_t& uiUserValue, uint32_t uiValue, CParameterAccessContext& parameterAccessContext) const
    241 {
    242     (void)parameterAccessContext;
    243 
    244     // Do assign
    245     uiUserValue = uiValue;
    246 
    247     return true;
    248 }
    249 
    250 // Signed Integer
    251 bool CIntegerParameterType::toBlackboard(int32_t iUserValue, uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
    252 {
    253     if (iUserValue < (int32_t)_uiMin || iUserValue > (int32_t)_uiMax) {
    254 
    255         parameterAccessContext.setError("Value out of range");
    256 
    257         return false;
    258     }
    259     // Do assign
    260     uiValue = iUserValue;
    261 
    262     return true;
    263 }
    264 
    265 bool CIntegerParameterType::fromBlackboard(int32_t& iUserValue, uint32_t uiValue, CParameterAccessContext& parameterAccessContext) const
    266 {
    267     (void)parameterAccessContext;
    268 
    269     int32_t iValue = uiValue;
    270 
    271     // Sign extend
    272     signExtend(iValue);
    273 
    274     // Do assign
    275     iUserValue = iValue;
    276 
    277     return true;
    278 }
    279 
    280 // Double
    281 bool CIntegerParameterType::toBlackboard(double dUserValue, uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
    282 {
    283     // Check if there's an adaptation object available
    284     const CParameterAdaptation* pParameterAdaption = getParameterAdaptation();
    285 
    286     if (!pParameterAdaption) {
    287 
    288         // Reject request and let upper class handle the error
    289         return base::toBlackboard(dUserValue, uiValue, parameterAccessContext);
    290     }
    291 
    292     // Do the conversion
    293     int64_t iConvertedValue = pParameterAdaption->fromUserValue(dUserValue);
    294 
    295     // Check against range
    296     if (_bSigned) {
    297 
    298         if (iConvertedValue < (int32_t)_uiMin || iConvertedValue > (int32_t)_uiMax) {
    299 
    300             parameterAccessContext.setError("Value out of range");
    301 
    302             return false;
    303         }
    304     } else {
    305 
    306         if (iConvertedValue < _uiMin || iConvertedValue > _uiMax) {
    307 
    308             parameterAccessContext.setError("Value out of range");
    309 
    310             return false;
    311         }
    312     }
    313 
    314     // Do assign
    315     uiValue = (uint32_t)iConvertedValue;
    316 
    317     return true;
    318 }
    319 
    320 bool CIntegerParameterType::fromBlackboard(double& dUserValue, uint32_t uiValue, CParameterAccessContext& parameterAccessContext) const
    321 {
    322     // Check if there's an adaptation object available
    323     const CParameterAdaptation* pParameterAdaption = getParameterAdaptation();
    324 
    325     if (!pParameterAdaption) {
    326 
    327         // Reject request and let upper class handle the error
    328         return base::fromBlackboard(dUserValue, uiValue, parameterAccessContext);
    329     }
    330 
    331     int64_t iValueToConvert;
    332 
    333     // Deal with signed data
    334     if (_bSigned) {
    335 
    336         int32_t iValue = uiValue;
    337 
    338         signExtend(iValue);
    339 
    340         iValueToConvert = iValue;
    341     } else {
    342 
    343         iValueToConvert = uiValue;
    344     }
    345 
    346     // Do the conversion
    347     dUserValue = pParameterAdaption->toUserValue(iValueToConvert);
    348 
    349     return true;
    350 }
    351 
    352 // Default value handling (simulation only)
    353 uint32_t CIntegerParameterType::getDefaultValue() const
    354 {
    355     return _uiMin;
    356 }
    357 
    358 int CIntegerParameterType::toPlainInteger(int iSizeOptimizedData) const
    359 {
    360     if (_bSigned) {
    361 
    362         signExtend(iSizeOptimizedData);
    363     }
    364 
    365     return base::toPlainInteger(iSizeOptimizedData);
    366 }
    367 
    368 // Convert value provided by the user as a string into an int64
    369 bool CIntegerParameterType::convertValueFromString(const string& strValue, int64_t& iData, CParameterAccessContext& parameterAccessContext) const {
    370 
    371     // Reset errno to check if it is updated during the conversion (strtol/strtoul)
    372     errno = 0;
    373     char *pcStrEnd;
    374 
    375     // Convert the input string
    376     if (_bSigned) {
    377 
    378         iData = strtoll(strValue.c_str(), &pcStrEnd, 0);
    379     } else {
    380 
    381         iData = strtoull(strValue.c_str(), &pcStrEnd, 0);
    382     }
    383 
    384     // Conversion error when the input string does not contain only digits or the number is out of range (int32_t type)
    385     if (errno || (*pcStrEnd != '\0')) {
    386 
    387         string strError;
    388         strError =  "Impossible to convert value " + strValue + " for " + getKind();
    389 
    390         parameterAccessContext.setError(strError);
    391 
    392         return false;
    393     }
    394 
    395     return true;
    396 }
    397 
    398 // Range checking
    399 template <typename type> bool CIntegerParameterType::checkValueAgainstRange(const string& strValue, type value, type minValue, type maxValue, CParameterAccessContext& parameterAccessContext, bool bHexaValue) const
    400 {
    401     if (value < minValue || value > maxValue) {
    402 
    403         ostringstream strStream;
    404 
    405         strStream << "Value " << strValue << " standing out of admitted range [";
    406 
    407         if (bHexaValue) {
    408 
    409             // Format Min
    410             strStream << "0x" << std::hex << std::uppercase << std::setw(getSize()*2) << std::setfill('0') << makeEncodable(minValue);
    411             // Format Max
    412             strStream << ", 0x" << std::hex << std::uppercase << std::setw(getSize()*2) << std::setfill('0') << makeEncodable(maxValue);
    413 
    414         } else {
    415 
    416             strStream << minValue << ", " <<  maxValue;
    417         }
    418 
    419         strStream << "] for " << getKind();
    420 
    421         parameterAccessContext.setError(strStream.str());
    422 
    423         return false;
    424     }
    425     return true;
    426 }
    427 
    428 // Adaptation element retrieval
    429 const CParameterAdaptation* CIntegerParameterType::getParameterAdaptation() const
    430 {
    431     return static_cast<const CParameterAdaptation*>(findChildOfKind("Adaptation"));
    432 }
    433 
    434 // From IXmlSource
    435 void CIntegerParameterType::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
    436 {
    437     // Sign
    438     xmlElement.setAttributeBoolean("Signed", _bSigned);
    439 
    440     if (_bSigned) {
    441 
    442         // Mininmum
    443         xmlElement.setAttributeString("Min", CUtility::toString((int32_t)_uiMin));
    444 
    445         // Maximum
    446         xmlElement.setAttributeString("Max", CUtility::toString((int32_t)_uiMax));
    447 
    448     } else {
    449 
    450         // Minimum
    451         xmlElement.setAttributeString("Min", CUtility::toString(_uiMin));
    452 
    453         // Maximum
    454         xmlElement.setAttributeString("Max", CUtility::toString(_uiMax));
    455     }
    456 
    457     // Size
    458     xmlElement.setAttributeString("Size", CUtility::toString(getSize() * 8));
    459 
    460     base::toXml(xmlElement, serializingContext);
    461 
    462 }
    463