Home | History | Annotate | Download | only in parameter
      1 /*
      2  * Copyright (c) 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 "ElementHandle.h"
     31 #include "ParameterAccessContext.h"
     32 #include "BaseParameter.h"
     33 #include "XmlParameterSerializingContext.h"
     34 #include "Subsystem.h"
     35 #include <assert.h>
     36 #include "ParameterMgr.h"
     37 
     38 #include <mutex>
     39 
     40 using std::string;
     41 using std::mutex;
     42 using std::lock_guard;
     43 
     44 /** @return 0 by default, ie for non overloaded types. */
     45 template <class T>
     46 static size_t getUserInputSize(const T & /*scalar*/)
     47 {
     48     return 0;
     49 }
     50 
     51 /** @return the vector's size. */
     52 template <class T>
     53 static size_t getUserInputSize(const std::vector<T> &vector)
     54 {
     55     return vector.size();
     56 }
     57 
     58 ElementHandle::ElementHandle(CConfigurableElement &element, CParameterMgr &parameterMgr)
     59     : mElement(element), mParameterMgr(parameterMgr)
     60 {
     61 }
     62 
     63 string ElementHandle::getName() const
     64 {
     65     return mElement.getName();
     66 }
     67 
     68 size_t ElementHandle::getSize() const
     69 {
     70     return mElement.getFootPrint();
     71 }
     72 
     73 bool ElementHandle::isParameter() const
     74 {
     75     return mElement.isParameter();
     76 }
     77 
     78 string ElementHandle::getDescription() const
     79 {
     80     return mElement.getDescription();
     81 }
     82 
     83 // Parameter features
     84 bool ElementHandle::isRogue() const
     85 {
     86     return mElement.isRogue();
     87 }
     88 
     89 bool ElementHandle::isArray() const
     90 {
     91     return getArrayLength() != 0;
     92 }
     93 
     94 size_t ElementHandle::getArrayLength() const
     95 {
     96     // Only instances can be arrays, SystemClass can not, nor subsystems
     97     auto *instance = dynamic_cast<CInstanceConfigurableElement *>(&mElement);
     98     if (instance == nullptr) {
     99         return 0;
    100     }
    101     return instance->getArrayLength();
    102 }
    103 
    104 string ElementHandle::getPath() const
    105 {
    106     return mElement.getPath();
    107 }
    108 
    109 string ElementHandle::getKind() const
    110 {
    111     return mElement.getKind();
    112 }
    113 
    114 std::vector<ElementHandle> ElementHandle::getChildren()
    115 {
    116     size_t nbChildren = mElement.getNbChildren();
    117 
    118     std::vector<ElementHandle> children;
    119     children.reserve(nbChildren);
    120 
    121     for (size_t childIndex = 0; childIndex < nbChildren; ++childIndex) {
    122         auto *child = static_cast<CConfigurableElement *>(mElement.getChild(childIndex));
    123         // Can not use emplace back as the constructor is private
    124         children.push_back({*child, mParameterMgr});
    125     }
    126     return children;
    127 }
    128 
    129 bool ElementHandle::getMappingData(const string &strKey, string &strValue) const
    130 {
    131     const std::string *pStrValue;
    132 
    133     // Seach for the key in self and ancestors
    134     auto elements = mElement.getConfigurableElementContext();
    135 
    136     for (auto *element : elements)
    137         if (element->getMappingData(strKey, pStrValue)) {
    138             strValue = *pStrValue;
    139             return true;
    140         }
    141 
    142     return false;
    143 }
    144 
    145 bool ElementHandle::getStructureAsXML(std::string &xmlSettings, std::string &error) const
    146 {
    147     // Use default access context for structure export
    148     CParameterAccessContext accessContext(error);
    149     return mParameterMgr.exportElementToXMLString(
    150         &mElement, mElement.getXmlElementName(),
    151         CXmlParameterSerializingContext{accessContext, error}, xmlSettings);
    152 }
    153 
    154 template <class T>
    155 struct isVector : std::false_type
    156 {
    157 };
    158 template <class T>
    159 struct isVector<std::vector<T>> : std::true_type
    160 {
    161 };
    162 
    163 bool ElementHandle::getAsXML(std::string &xmlValue, std::string &error) const
    164 {
    165     std::string result;
    166     if (not mParameterMgr.getSettingsAsXML(&mElement, result)) {
    167         error = result;
    168         return false;
    169     }
    170 
    171     xmlValue = result;
    172     return true;
    173 }
    174 
    175 bool ElementHandle::setAsXML(const std::string &xmlValue, std::string &error)
    176 {
    177     return mParameterMgr.setSettingsAsXML(&mElement, xmlValue, error);
    178 }
    179 
    180 bool ElementHandle::getAsBytes(std::vector<uint8_t> &bytesValue, std::string & /*error*/) const
    181 {
    182     mParameterMgr.getSettingsAsBytes(mElement, bytesValue);
    183 
    184     // Currently this operation can not fail.
    185     // Nevertheless this is more a design than intrinsic property.
    186     // Use the same error reporting pattern to avoid breaking the api in future
    187     // release if an error need to be reported (and be consistent with all other getAs*).
    188     return true;
    189 }
    190 
    191 bool ElementHandle::setAsBytes(const std::vector<uint8_t> &bytesValue, std::string &error)
    192 {
    193     return mParameterMgr.setSettingsAsBytes(mElement, bytesValue, error);
    194 }
    195 
    196 template <class T>
    197 bool ElementHandle::setAs(const T value, string &error) const
    198 {
    199     if (not checkSetValidity(getUserInputSize(value), error)) {
    200         return false;
    201     }
    202     // Safe downcast thanks to isParameter check in checkSetValidity
    203     auto &parameter = static_cast<CBaseParameter &>(mElement);
    204 
    205     // When in tuning mode, silently skip "set" requests
    206     if (mParameterMgr.tuningModeOn()) {
    207 
    208         return true;
    209     }
    210 
    211     CParameterAccessContext parameterAccessContext(error, mParameterMgr.getParameterBlackboard());
    212 
    213     // BaseParamere::access takes a non-const argument - therefore we need to
    214     // copy the value
    215     T copy = value;
    216 
    217     // Ensure we're safe against blackboard foreign access
    218     lock_guard<mutex> autoLock(mParameterMgr.getBlackboardMutex());
    219 
    220     return parameter.access(copy, true, parameterAccessContext);
    221 }
    222 
    223 template <class T>
    224 bool ElementHandle::getAs(T &value, string &error) const
    225 {
    226     if (not checkGetValidity(isVector<T>::value, error)) {
    227         return false;
    228     }
    229     // Safe downcast thanks to isParameter check in checkGetValidity
    230     auto &parameter = static_cast<const CBaseParameter &>(mElement);
    231 
    232     // Ensure we're safe against blackboard foreign access
    233     lock_guard<mutex> autoLock(mParameterMgr.getBlackboardMutex());
    234 
    235     CParameterAccessContext parameterAccessContext(error, mParameterMgr.getParameterBlackboard());
    236 
    237     return parameter.access(value, false, parameterAccessContext);
    238 }
    239 
    240 // Boolean access
    241 bool ElementHandle::setAsBoolean(bool value, string &error)
    242 {
    243     return setAs(value, error);
    244 }
    245 
    246 bool ElementHandle::getAsBoolean(bool &value, string &error) const
    247 {
    248     return getAs(value, error);
    249 }
    250 
    251 bool ElementHandle::setAsBooleanArray(const std::vector<bool> &value, string &error)
    252 {
    253     return setAs(value, error);
    254 }
    255 
    256 bool ElementHandle::getAsBooleanArray(std::vector<bool> &value, string &error) const
    257 {
    258     return getAs(value, error);
    259 }
    260 
    261 // Integer Access
    262 bool ElementHandle::setAsInteger(uint32_t value, string &error)
    263 {
    264     return setAs(value, error);
    265 }
    266 
    267 bool ElementHandle::getAsInteger(uint32_t &value, string &error) const
    268 {
    269     return getAs(value, error);
    270 }
    271 
    272 bool ElementHandle::setAsIntegerArray(const std::vector<uint32_t> &value, string &error)
    273 {
    274     return setAs(value, error);
    275 }
    276 
    277 bool ElementHandle::getAsIntegerArray(std::vector<uint32_t> &value, string &error) const
    278 {
    279     return getAs(value, error);
    280 }
    281 
    282 // Signed Integer Access
    283 bool ElementHandle::setAsSignedInteger(int32_t value, string &error)
    284 {
    285     return setAs(value, error);
    286 }
    287 
    288 bool ElementHandle::getAsSignedInteger(int32_t &value, string &error) const
    289 {
    290     return getAs(value, error);
    291 }
    292 
    293 bool ElementHandle::setAsSignedIntegerArray(const std::vector<int32_t> &value, string &error)
    294 {
    295     return setAs(value, error);
    296 }
    297 
    298 bool ElementHandle::getAsSignedIntegerArray(std::vector<int32_t> &value, string &error) const
    299 {
    300     return getAs(value, error);
    301 }
    302 
    303 // Double Access
    304 bool ElementHandle::setAsDouble(double value, string &error)
    305 {
    306     return setAs(value, error);
    307 }
    308 
    309 bool ElementHandle::getAsDouble(double &value, string &error) const
    310 {
    311     return getAs(value, error);
    312 }
    313 
    314 bool ElementHandle::setAsDoubleArray(const std::vector<double> &value, string &error)
    315 {
    316     return setAs(value, error);
    317 }
    318 
    319 bool ElementHandle::getAsDoubleArray(std::vector<double> &value, string &error) const
    320 {
    321     return getAs(value, error);
    322 }
    323 
    324 // String Access
    325 bool ElementHandle::setAsString(const string &value, string &error)
    326 {
    327     return setAs(value, error);
    328 }
    329 
    330 bool ElementHandle::getAsString(string &value, string &error) const
    331 {
    332     return getAs(value, error);
    333 }
    334 
    335 bool ElementHandle::setAsStringArray(const std::vector<string> &value, string &error)
    336 {
    337     return setAs(value, error);
    338 }
    339 
    340 bool ElementHandle::getAsStringArray(std::vector<string> &value, string &error) const
    341 {
    342     return getAs(value, error);
    343 }
    344 
    345 bool ElementHandle::checkGetValidity(bool asArray, string &error) const
    346 {
    347     if (not isParameter()) {
    348         error = "Can not set element " + getPath() + " as it is not a parameter.";
    349         return false;
    350     }
    351 
    352     if (asArray != isArray()) {
    353 
    354         auto toStr = [](bool array) { return array ? "an array" : "a scalar"; };
    355         error = "Can not get \"" + getPath() + "\" as " + toStr(asArray) + " because it is " +
    356                 toStr(isArray());
    357         return false;
    358     }
    359 
    360     return true;
    361 }
    362 
    363 // Access validity
    364 bool ElementHandle::checkSetValidity(size_t arrayLength, string &error) const
    365 {
    366     // Settings a parameter necessitates the right to get it
    367     if (not checkGetValidity(arrayLength != 0, error)) {
    368         return false;
    369     }
    370 
    371     if (!isRogue()) {
    372 
    373         error = "Can not set parameter \"" + getPath() + "\" as it is not rogue.";
    374         return false;
    375     }
    376 
    377     if (arrayLength && (arrayLength != getArrayLength())) {
    378 
    379         using std::to_string;
    380         error = "Array length mismatch for \"" + getPath() + "\", expected: " +
    381                 to_string(getArrayLength()) + ", got: " + to_string(arrayLength);
    382         return false;
    383     }
    384 
    385     return true;
    386 }
    387