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
31 #include "ParameterFramework.h"
32 #include <ParameterMgrPlatformConnector.h>
33
34 #include <iostream>
35 #include <limits>
36 #include <string>
37 #include <map>
38
39 #include <cassert>
40 #include <cstring>
41 #include <cstdlib>
42
43 using std::string;
44
45 /** Rename long pfw types to short ones in pfw namespace. */
46 namespace pfw
47 {
48 typedef ISelectionCriterionInterface Criterion;
49 typedef std::map<string, Criterion *> Criteria;
50 typedef CParameterMgrPlatformConnector Pfw;
51 }
52
53 /** Class to abstract the boolean+string status api. */
54 class Status
55 {
56 public:
57 /** Fail without an instance of status. */
failure()58 static bool failure() { return false; }
59 /** Fail with the given error msg. */
failure(const string & msg)60 bool failure(const string &msg) { mMsg = msg; return false; }
61 /** Success (no error message). */
success()62 bool success() { mMsg.clear(); return true; }
63
64 /** Forward a status operation.
65 * @param success[in] the operaton status to forward
66 * or forward a previous failure if omitted
67 */
forward(bool success=false)68 bool forward(bool success = false) {
69 if (success) { mMsg.clear(); }
70 return success;
71 }
72 /** Error message accessors.
73 *
74 * Pfw api requires to provide a reference to a string in order
75 * for it to log. This function provide a reference to a string that
76 * will be added to the error message on failure.
77 */
msg()78 string &msg() { return mMsg; }
79 private:
80 string mMsg;
81 };
82
83 ///////////////////////////////
84 ///////////// Log /////////////
85 ///////////////////////////////
86
87 /** Default log callback. Log to cout or cerr depending on level. */
defaultLogCb(void *,PfwLogLevel level,const char * logLine)88 static void defaultLogCb(void *, PfwLogLevel level, const char *logLine) {
89 switch (level) {
90 case pfwLogInfo:
91 std::cout << logLine << std::endl;
92 break;
93 case pfwLogWarning:
94 std::cerr << logLine << std::endl;
95 break;
96 };
97 }
98
99 static PfwLogger defaultLogger = { NULL, &defaultLogCb };
100
101 class LogWrapper : public CParameterMgrPlatformConnector::ILogger
102 {
103 public:
LogWrapper(const PfwLogger & logger)104 LogWrapper(const PfwLogger &logger) : mLogger(logger) {}
LogWrapper()105 LogWrapper() : mLogger() {}
~LogWrapper()106 virtual ~LogWrapper() {}
107 private:
log(bool bIsWarning,const string & strLog)108 virtual void log(bool bIsWarning, const string &strLog)
109 {
110 // A LogWrapper should NOT be register to the pfw (thus log called)
111 // if logCb is NULL.
112 assert(mLogger.logCb != NULL);
113 mLogger.logCb(mLogger.userCtx,
114 bIsWarning ? pfwLogWarning : pfwLogInfo,
115 strLog.c_str());
116 }
117 PfwLogger mLogger;
118 };
119
120 ///////////////////////////////
121 ///////////// Core ////////////
122 ///////////////////////////////
123
124 struct PfwHandler_
125 {
126 void setLogger(const PfwLogger *logger);
127 bool createCriteria(const PfwCriterion criteria[], size_t criterionNb);
128
129 pfw::Criteria criteria;
130 pfw::Pfw *pfw;
131 /** Status of the last called function.
132 * Is mutable because even a const function can fail.
133 */
134 mutable Status lastStatus;
135 private:
136 LogWrapper mLogger;
137 };
138
139
pfwCreate()140 PfwHandler *pfwCreate()
141 {
142 return new PfwHandler();
143 }
144
pfwDestroy(PfwHandler * handle)145 void pfwDestroy(PfwHandler *handle)
146 {
147 if(handle != NULL and handle->pfw != NULL) {
148 delete handle->pfw;
149 }
150 delete handle;
151 }
152
setLogger(const PfwLogger * logger)153 void PfwHandler::setLogger(const PfwLogger *logger)
154 {
155 if (logger != NULL and logger->logCb == NULL) {
156 return; // There is no callback, do not log => do not add a logger
157 }
158 mLogger = logger != NULL ? *logger : defaultLogger;
159 pfw->setLogger(&mLogger);
160 }
161
162
createCriteria(const PfwCriterion criteriaArray[],size_t criterionNb)163 bool PfwHandler::createCriteria(const PfwCriterion criteriaArray[], size_t criterionNb)
164 {
165 Status &status = lastStatus;
166 // Add criteria
167 for (size_t criterionIndex = 0; criterionIndex < criterionNb; ++criterionIndex) {
168 const PfwCriterion &criterion = criteriaArray[criterionIndex];
169 if (criterion.name == NULL) {
170 return status.failure("Criterion name is NULL");
171 }
172 if (criterion.values == NULL) {
173 return status.failure("Criterion values is NULL");
174 }
175 // Check that the criterion does not exist
176 if (criteria.find(criterion.name) != criteria.end()) {
177 return status.failure("Criterion \"" + string(criterion.name) +
178 "\" already exist");
179 }
180
181 // Create criterion type
182 ISelectionCriterionTypeInterface *type =
183 pfw->createSelectionCriterionType(criterion.inclusive);
184 assert(type != NULL);
185 // Add criterion values
186 for (size_t valueIndex = 0; criterion.values[valueIndex] != NULL; ++valueIndex) {
187 int value;
188 if (criterion.inclusive) {
189 // Check that (int)1 << valueIndex would not overflow (UB)
190 if(std::numeric_limits<int>::max() >> valueIndex == 0) {
191 return status.failure("Too many values for criterion " +
192 string(criterion.name));
193 }
194 value = 1 << valueIndex;
195 } else {
196 value = valueIndex;
197 }
198 const char * valueName = criterion.values[valueIndex];
199 if(not type->addValuePair(value, valueName)) {
200 return status.failure("Could not add value " + string(valueName) +
201 " to criterion " + criterion.name);
202 }
203 }
204 // Create criterion and add it to the pfw
205 criteria[criterion.name] = pfw->createSelectionCriterion(criterion.name, type);
206 }
207 return status.success();
208 }
209
210
pfwStart(PfwHandler * handle,const char * configPath,const PfwCriterion criteria[],size_t criterionNb,const PfwLogger * logger)211 bool pfwStart(PfwHandler *handle, const char *configPath,
212 const PfwCriterion criteria[], size_t criterionNb,
213 const PfwLogger *logger)
214 {
215 // Check that the api is correctly used
216 if (handle == NULL) { return Status::failure(); }
217 Status &status = handle->lastStatus;
218
219 if (handle->pfw != NULL) {
220 return status.failure("Can not start an already started parameter framework");
221 }
222 if (configPath == NULL) {
223 return status.failure("char *configPath is NULL, "
224 "while starting the parameter framework");
225 }
226 if (criteria == NULL) {
227 return status.failure("char *criteria is NULL, "
228 "while starting the parameter framework "
229 "(config path is " + string(configPath) + ")");
230 }
231 // Create a pfw
232 handle->pfw = new CParameterMgrPlatformConnector(configPath);
233
234 handle->setLogger(logger);
235
236 if (not handle->createCriteria(criteria, criterionNb)) {
237 return status.failure();
238 }
239
240 return status.forward(handle->pfw->start(status.msg()));
241 }
242
pfwGetLastError(const PfwHandler * handle)243 const char *pfwGetLastError(const PfwHandler *handle)
244 {
245 return handle == NULL ? NULL : handle->lastStatus.msg().c_str();
246 }
247
getCriterion(const pfw::Criteria & criteria,const string & name)248 static pfw::Criterion *getCriterion(const pfw::Criteria &criteria,
249 const string &name)
250 {
251 pfw::Criteria::const_iterator it = criteria.find(name);
252 return it == criteria.end() ? NULL : it->second;
253 }
254
pfwSetCriterion(PfwHandler * handle,const char name[],int value)255 bool pfwSetCriterion(PfwHandler *handle, const char name[], int value)
256 {
257 if (handle == NULL) { return Status::failure(); }
258 Status &status = handle->lastStatus;
259 if (name == NULL) {
260 return status.failure("char *name of the criterion is NULL, "
261 "while setting a criterion.");
262 }
263 if (handle->pfw == NULL) {
264 return status.failure("Can not set criterion \"" + string(name) +
265 "\" as the parameter framework is not started.");
266 }
267 pfw::Criterion *criterion = getCriterion(handle->criteria, name);
268 if (criterion == NULL) {
269 return status.failure("Can not set criterion " + string(name) + " as does not exist");
270 }
271 criterion->setCriterionState(value);
272 return status.success();
273 }
pfwGetCriterion(const PfwHandler * handle,const char name[],int * value)274 bool pfwGetCriterion(const PfwHandler *handle, const char name[], int *value)
275 {
276 if (handle == NULL) { return Status::failure(); }
277 Status &status = handle->lastStatus;
278 if (name == NULL) {
279 return status.failure("char *name of the criterion is NULL, "
280 "while getting a criterion.");
281 }
282 if (handle->pfw == NULL) {
283 return status.failure("Can not get criterion \"" + string(name) +
284 "\" as the parameter framework is not started.");
285 }
286 if (value == NULL) {
287 return status.failure("Can not get criterion \"" + string(name) +
288 "\" as the out value is NULL.");
289 }
290 pfw::Criterion *criterion = getCriterion(handle->criteria, name);
291 if (criterion == NULL) {
292 return status.failure("Can not get criterion " + string(name) + " as it does not exist");
293 }
294 *value = criterion->getCriterionState();
295 return status.success();
296 }
297
pfwApplyConfigurations(const PfwHandler * handle)298 bool pfwApplyConfigurations(const PfwHandler *handle)
299 {
300 if (handle == NULL) { return Status::failure(); }
301 Status &status = handle->lastStatus;
302 if (handle->pfw == NULL) {
303 return status.failure("Can not commit criteria "
304 "as the parameter framework is not started.");
305 }
306 handle->pfw->applyConfigurations();
307 return status.success();
308 }
309
310 ///////////////////////////////
311 /////// Parameter access //////
312 ///////////////////////////////
313
314 struct PfwParameterHandler_
315 {
316 PfwHandler &pfw;
317 CParameterHandle ¶meter;
318 };
319
pfwBindParameter(PfwHandler * handle,const char path[])320 PfwParameterHandler *pfwBindParameter(PfwHandler *handle, const char path[])
321 {
322 if (handle == NULL) { return NULL; }
323 Status &status = handle->lastStatus;
324 if (path == NULL) {
325 status.failure("Can not bind a parameter without its path");
326 return NULL;
327 }
328 if (handle->pfw == NULL) {
329 status.failure("The parameter framework is not started, "
330 "while trying to bind parameter \"" + string(path) + "\")");
331 return NULL;
332 }
333
334 CParameterHandle *paramHandle;
335 paramHandle = handle->pfw->createParameterHandle(path, status.msg());
336 if (paramHandle == NULL) {
337 return NULL;
338 }
339
340 status.success();
341 PfwParameterHandler publicHandle = {*handle, *paramHandle};
342 return new PfwParameterHandler(publicHandle);
343 }
344
pfwUnbindParameter(PfwParameterHandler * handle)345 void pfwUnbindParameter(PfwParameterHandler *handle)
346 {
347 if (handle == NULL) { return; }
348 delete &handle->parameter;
349 delete handle;
350 }
351
352
pfwGetIntParameter(const PfwParameterHandler * handle,int32_t * value)353 bool pfwGetIntParameter(const PfwParameterHandler *handle, int32_t *value)
354 {
355 if (handle == NULL) { return Status::failure(); }
356 Status &status = handle->pfw.lastStatus;
357 if (value == NULL) {
358 return status.failure("int32_t *value is NULL, "
359 "while trying to get parameter \"" +
360 handle->parameter.getPath() + "\" value as int)");
361 }
362 return status.forward(handle->parameter.getAsSignedInteger(*value, status.msg()));
363 }
pfwSetIntParameter(PfwParameterHandler * handle,int32_t value)364 bool pfwSetIntParameter(PfwParameterHandler *handle, int32_t value)
365 {
366 if (handle == NULL) { return Status::failure(); }
367 Status &status = handle->pfw.lastStatus;
368 return status.forward(handle->parameter.setAsSignedInteger(value, status.msg()));
369 }
370
pfwGetStringParameter(const PfwParameterHandler * handle,const char * value[])371 bool pfwGetStringParameter(const PfwParameterHandler *handle, const char *value[])
372 {
373 if (handle == NULL) { return Status::failure(); }
374 Status &status = handle->pfw.lastStatus;
375 if (value == NULL) {
376 return status.failure("char **value is NULL, "
377 "while trying to get parameter \"" +
378 handle->parameter.getPath() + "\" value as string)");
379 }
380 *value = NULL;
381 string retValue;
382 bool success = handle->parameter.getAsString(retValue, status.msg());
383 if (not success) { return status.forward(); }
384
385 *value = strdup(retValue.c_str());
386 return status.success();
387 }
388
pfwSetStringParameter(PfwParameterHandler * handle,const char value[])389 bool pfwSetStringParameter(PfwParameterHandler *handle, const char value[])
390 {
391 if (handle == NULL) { return Status::failure(); }
392 Status &status = handle->pfw.lastStatus;
393 return status.forward(handle->parameter.setAsString(value, status.msg()));
394 }
395
pfwFree(void * ptr)396 void pfwFree(void *ptr) { std::free(ptr); }
397
398