| /* |
| * 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; |
| } |