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