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>
getUserInputSize(const 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>
getUserInputSize(const std::vector<T> & vector)53 static size_t getUserInputSize(const std::vector<T> &vector)
54 {
55 return vector.size();
56 }
57
ElementHandle(CConfigurableElement & element,CParameterMgr & parameterMgr)58 ElementHandle::ElementHandle(CConfigurableElement &element, CParameterMgr ¶meterMgr)
59 : mElement(element), mParameterMgr(parameterMgr)
60 {
61 }
62
getName() const63 string ElementHandle::getName() const
64 {
65 return mElement.getName();
66 }
67
getSize() const68 size_t ElementHandle::getSize() const
69 {
70 return mElement.getFootPrint();
71 }
72
isParameter() const73 bool ElementHandle::isParameter() const
74 {
75 return mElement.isParameter();
76 }
77
getDescription() const78 string ElementHandle::getDescription() const
79 {
80 return mElement.getDescription();
81 }
82
83 // Parameter features
isRogue() const84 bool ElementHandle::isRogue() const
85 {
86 return mElement.isRogue();
87 }
88
isArray() const89 bool ElementHandle::isArray() const
90 {
91 return getArrayLength() != 0;
92 }
93
getArrayLength() const94 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
getPath() const104 string ElementHandle::getPath() const
105 {
106 return mElement.getPath();
107 }
108
getKind() const109 string ElementHandle::getKind() const
110 {
111 return mElement.getKind();
112 }
113
getChildren()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
getMappingData(const string & strKey,string & strValue) const129 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
getStructureAsXML(std::string & xmlSettings,std::string & error) const145 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
getAsXML(std::string & xmlValue,std::string & error) const163 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
setAsXML(const std::string & xmlValue,std::string & error)175 bool ElementHandle::setAsXML(const std::string &xmlValue, std::string &error)
176 {
177 return mParameterMgr.setSettingsAsXML(&mElement, xmlValue, error);
178 }
179
getAsBytes(std::vector<uint8_t> & bytesValue,std::string &) const180 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
setAsBytes(const std::vector<uint8_t> & bytesValue,std::string & error)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>
setAs(const T value,string & error) const197 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>
getAs(T & value,string & error) const224 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
setAsBoolean(bool value,string & error)241 bool ElementHandle::setAsBoolean(bool value, string &error)
242 {
243 return setAs(value, error);
244 }
245
getAsBoolean(bool & value,string & error) const246 bool ElementHandle::getAsBoolean(bool &value, string &error) const
247 {
248 return getAs(value, error);
249 }
250
setAsBooleanArray(const std::vector<bool> & value,string & error)251 bool ElementHandle::setAsBooleanArray(const std::vector<bool> &value, string &error)
252 {
253 return setAs(value, error);
254 }
255
getAsBooleanArray(std::vector<bool> & value,string & error) const256 bool ElementHandle::getAsBooleanArray(std::vector<bool> &value, string &error) const
257 {
258 return getAs(value, error);
259 }
260
261 // Integer Access
setAsInteger(uint32_t value,string & error)262 bool ElementHandle::setAsInteger(uint32_t value, string &error)
263 {
264 return setAs(value, error);
265 }
266
getAsInteger(uint32_t & value,string & error) const267 bool ElementHandle::getAsInteger(uint32_t &value, string &error) const
268 {
269 return getAs(value, error);
270 }
271
setAsIntegerArray(const std::vector<uint32_t> & value,string & error)272 bool ElementHandle::setAsIntegerArray(const std::vector<uint32_t> &value, string &error)
273 {
274 return setAs(value, error);
275 }
276
getAsIntegerArray(std::vector<uint32_t> & value,string & error) const277 bool ElementHandle::getAsIntegerArray(std::vector<uint32_t> &value, string &error) const
278 {
279 return getAs(value, error);
280 }
281
282 // Signed Integer Access
setAsSignedInteger(int32_t value,string & error)283 bool ElementHandle::setAsSignedInteger(int32_t value, string &error)
284 {
285 return setAs(value, error);
286 }
287
getAsSignedInteger(int32_t & value,string & error) const288 bool ElementHandle::getAsSignedInteger(int32_t &value, string &error) const
289 {
290 return getAs(value, error);
291 }
292
setAsSignedIntegerArray(const std::vector<int32_t> & value,string & error)293 bool ElementHandle::setAsSignedIntegerArray(const std::vector<int32_t> &value, string &error)
294 {
295 return setAs(value, error);
296 }
297
getAsSignedIntegerArray(std::vector<int32_t> & value,string & error) const298 bool ElementHandle::getAsSignedIntegerArray(std::vector<int32_t> &value, string &error) const
299 {
300 return getAs(value, error);
301 }
302
303 // Double Access
setAsDouble(double value,string & error)304 bool ElementHandle::setAsDouble(double value, string &error)
305 {
306 return setAs(value, error);
307 }
308
getAsDouble(double & value,string & error) const309 bool ElementHandle::getAsDouble(double &value, string &error) const
310 {
311 return getAs(value, error);
312 }
313
setAsDoubleArray(const std::vector<double> & value,string & error)314 bool ElementHandle::setAsDoubleArray(const std::vector<double> &value, string &error)
315 {
316 return setAs(value, error);
317 }
318
getAsDoubleArray(std::vector<double> & value,string & error) const319 bool ElementHandle::getAsDoubleArray(std::vector<double> &value, string &error) const
320 {
321 return getAs(value, error);
322 }
323
324 // String Access
setAsString(const string & value,string & error)325 bool ElementHandle::setAsString(const string &value, string &error)
326 {
327 return setAs(value, error);
328 }
329
getAsString(string & value,string & error) const330 bool ElementHandle::getAsString(string &value, string &error) const
331 {
332 return getAs(value, error);
333 }
334
setAsStringArray(const std::vector<string> & value,string & error)335 bool ElementHandle::setAsStringArray(const std::vector<string> &value, string &error)
336 {
337 return setAs(value, error);
338 }
339
getAsStringArray(std::vector<string> & value,string & error) const340 bool ElementHandle::getAsStringArray(std::vector<string> &value, string &error) const
341 {
342 return getAs(value, error);
343 }
344
checkGetValidity(bool asArray,string & error) const345 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
checkSetValidity(size_t arrayLength,string & error) const364 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