diff --git a/.travis.yml b/.travis.yml index 71d95d6e7..09c5451d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,6 @@ addons: - g++-4.8 - cmake - python3-dev - - libasio-dev - clang-format-3.8 install: diff --git a/parameter/BooleanParameterType.cpp b/parameter/BooleanParameterType.cpp index 66556d304..3e544c2b8 100644 --- a/parameter/BooleanParameterType.cpp +++ b/parameter/BooleanParameterType.cpp @@ -30,6 +30,7 @@ #include "BooleanParameterType.h" #include "ParameterAccessContext.h" #include "Utility.h" +#include "convert.hpp" #define base CParameterType @@ -47,27 +48,14 @@ std::string CBooleanParameterType::getKind() const bool CBooleanParameterType::toBlackboard(const std::string &strValue, uint32_t &uiValue, CParameterAccessContext ¶meterAccessContext) const { - if (strValue == "1" || strValue == "0x1") { - - uiValue = true; - } else if (strValue == "0" || strValue == "0x0") { - - uiValue = false; - } else { - parameterAccessContext.setError(strValue + " value not part of numerical space {"); - - if (utility::isHexadecimal(strValue)) { - - parameterAccessContext.appendToError("0x0, 0x1"); - } else { - - parameterAccessContext.appendToError("0, 1"); - } - parameterAccessContext.appendToError("} for " + getKind()); + bool value; + if (not convertTo(strValue, value)) { + parameterAccessContext.setError(strValue + " value is invalid for " + getKind() + + ", valid values are {0, 1, 0x0, 0x1, true, false}"); return false; } - + uiValue = value; return true; } diff --git a/parameter/ElementHandle.cpp b/parameter/ElementHandle.cpp index ac9376526..553526a96 100644 --- a/parameter/ElementHandle.cpp +++ b/parameter/ElementHandle.cpp @@ -218,6 +218,10 @@ bool ElementHandle::setAs(const T value, string &error) const return parameter.access(copy, true, parameterAccessContext); } +template PARAMETER_EXPORT bool ElementHandle::setAs(bool, string &) const; +template PARAMETER_EXPORT bool ElementHandle::setAs(string, string &) const; +template PARAMETER_EXPORT bool ElementHandle::setAs(double, string &) const; + template bool ElementHandle::getAs(T &value, string &error) const { @@ -235,6 +239,10 @@ bool ElementHandle::getAs(T &value, string &error) const return parameter.access(value, false, parameterAccessContext); } +template PARAMETER_EXPORT bool ElementHandle::getAs(bool &, string &) const; +template PARAMETER_EXPORT bool ElementHandle::getAs(string &, string &) const; +template PARAMETER_EXPORT bool ElementHandle::getAs(double &, string &) const; + // Boolean access bool ElementHandle::setAsBoolean(bool bValue, string &error) { diff --git a/parameter/include/ElementHandle.h b/parameter/include/ElementHandle.h index 542379409..0990e2f0c 100644 --- a/parameter/include/ElementHandle.h +++ b/parameter/include/ElementHandle.h @@ -45,7 +45,13 @@ class CConfigurableElement; class CBaseParameter; /** @} */ -/** TODO */ +/** ElementHandle gives access to elements of the parameter tree. + * + * ElementHandle objects can be created by calling the + * ParameterMgrPlatformConnector::createElementHandle. + * + * @note non const method can only be called on rogue elements. + */ class PARAMETER_EXPORT ElementHandle { public: @@ -171,7 +177,7 @@ class PARAMETER_EXPORT ElementHandle /** Access (get or set) parameters as different types. * - * Will fail if the element is not a paramete. + * Will fail if the element is not a parameter. * Array access will fail if the parameter is not an array. * * @param value if get, the value to get (in parameter) @@ -226,16 +232,34 @@ class PARAMETER_EXPORT ElementHandle /** @} */ -protected: - ElementHandle(CConfigurableElement &element, CParameterMgr ¶meterMgr); - friend CParameterMgr; // So that it can build the handler - -private: + /** Access a parameter with a template type + * + * Template version of getAsBoolean, getAsInteger, getAsDoubleArray... + * + * @tparam T How to access the parameter. + * Eg: use bool to call setAsBoolean + * use std::vector to call setAsBooleanArray + * + * @note Why are those two methods not public ? + * It could depreciate all the other setAs* and getAs* + * @{ + */ template bool setAs(const T value, std::string &error) const; template bool getAs(T &value, std::string &error) const; + /** @} */ + +protected: + /** Friend to be constructed from CParameterMgr::createElementHandle. */ + friend CParameterMgr; + /** Protected for test purposes. + * Client must not inherit from this class anyway. + */ + ElementHandle(CConfigurableElement &element, CParameterMgr ¶meterMgr); + +private: template static size_t getSize(T value); template diff --git a/test/functional-tests/FloatingPoint.cpp b/test/functional-tests/FloatingPoint.cpp index fd41797f1..ec6a68eef 100644 --- a/test/functional-tests/FloatingPoint.cpp +++ b/test/functional-tests/FloatingPoint.cpp @@ -159,9 +159,9 @@ SCENARIO_METHOD(FloatsPF, "Floating points", "[floating points]") {"(inside range)", 0.0f}, }) { GIVEN ("A valid value " + vec.title) { - CHECK_NOTHROW(handle.setAsDouble(vec.payload)); + CHECK_NOTHROW(handle.setAs(vec.payload)); double getValueBack; - REQUIRE_NOTHROW(handle.getAsDouble(getValueBack)); + REQUIRE_NOTHROW(getValueBack = handle.getAs()); CHECK(getValueBack == vec.payload); } } @@ -169,7 +169,7 @@ SCENARIO_METHOD(FloatsPF, "Floating points", "[floating points]") {"(too high)", 12.3f}, {"(too low)", -50.5f}, }) { GIVEN ("An invalid value " + vec.title) { - CHECK_THROWS_AS(handle.setAsDouble(vec.payload), Exception); + CHECK_THROWS_AS(handle.setAs(vec.payload), Exception); } } } diff --git a/test/functional-tests/Handle.cpp b/test/functional-tests/Handle.cpp index 1c594fdd3..f3a48bf4b 100644 --- a/test/functional-tests/Handle.cpp +++ b/test/functional-tests/Handle.cpp @@ -602,4 +602,33 @@ SCENARIO("Mapping handle access", "[handler][mapping]") } } +SCENARIO_METHOD(AllParamsPF, "Access boolean", "[handler][access]") +{ + ElementHandle handle(*this, "/test/test/bool"); + struct TestVector + { + bool expectedValue; + list values; + }; + list testVectors = { + {true, {"1", "0x1", "001", "0x001", "true", "True", "TRUe"}}, + {false, {"0", "0x0", "000", "0x000", "false", "False", "FaLSe"}}}; + + for (auto testVector : testVectors) { + for (auto value : testVector.values) { + CAPTURE(value); + auto expectedValue = testVector.expectedValue; + CAPTURE(expectedValue); + + CHECK_NOTHROW(handle.setAs(value)); + CHECK(handle.getAs() == std::to_string(expectedValue)); + CHECK(handle.getAs() == expectedValue); + } + } + + for (string invalid : {"2", "-1", "0x10", "None", "faux"}) { + CHECK_THROWS_AS(handle.setAs(invalid), Exception); + } +} + } // namespace parameterFramework diff --git a/test/functional-tests/include/ElementHandle.hpp b/test/functional-tests/include/ElementHandle.hpp index dc48ce908..aa4981ab5 100644 --- a/test/functional-tests/include/ElementHandle.hpp +++ b/test/functional-tests/include/ElementHandle.hpp @@ -41,8 +41,12 @@ namespace parameterFramework * Contrary to ::ElementHandle, is constructed through it's constructor * and not a factory method. * @see parameterFramework::ParameterFramework for the main PF interface. + * + * @fixme Should privately inherit from FailureWrapper but this can not be done + * as this class uses protected ::ElementHandle::getAs and setAs methods. + * See their documentation for more information. */ -class ElementHandle : private FailureWrapper<::ElementHandle> +class ElementHandle : protected FailureWrapper<::ElementHandle> { ElementHandle(const ElementHandle &other) = delete; ElementHandle &operator=(const ElementHandle &other) = delete; @@ -71,10 +75,20 @@ class ElementHandle : private FailureWrapper<::ElementHandle> return value; } - /** Wrap EH::setAsDouble to throw an exception on failure. */ - void setAsDouble(double value) { mayFailCall(&EH::setAsDouble, value); } - /** Wrap EH::getAsDouble to throw an exception on failure. */ - void getAsDouble(double &value) const { mayFailCall(&EH::getAsDouble, value); } + /** Wrap EH::setAs* to throw an exception on failure. */ + template + void setAs(T value) + { + mayFailCall(&EH::setAs, value); + } + + /** Wrap EH::getAs* to throw an exception on failure. + * @todo list allowed types. */ + template + T getAs() + { + return mayFailGet(&EH::getAs); + } std::string getStructureAsXML() const { return mayFailGet(&EH::getStructureAsXML); } diff --git a/test/xml-generator/testVector/complex.pfw b/test/xml-generator/testVector/complex.pfw index 042259572..b1bfc6422 100644 --- a/test/xml-generator/testVector/complex.pfw +++ b/test/xml-generator/testVector/complex.pfw @@ -37,4 +37,4 @@ domainGroup: Red sequenceAware q2.5 = 1.18750 string = 12 ab @ \n \0 ✔ "'\ component: included - bool = 1 + bool = true diff --git a/utility/convert.hpp b/utility/convert.hpp index a45c4a718..acbdd618b 100644 --- a/utility/convert.hpp +++ b/utility/convert.hpp @@ -33,8 +33,10 @@ #include #include #include +#include #include #include +#include #include /* details namespace is here to hide implementation details to header end user. It @@ -184,6 +186,8 @@ static inline bool convertToVia(const std::string &str, T &result) * @param[out] result reference to object where to store the result. * * @return true if conversion was successful, false otherwise. + * + * @FIXME: Unit tests were not imported with this conversion library. */ template static inline bool convertTo(const std::string &str, T &result) @@ -302,12 +306,30 @@ inline bool convertTo(const std::string &str, double &result) template <> inline bool convertTo(const std::string &str, bool &result) { - if (str == "0" || str == "FALSE" || str == "false") { + // Try the numerical representation + uint8_t numeric; + if (convertTo(str, numeric)) { + switch (numeric) { + case 0: + result = false; + return true; + case 1: + result = true; + return true; + default: + return false; + } + } + + std::string lower = str; + transform(begin(str), end(str), begin(lower), tolower); + + if (lower == "false") { result = false; return true; } - if (str == "1" || str == "TRUE" || str == "true") { + if (lower == "true") { result = true; return true; }