Home | History | Annotate | Download | only in c
      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 }
     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 = {NULL, &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 != NULL);
    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 != NULL and logger->logCb == NULL) {
    171         return; // There is no callback, do not log => do not add a logger
    172     }
    173     mLogger = logger != NULL ? *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 == NULL) {
    184             return status.failure("Criterion name is NULL");
    185         }
    186         if (criterion.values == NULL) {
    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 != NULL);
    198         // Add criterion values
    199         for (size_t valueIndex = 0; criterion.values[valueIndex] != NULL; ++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 != NULL) {
    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     pfw::Criteria::const_iterator it = criteria.find(name);
    253     return it == criteria.end() ? NULL : it->second;
    254 }
    255 
    256 bool pfwSetCriterion(PfwHandler *handle, const char name[], int value)
    257 {
    258     Status &status = handle->lastStatus;
    259     if (handle->pfw == NULL) {
    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 == NULL) {
    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 == NULL) {
    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 == NULL) {
    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 == NULL) {
    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 &parameter;
    304 };
    305 
    306 PfwParameterHandler *pfwBindParameter(PfwHandler *handle, const char path[])
    307 {
    308     Status &status = handle->lastStatus;
    309     if (handle->pfw == NULL) {
    310         status.failure("The parameter framework is not started, "
    311                        "while trying to bind parameter \"" +
    312                        string(path) + "\")");
    313         return NULL;
    314     }
    315 
    316     CParameterHandle *paramHandle;
    317     paramHandle = handle->pfw->createParameterHandle(path, status.msg());
    318     if (paramHandle == NULL) {
    319         return NULL;
    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 = NULL;
    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