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 40using std::string; 41using std::mutex; 42using std::lock_guard; 43 44/** @return 0 by default, ie for non overloaded types. */ 45template <class T> 46static size_t getUserInputSize(const T & /*scalar*/) 47{ 48 return 0; 49} 50 51/** @return the vector's size. */ 52template <class T> 53static size_t getUserInputSize(const std::vector<T> &vector) 54{ 55 return vector.size(); 56} 57 58ElementHandle::ElementHandle(CConfigurableElement &element, CParameterMgr ¶meterMgr) 59 : mElement(element), mParameterMgr(parameterMgr) 60{ 61} 62 63string ElementHandle::getName() const 64{ 65 return mElement.getName(); 66} 67 68size_t ElementHandle::getSize() const 69{ 70 return mElement.getFootPrint(); 71} 72 73bool ElementHandle::isParameter() const 74{ 75 return mElement.isParameter(); 76} 77 78string ElementHandle::getDescription() const 79{ 80 return mElement.getDescription(); 81} 82 83// Parameter features 84bool ElementHandle::isRogue() const 85{ 86 return mElement.isRogue(); 87} 88 89bool ElementHandle::isArray() const 90{ 91 return getArrayLength() != 0; 92} 93 94size_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 104string ElementHandle::getPath() const 105{ 106 return mElement.getPath(); 107} 108 109string ElementHandle::getKind() const 110{ 111 return mElement.getKind(); 112} 113 114std::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 129bool 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 145bool 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 154template <class T> 155struct isVector : std::false_type 156{ 157}; 158template <class T> 159struct isVector<std::vector<T>> : std::true_type 160{ 161}; 162 163bool 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 175bool ElementHandle::setAsXML(const std::string &xmlValue, std::string &error) 176{ 177 return mParameterMgr.setSettingsAsXML(&mElement, xmlValue, error); 178} 179 180bool 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 191bool ElementHandle::setAsBytes(const std::vector<uint8_t> &bytesValue, std::string &error) 192{ 193 return mParameterMgr.setSettingsAsBytes(mElement, bytesValue, error); 194} 195 196template <class T> 197bool 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 ¶meter = 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 223template <class T> 224bool 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 ¶meter = 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 241bool ElementHandle::setAsBoolean(bool value, string &error) 242{ 243 return setAs(value, error); 244} 245 246bool ElementHandle::getAsBoolean(bool &value, string &error) const 247{ 248 return getAs(value, error); 249} 250 251bool ElementHandle::setAsBooleanArray(const std::vector<bool> &value, string &error) 252{ 253 return setAs(value, error); 254} 255 256bool ElementHandle::getAsBooleanArray(std::vector<bool> &value, string &error) const 257{ 258 return getAs(value, error); 259} 260 261// Integer Access 262bool ElementHandle::setAsInteger(uint32_t value, string &error) 263{ 264 return setAs(value, error); 265} 266 267bool ElementHandle::getAsInteger(uint32_t &value, string &error) const 268{ 269 return getAs(value, error); 270} 271 272bool ElementHandle::setAsIntegerArray(const std::vector<uint32_t> &value, string &error) 273{ 274 return setAs(value, error); 275} 276 277bool ElementHandle::getAsIntegerArray(std::vector<uint32_t> &value, string &error) const 278{ 279 return getAs(value, error); 280} 281 282// Signed Integer Access 283bool ElementHandle::setAsSignedInteger(int32_t value, string &error) 284{ 285 return setAs(value, error); 286} 287 288bool ElementHandle::getAsSignedInteger(int32_t &value, string &error) const 289{ 290 return getAs(value, error); 291} 292 293bool ElementHandle::setAsSignedIntegerArray(const std::vector<int32_t> &value, string &error) 294{ 295 return setAs(value, error); 296} 297 298bool ElementHandle::getAsSignedIntegerArray(std::vector<int32_t> &value, string &error) const 299{ 300 return getAs(value, error); 301} 302 303// Double Access 304bool ElementHandle::setAsDouble(double value, string &error) 305{ 306 return setAs(value, error); 307} 308 309bool ElementHandle::getAsDouble(double &value, string &error) const 310{ 311 return getAs(value, error); 312} 313 314bool ElementHandle::setAsDoubleArray(const std::vector<double> &value, string &error) 315{ 316 return setAs(value, error); 317} 318 319bool ElementHandle::getAsDoubleArray(std::vector<double> &value, string &error) const 320{ 321 return getAs(value, error); 322} 323 324// String Access 325bool ElementHandle::setAsString(const string &value, string &error) 326{ 327 return setAs(value, error); 328} 329 330bool ElementHandle::getAsString(string &value, string &error) const 331{ 332 return getAs(value, error); 333} 334 335bool ElementHandle::setAsStringArray(const std::vector<string> &value, string &error) 336{ 337 return setAs(value, error); 338} 339 340bool ElementHandle::getAsStringArray(std::vector<string> &value, string &error) const 341{ 342 return getAs(value, error); 343} 344 345bool 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 364bool 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