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 "EnumParameterType.h"
     31 #include <stdlib.h>
     32 #include <sstream>
     33 #include <iomanip>
     34 #include <ctype.h>
     35 #include <assert.h>
     36 #include "ParameterAccessContext.h"
     37 #include "EnumValuePair.h"
     38 #include "Utility.h"
     39 #include <errno.h>
     40 
     41 #define base CParameterType
     42 
     43 using std::string;
     44 
     45 CEnumParameterType::CEnumParameterType(const string& strName) : base(strName)
     46 {
     47 }
     48 
     49 string CEnumParameterType::getKind() const
     50 {
     51     return "EnumParameter";
     52 }
     53 
     54 bool CEnumParameterType::childrenAreDynamic() const
     55 {
     56     return true;
     57 }
     58 
     59 // Element properties
     60 void CEnumParameterType::showProperties(string& strResult) const
     61 {
     62     base::showProperties(strResult);
     63 
     64     strResult += "Value Pairs:\n";
     65 
     66     // Show all value pairs
     67     size_t uiChild;
     68     size_t uiNbChildren = getNbChildren();
     69 
     70     for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
     71 
     72         const CEnumValuePair* pValuePair = static_cast<const CEnumValuePair*>(getChild(uiChild));
     73 
     74         strResult += "\tLiteral: \"";
     75         strResult += pValuePair->getName();
     76         strResult += "\", Numerical: ";
     77         strResult += pValuePair->getNumericalAsString();
     78         strResult += "\n";
     79     }
     80 }
     81 
     82 bool CEnumParameterType::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
     83 {
     84     // Size in bits
     85     uint32_t uiSizeInBits = xmlElement.getAttributeInteger("Size");
     86 
     87     // Size
     88     setSize(uiSizeInBits / 8);
     89 
     90     // Base
     91     return base::fromXml(xmlElement, serializingContext);
     92 }
     93 
     94 // Conversion (tuning)
     95 bool CEnumParameterType::toBlackboard(const string& strValue, uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
     96 {
     97     int64_t iData;
     98 
     99     if (isNumber(strValue)) {
    100 
    101         /// Numerical value provided
    102 
    103         // Hexa
    104         bool bValueProvidedAsHexa = !strValue.compare(0, 2, "0x");
    105 
    106         errno = 0;
    107         char *pcStrEnd;
    108 
    109         // Get value
    110         iData = strtoll(strValue.c_str(), &pcStrEnd, 0);
    111 
    112         // Conversion error when the input string does not contain any digit or the number is out of range (int32_t type)
    113         bool bConversionSucceeded = !errno && (strValue.c_str() != pcStrEnd);
    114 
    115         // Check validity against type
    116         if (!checkValueAgainstRange(strValue, iData, parameterAccessContext, bValueProvidedAsHexa, bConversionSucceeded)) {
    117 
    118             return false;
    119         }
    120 
    121         if (bValueProvidedAsHexa) {
    122 
    123             // Sign extend
    124             signExtend(iData);
    125         }
    126 
    127         // Check validity against lexical space
    128         string strError;
    129         if (!isValid(iData, parameterAccessContext)) {
    130 
    131             parameterAccessContext.setError(strError);
    132 
    133             return false;
    134         }
    135     } else {
    136         /// Literal value provided
    137 
    138         // Check validity against lexical space
    139         int iNumerical;
    140         if (!getNumerical(strValue, iNumerical)) {
    141 
    142             parameterAccessContext.setError("Provided value not part of lexical space");
    143 
    144             return false;
    145         }
    146         iData = iNumerical;
    147 
    148         // Check validity against type
    149         if (!checkValueAgainstRange(strValue, iData, parameterAccessContext, false, isEncodable((uint64_t)iData, true))) {
    150 
    151             return false;
    152         }
    153     }
    154 
    155     // Return data
    156     uiValue = (uint32_t)iData;
    157 
    158     return true;
    159 }
    160 
    161 // Range checking
    162 bool CEnumParameterType::checkValueAgainstRange(const string& strValue, int64_t value, CParameterAccessContext& parameterAccessContext, bool bHexaValue, bool bConversionSucceeded) const
    163 {
    164     // Enums are always signed, it means we have one less util bit
    165     int64_t maxValue = getMaxValue<uint64_t>();
    166     int64_t minValue = -maxValue - 1;
    167 
    168     if (!bConversionSucceeded || value < minValue || value > maxValue) {
    169 
    170 	std::ostringstream strStream;
    171 
    172         strStream << "Value " << strValue << " standing out of admitted range [";
    173 
    174         if (bHexaValue) {
    175 
    176             // Format Min
    177             strStream << "0x" << std::hex << std::uppercase << std::setw(getSize()*2) << std::setfill('0') << makeEncodable(minValue);
    178             // Format Max
    179             strStream << ", 0x" << std::hex << std::uppercase << std::setw(getSize()*2) << std::setfill('0') << makeEncodable(maxValue);
    180 
    181         } else {
    182 
    183             strStream << minValue << ", " <<  maxValue;
    184         }
    185 
    186         strStream << "] for " << getKind();
    187 
    188         parameterAccessContext.setError(strStream.str());
    189 
    190         return false;
    191     }
    192     return true;
    193 }
    194 
    195 bool CEnumParameterType::fromBlackboard(string& strValue, const uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
    196 {
    197     // Take care of format
    198     if (parameterAccessContext.valueSpaceIsRaw()) {
    199 
    200         // Format
    201 	std::ostringstream strStream;
    202 
    203         // Numerical format requested
    204         if (parameterAccessContext.outputRawFormatIsHex()) {
    205 
    206             // Hexa display with unecessary bits cleared out
    207             strStream << "0x" << std::hex << std::uppercase << std::setw(getSize()*2) << std::setfill('0') << makeEncodable(uiValue);
    208 
    209             strValue = strStream.str();
    210         } else {
    211 
    212             // Integer display
    213             int32_t iValue = uiValue;
    214 
    215             // Sign extend
    216             signExtend(iValue);
    217 
    218             strStream << iValue;
    219 
    220             strValue = strStream.str();
    221         }
    222     } else {
    223 
    224         // Integer display
    225         int32_t iValue = uiValue;
    226 
    227         // Sign extend
    228         signExtend(iValue);
    229 
    230         // Literal display requested (should succeed)
    231         getLiteral(iValue, strValue);
    232     }
    233     return true;
    234 }
    235 
    236 // Value access
    237 bool CEnumParameterType::toBlackboard(int32_t iUserValue, uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
    238 {
    239     if (!isValid(iUserValue, parameterAccessContext)) {
    240 
    241         return false;
    242     }
    243     uiValue = iUserValue;
    244 
    245     return true;
    246 }
    247 
    248 bool CEnumParameterType::fromBlackboard(int32_t& iUserValue, uint32_t uiValue, CParameterAccessContext& parameterAccessContext) const
    249 {
    250     (void)parameterAccessContext;
    251 
    252     int32_t iValue = uiValue;
    253 
    254     // Sign extend
    255     signExtend(iValue);
    256 
    257     iUserValue = iValue;
    258 
    259     return true;
    260 }
    261 
    262 // Default value handling (simulation only)
    263 uint32_t CEnumParameterType::getDefaultValue() const
    264 {
    265     if (!getNbChildren()) {
    266 
    267         return 0;
    268     }
    269 
    270     // Return first available numerical
    271     return static_cast<const CEnumValuePair*>(getChild(0))->getNumerical();
    272 }
    273 
    274 // Check string is a number
    275 bool CEnumParameterType::isNumber(const string& strValue)
    276 {
    277     char cFirst = strValue[0];
    278 
    279     return isdigit(cFirst) || cFirst == '+' || cFirst == '-';
    280 }
    281 
    282 // Literal - numerical conversions
    283 bool CEnumParameterType::getLiteral(int32_t iNumerical, string& strLiteral) const
    284 {
    285     size_t uiChild;
    286     size_t uiNbChildren = getNbChildren();
    287 
    288     for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
    289 
    290         const CEnumValuePair* pValuePair = static_cast<const CEnumValuePair*>(getChild(uiChild));
    291 
    292         if (pValuePair->getNumerical() == iNumerical) {
    293 
    294             strLiteral = pValuePair->getName();
    295 
    296             return true;
    297         }
    298     }
    299 
    300     return false;
    301 }
    302 
    303 bool CEnumParameterType::getNumerical(const string& strLiteral, int& iNumerical) const
    304 {
    305     size_t uiChild;
    306     size_t uiNbChildren = getNbChildren();
    307 
    308     for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
    309 
    310         const CEnumValuePair* pValuePair = static_cast<const CEnumValuePair*>(getChild(uiChild));
    311 
    312         if (pValuePair->getName() == strLiteral) {
    313 
    314             iNumerical = pValuePair->getNumerical();
    315 
    316             return true;
    317         }
    318     }
    319 
    320     return false;
    321 }
    322 
    323 // Numerical validity of the enum value
    324 bool CEnumParameterType::isValid(int iNumerical, CParameterAccessContext& parameterAccessContext) const
    325 {
    326     // Check that the value is part of the allowed values for this kind of enum
    327     size_t uiChild;
    328     size_t uiNbChildren = getNbChildren();
    329 
    330     for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
    331 
    332         const CEnumValuePair* pValuePair = static_cast<const CEnumValuePair*>(getChild(uiChild));
    333 
    334         if (pValuePair->getNumerical() == iNumerical) {
    335 
    336             return true;
    337         }
    338     }
    339 
    340     parameterAccessContext.setError("Provided value not part of numerical space");
    341 
    342     return false;
    343 }
    344 // From IXmlSource
    345 void CEnumParameterType::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
    346 {
    347     // Size
    348     xmlElement.setAttributeString("Size", CUtility::toString(getSize() * 8));
    349 
    350     base::toXml(xmlElement, serializingContext);
    351 }
    352