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 ¶meterMgr) 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 ¶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 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 ¶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 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