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 "ArrayParameter.h"
     31 #include <sstream> // for istringstream
     32 #include "Tokenizer.h"
     33 #include "ParameterType.h"
     34 #include "ParameterAccessContext.h"
     35 #include "ConfigurationAccessContext.h"
     36 #include "ParameterBlackboard.h"
     37 #include "Utility.h"
     38 #include <assert.h>
     39 
     40 #define base CParameter
     41 
     42 using std::string;
     43 
     44 CArrayParameter::CArrayParameter(const string &strName, const CTypeElement *pTypeElement)
     45     : base(strName, pTypeElement)
     46 {
     47 }
     48 
     49 size_t CArrayParameter::getFootPrint() const
     50 {
     51     return getSize() * getArrayLength();
     52 }
     53 
     54 // Array length
     55 size_t CArrayParameter::getArrayLength() const
     56 {
     57     return getTypeElement()->getArrayLength();
     58 }
     59 
     60 // Element properties
     61 void CArrayParameter::showProperties(string &strResult) const
     62 {
     63     base::showProperties(strResult);
     64 
     65     // Array length
     66     strResult += "Array length: ";
     67     strResult += std::to_string(getArrayLength());
     68     strResult += "\n";
     69 }
     70 
     71 // User set/get
     72 bool CArrayParameter::accessValue(CPathNavigator &pathNavigator, string &strValue, bool bSet,
     73                                   CParameterAccessContext &parameterAccessContext) const
     74 {
     75     size_t index;
     76 
     77     if (!getIndex(pathNavigator, index, parameterAccessContext)) {
     78 
     79         return false;
     80     }
     81 
     82     if (bSet) {
     83         // Set
     84         if (index == (size_t)-1) {
     85 
     86             // No index provided, start with 0
     87             index = 0;
     88         }
     89 
     90         // Actually set values
     91         if (!setValues(index, getOffset() - parameterAccessContext.getBaseOffset(), strValue,
     92                        parameterAccessContext)) {
     93             return false;
     94         }
     95 
     96         // Synchronize
     97         if (!sync(parameterAccessContext)) {
     98 
     99             appendParameterPathToError(parameterAccessContext);
    100             return false;
    101         }
    102     } else {
    103         // Get
    104         if (index == (size_t)-1) {
    105 
    106             // Whole array requested
    107             strValue = getValues(getOffset() - parameterAccessContext.getBaseOffset(),
    108                                  parameterAccessContext);
    109 
    110         } else {
    111             // Scalar requested
    112             CParameter::doGetValue(strValue, getOffset() + index * getSize(),
    113                                    parameterAccessContext);
    114         }
    115     }
    116 
    117     return true;
    118 }
    119 
    120 /// Actual parameter access
    121 // String access
    122 bool CArrayParameter::doSetValue(const string &value, size_t offset,
    123                                  CParameterAccessContext &parameterAccessContext) const
    124 {
    125     return setValues(0, offset, value, parameterAccessContext);
    126 }
    127 
    128 void CArrayParameter::doGetValue(string &value, size_t offset,
    129                                  CParameterAccessContext &parameterAccessContext) const
    130 {
    131     // Whole array requested
    132     value = getValues(offset, parameterAccessContext);
    133 }
    134 
    135 // Boolean
    136 bool CArrayParameter::access(std::vector<bool> &abValues, bool bSet,
    137                              CParameterAccessContext &parameterAccessContext) const
    138 {
    139     return accessValues(abValues, bSet, parameterAccessContext);
    140 }
    141 
    142 // Integer
    143 bool CArrayParameter::access(std::vector<uint32_t> &auiValues, bool bSet,
    144                              CParameterAccessContext &parameterAccessContext) const
    145 {
    146     return accessValues(auiValues, bSet, parameterAccessContext);
    147 }
    148 
    149 // Signed Integer Access
    150 bool CArrayParameter::access(std::vector<int32_t> &aiValues, bool bSet,
    151                              CParameterAccessContext &parameterAccessContext) const
    152 {
    153     return accessValues(aiValues, bSet, parameterAccessContext);
    154 }
    155 
    156 // Double Access
    157 bool CArrayParameter::access(std::vector<double> &adValues, bool bSet,
    158                              CParameterAccessContext &parameterAccessContext) const
    159 {
    160     return accessValues(adValues, bSet, parameterAccessContext);
    161 }
    162 
    163 // String Access
    164 bool CArrayParameter::access(std::vector<string> &astrValues, bool bSet,
    165                              CParameterAccessContext &parameterAccessContext) const
    166 {
    167     return accessValues(astrValues, bSet, parameterAccessContext);
    168 }
    169 
    170 // Dump
    171 string CArrayParameter::logValue(CParameterAccessContext &context) const
    172 {
    173     // Dump values
    174     return getValues(0, context);
    175 }
    176 
    177 // Used for simulation and virtual subsystems
    178 void CArrayParameter::setDefaultValues(CParameterAccessContext &parameterAccessContext) const
    179 {
    180     // Get default value from type
    181     uint32_t uiDefaultValue =
    182         static_cast<const CParameterType *>(getTypeElement())->getDefaultValue();
    183 
    184     // Write blackboard
    185     CParameterBlackboard *pBlackboard = parameterAccessContext.getParameterBlackboard();
    186 
    187     // Process
    188     size_t valueIndex;
    189     size_t size = getSize();
    190     size_t offset = getOffset();
    191     size_t arrayLength = getArrayLength();
    192 
    193     for (valueIndex = 0; valueIndex < arrayLength; valueIndex++) {
    194 
    195         // Beware this code works on little endian architectures only!
    196         pBlackboard->writeInteger(&uiDefaultValue, size, offset);
    197 
    198         offset += size;
    199     }
    200 }
    201 
    202 // Index from path
    203 bool CArrayParameter::getIndex(CPathNavigator &pathNavigator, size_t &index,
    204                                CParameterAccessContext &parameterAccessContext) const
    205 {
    206     index = (size_t)-1;
    207 
    208     string *pStrChildName = pathNavigator.next();
    209 
    210     if (pStrChildName) {
    211 
    212         // Check index is numeric
    213         std::istringstream iss(*pStrChildName);
    214 
    215         iss >> index;
    216 
    217         if (!iss) {
    218 
    219             parameterAccessContext.setError("Expected numerical expression as last item in " +
    220                                             pathNavigator.getCurrentPath());
    221 
    222             return false;
    223         }
    224 
    225         if (index >= getArrayLength()) {
    226             std::ostringstream oss;
    227 
    228             oss << "Provided index out of range (max is " << getArrayLength() - 1 << ")";
    229 
    230             parameterAccessContext.setError(oss.str());
    231 
    232             return false;
    233         }
    234 
    235         // Check no other item provided in path
    236         pStrChildName = pathNavigator.next();
    237 
    238         if (pStrChildName) {
    239 
    240             // Should be leaf element
    241             parameterAccessContext.setError("Path not found: " + pathNavigator.getCurrentPath());
    242 
    243             return false;
    244         }
    245     }
    246 
    247     return true;
    248 }
    249 
    250 // Common set value processing
    251 bool CArrayParameter::setValues(size_t uiStartIndex, size_t offset, const string &strValue,
    252                                 CParameterAccessContext &parameterAccessContext) const
    253 {
    254     // Deal with value(s)
    255     Tokenizer tok(strValue, Tokenizer::defaultDelimiters + ",");
    256 
    257     std::vector<string> astrValues = tok.split();
    258     size_t nbValues = astrValues.size();
    259 
    260     // Check number of provided values
    261     if (nbValues + uiStartIndex > getArrayLength()) {
    262 
    263         // Out of bounds
    264         parameterAccessContext.setError("Too many values provided");
    265 
    266         return false;
    267     }
    268 
    269     // Process
    270     size_t valueIndex;
    271     size_t size = getSize();
    272     offset += uiStartIndex * size;
    273 
    274     for (valueIndex = 0; valueIndex < nbValues; valueIndex++) {
    275 
    276         if (!doSet(astrValues[valueIndex], offset, parameterAccessContext)) {
    277 
    278             // Append parameter path to error
    279             parameterAccessContext.appendToError(" " + getPath() + "/" +
    280                                                  std::to_string(valueIndex + uiStartIndex));
    281 
    282             return false;
    283         }
    284 
    285         offset += size;
    286     }
    287     return true;
    288 }
    289 
    290 // Common get value processing
    291 string CArrayParameter::getValues(size_t offset,
    292                                   CParameterAccessContext &parameterAccessContext) const
    293 {
    294     size_t size = getSize();
    295     size_t arrayLength = getArrayLength();
    296 
    297     string output;
    298 
    299     bool bFirst = true;
    300 
    301     for (size_t valueIndex = 0; valueIndex < arrayLength; valueIndex++) {
    302         string strReadValue;
    303 
    304         doGet(strReadValue, offset, parameterAccessContext);
    305 
    306         if (!bFirst) {
    307 
    308             output += " ";
    309         } else {
    310 
    311             bFirst = false;
    312         }
    313 
    314         output += strReadValue;
    315 
    316         offset += size;
    317     }
    318 
    319     return output;
    320 }
    321 
    322 // Generic Access
    323 template <typename type>
    324 bool CArrayParameter::accessValues(std::vector<type> &values, bool bSet,
    325                                    CParameterAccessContext &parameterAccessContext) const
    326 {
    327     if (bSet) {
    328 
    329         // Set Value
    330         if (!setValues(values, parameterAccessContext)) {
    331 
    332             appendParameterPathToError(parameterAccessContext);
    333             return false;
    334         }
    335         if (!sync(parameterAccessContext)) {
    336 
    337             appendParameterPathToError(parameterAccessContext);
    338             return false;
    339         }
    340     } else {
    341         // Get Value
    342         if (!getValues(values, parameterAccessContext)) {
    343 
    344             appendParameterPathToError(parameterAccessContext);
    345             return false;
    346         }
    347     }
    348     return true;
    349 }
    350 
    351 template <typename type>
    352 bool CArrayParameter::setValues(const std::vector<type> &values,
    353                                 CParameterAccessContext &parameterAccessContext) const
    354 {
    355     size_t nbValues = getArrayLength();
    356     size_t size = getSize();
    357     size_t offset = getOffset();
    358 
    359     assert(values.size() == nbValues);
    360 
    361     // Process
    362     for (size_t valueIndex = 0; valueIndex < nbValues; valueIndex++) {
    363 
    364         if (!doSet(values[valueIndex], offset, parameterAccessContext)) {
    365 
    366             return false;
    367         }
    368 
    369         offset += size;
    370     }
    371 
    372     return true;
    373 }
    374 
    375 template <typename type>
    376 bool CArrayParameter::getValues(std::vector<type> &values,
    377                                 CParameterAccessContext &parameterAccessContext) const
    378 {
    379     size_t nbValues = getArrayLength();
    380     size_t size = getSize();
    381     size_t offset = getOffset();
    382 
    383     values.clear();
    384 
    385     for (size_t valueIndex = 0; valueIndex < nbValues; valueIndex++) {
    386         type readValue;
    387 
    388         if (!doGet(readValue, offset, parameterAccessContext)) {
    389 
    390             return false;
    391         }
    392 
    393         values.push_back(readValue);
    394 
    395         offset += size;
    396     }
    397     return true;
    398 }
    399 
    400 template <typename type>
    401 bool CArrayParameter::doSet(type value, size_t offset,
    402                             CParameterAccessContext &parameterAccessContext) const
    403 {
    404     uint32_t uiData;
    405 
    406     if (!static_cast<const CParameterType *>(getTypeElement())
    407              ->toBlackboard(value, uiData, parameterAccessContext)) {
    408 
    409         return false;
    410     }
    411     // Write blackboard
    412     CParameterBlackboard *pBlackboard = parameterAccessContext.getParameterBlackboard();
    413 
    414     // Beware this code works on little endian architectures only!
    415     pBlackboard->writeInteger(&uiData, getSize(), offset);
    416 
    417     return true;
    418 }
    419 
    420 template <typename type>
    421 bool CArrayParameter::doGet(type &value, size_t offset,
    422                             CParameterAccessContext &parameterAccessContext) const
    423 {
    424     uint32_t uiData = 0;
    425 
    426     // Read blackboard
    427     const CParameterBlackboard *pBlackboard = parameterAccessContext.getParameterBlackboard();
    428 
    429     // Beware this code works on little endian architectures only!
    430     pBlackboard->readInteger(&uiData, getSize(), offset);
    431 
    432     return static_cast<const CParameterType *>(getTypeElement())
    433         ->fromBlackboard(value, uiData, parameterAccessContext);
    434 }
    435