/* * Copyright (c) 2015, Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "ElementHandle.h" #include "ParameterAccessContext.h" #include "BaseParameter.h" #include "XmlParameterSerializingContext.h" #include "Subsystem.h" #include <assert.h> #include "ParameterMgr.h" #include <mutex> using std::string; using std::mutex; using std::lock_guard; /** @return 0 by default, ie for non overloaded types. */ template <class T> static size_t getUserInputSize(const T & /*scalar*/) { return 0; } /** @return the vector's size. */ template <class T> static size_t getUserInputSize(const std::vector<T> &vector) { return vector.size(); } ElementHandle::ElementHandle(CConfigurableElement &element, CParameterMgr ¶meterMgr) : mElement(element), mParameterMgr(parameterMgr) { } string ElementHandle::getName() const { return mElement.getName(); } size_t ElementHandle::getSize() const { return mElement.getFootPrint(); } bool ElementHandle::isParameter() const { return mElement.isParameter(); } string ElementHandle::getDescription() const { return mElement.getDescription(); } // Parameter features bool ElementHandle::isRogue() const { return mElement.isRogue(); } bool ElementHandle::isArray() const { return getArrayLength() != 0; } size_t ElementHandle::getArrayLength() const { // Only instances can be arrays, SystemClass can not, nor subsystems auto *instance = dynamic_cast<CInstanceConfigurableElement *>(&mElement); if (instance == nullptr) { return 0; } return instance->getArrayLength(); } string ElementHandle::getPath() const { return mElement.getPath(); } string ElementHandle::getKind() const { return mElement.getKind(); } std::vector<ElementHandle> ElementHandle::getChildren() { size_t nbChildren = mElement.getNbChildren(); std::vector<ElementHandle> children; children.reserve(nbChildren); for (size_t childIndex = 0; childIndex < nbChildren; ++childIndex) { auto *child = static_cast<CConfigurableElement *>(mElement.getChild(childIndex)); // Can not use emplace back as the constructor is private children.push_back({*child, mParameterMgr}); } return children; } bool ElementHandle::getMappingData(const string &strKey, string &strValue) const { const std::string *pStrValue; // Seach for the key in self and ancestors auto elements = mElement.getConfigurableElementContext(); for (auto *element : elements) if (element->getMappingData(strKey, pStrValue)) { strValue = *pStrValue; return true; } return false; } bool ElementHandle::getStructureAsXML(std::string &xmlSettings, std::string &error) const { // Use default access context for structure export CParameterAccessContext accessContext(error); return mParameterMgr.exportElementToXMLString( &mElement, mElement.getXmlElementName(), CXmlParameterSerializingContext{accessContext, error}, xmlSettings); } template <class T> struct isVector : std::false_type { }; template <class T> struct isVector<std::vector<T>> : std::true_type { }; bool ElementHandle::getAsXML(std::string &xmlValue, std::string &error) const { std::string result; if (not mParameterMgr.getSettingsAsXML(&mElement, result)) { error = result; return false; } xmlValue = result; return true; } bool ElementHandle::setAsXML(const std::string &xmlValue, std::string &error) { return mParameterMgr.setSettingsAsXML(&mElement, xmlValue, error); } bool ElementHandle::getAsBytes(std::vector<uint8_t> &bytesValue, std::string & /*error*/) const { mParameterMgr.getSettingsAsBytes(mElement, bytesValue); // Currently this operation can not fail. // Nevertheless this is more a design than intrinsic property. // Use the same error reporting pattern to avoid breaking the api in future // release if an error need to be reported (and be consistent with all other getAs*). return true; } bool ElementHandle::setAsBytes(const std::vector<uint8_t> &bytesValue, std::string &error) { return mParameterMgr.setSettingsAsBytes(mElement, bytesValue, error); } template <class T> bool ElementHandle::setAs(const T value, string &error) const { if (not checkSetValidity(getUserInputSize(value), error)) { return false; } // Safe downcast thanks to isParameter check in checkSetValidity auto ¶meter = static_cast<CBaseParameter &>(mElement); // When in tuning mode, silently skip "set" requests if (mParameterMgr.tuningModeOn()) { return true; } CParameterAccessContext parameterAccessContext(error, mParameterMgr.getParameterBlackboard()); // BaseParamere::access takes a non-const argument - therefore we need to // copy the value T copy = value; // Ensure we're safe against blackboard foreign access lock_guard<mutex> autoLock(mParameterMgr.getBlackboardMutex()); return parameter.access(copy, true, parameterAccessContext); } template <class T> bool ElementHandle::getAs(T &value, string &error) const { if (not checkGetValidity(isVector<T>::value, error)) { return false; } // Safe downcast thanks to isParameter check in checkGetValidity auto ¶meter = static_cast<const CBaseParameter &>(mElement); // Ensure we're safe against blackboard foreign access lock_guard<mutex> autoLock(mParameterMgr.getBlackboardMutex()); CParameterAccessContext parameterAccessContext(error, mParameterMgr.getParameterBlackboard()); return parameter.access(value, false, parameterAccessContext); } // Boolean access bool ElementHandle::setAsBoolean(bool value, string &error) { return setAs(value, error); } bool ElementHandle::getAsBoolean(bool &value, string &error) const { return getAs(value, error); } bool ElementHandle::setAsBooleanArray(const std::vector<bool> &value, string &error) { return setAs(value, error); } bool ElementHandle::getAsBooleanArray(std::vector<bool> &value, string &error) const { return getAs(value, error); } // Integer Access bool ElementHandle::setAsInteger(uint32_t value, string &error) { return setAs(value, error); } bool ElementHandle::getAsInteger(uint32_t &value, string &error) const { return getAs(value, error); } bool ElementHandle::setAsIntegerArray(const std::vector<uint32_t> &value, string &error) { return setAs(value, error); } bool ElementHandle::getAsIntegerArray(std::vector<uint32_t> &value, string &error) const { return getAs(value, error); } // Signed Integer Access bool ElementHandle::setAsSignedInteger(int32_t value, string &error) { return setAs(value, error); } bool ElementHandle::getAsSignedInteger(int32_t &value, string &error) const { return getAs(value, error); } bool ElementHandle::setAsSignedIntegerArray(const std::vector<int32_t> &value, string &error) { return setAs(value, error); } bool ElementHandle::getAsSignedIntegerArray(std::vector<int32_t> &value, string &error) const { return getAs(value, error); } // Double Access bool ElementHandle::setAsDouble(double value, string &error) { return setAs(value, error); } bool ElementHandle::getAsDouble(double &value, string &error) const { return getAs(value, error); } bool ElementHandle::setAsDoubleArray(const std::vector<double> &value, string &error) { return setAs(value, error); } bool ElementHandle::getAsDoubleArray(std::vector<double> &value, string &error) const { return getAs(value, error); } // String Access bool ElementHandle::setAsString(const string &value, string &error) { return setAs(value, error); } bool ElementHandle::getAsString(string &value, string &error) const { return getAs(value, error); } bool ElementHandle::setAsStringArray(const std::vector<string> &value, string &error) { return setAs(value, error); } bool ElementHandle::getAsStringArray(std::vector<string> &value, string &error) const { return getAs(value, error); } bool ElementHandle::checkGetValidity(bool asArray, string &error) const { if (not isParameter()) { error = "Can not set element " + getPath() + " as it is not a parameter."; return false; } if (asArray != isArray()) { auto toStr = [](bool array) { return array ? "an array" : "a scalar"; }; error = "Can not get \"" + getPath() + "\" as " + toStr(asArray) + " because it is " + toStr(isArray()); return false; } return true; } // Access validity bool ElementHandle::checkSetValidity(size_t arrayLength, string &error) const { // Settings a parameter necessitates the right to get it if (not checkGetValidity(arrayLength != 0, error)) { return false; } if (!isRogue()) { error = "Can not set parameter \"" + getPath() + "\" as it is not rogue."; return false; } if (arrayLength && (arrayLength != getArrayLength())) { using std::to_string; error = "Array length mismatch for \"" + getPath() + "\", expected: " + to_string(getArrayLength()) + ", got: " + to_string(arrayLength); return false; } return true; }