/** @file * @author Edouard DUPIN * @copyright 2016, Edouard DUPIN, all right reserved * @license APACHE v2.0 (see license file) */ #pragma once #include #include #include #include class ParamType { protected: const char* m_typeName; public: ParamType(const char* _name = ""): m_typeName(_name) { } const char* getName() const { return m_typeName; } bool operator == (const ParamType& _obj) const { return m_typeName == _obj.m_typeName; } }; template ParamType createType(); #define generate_basic_type(_type, _name) \ template<> ParamType createType<_type>() {\ return ParamType(_name); \ } class CmdBase { protected: const std::string m_name; public: const std::string& getName() const { return m_name; } protected: const std::string m_description; public: const std::string& getDescription() const { return m_description; } protected: CmdBase(const std::string& _name, const std::string& _desc): m_name(_name), m_description(_desc) { } public: virtual ~CmdBase() {}; bool checkCompatibility(const ParamType& _type, const ejson::Value& _params); bool checkCompatibility(const ParamType& _type, const std::string& _params); public: virtual std::string getPrototype() const = 0; virtual ejson::Value executeJson(const ejson::Array& _params) = 0; virtual std::string executeString(const std::vector& _params) = 0; }; template JUS_TYPE convertStringTo(const std::string& _value); template JUS_TYPE convertJsonTo(const ejson::Value& _value); template ejson::Value convertToJson(const JUS_TYPE& _value); template class TypeList; template ejson::Value executeCallJson(JUS_RETURN (*_func)(JUS_TYPES...), const ejson::Array& _params) { #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; return convertToJson(_func((convertJsonTo(_params[idParam++]))...)); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = m_paramCount-1; return convertToJson(_func(convertJsonTo(_params[idParam--])...)); #else #error Must be implemented ... #endif return ejson::Null(); } template ejson::Value executeCallJson(void (*_func)(JUS_TYPES...), const ejson::Array& _params) { ejson::Object out; #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; _func((convertJsonTo(_params[idParam++]))...); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = m_paramCount-1; _func(convertJsonTo(_params[idParam--])...); #else #error Must be implemented ... #endif return ejson::Null(); } template std::string executeCallString(JUS_RETURN (*_func)(JUS_TYPES...), const std::vector& _params) { #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; return etk::to_string(_func((convertStringTo(_params[idParam++]))...)); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = m_paramCount-1; return etk::to_string(_func(convertStringTo(_params[idParam--])...)); #else #error Must be implemented ... #endif return ""; } template std::string executeCallString(void (*_func)(JUS_TYPES...), const std::vector& _params) { ejson::Object out; #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; _func((convertStringTo(_params[idParam++]))...); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = m_paramCount-1; _func(convertStringTo(_params[idParam--])...); #else #error Must be implemented ... #endif return ""; } template class TypeList: public CmdBase { protected: static const ParamType m_returnType; static const ParamType m_paramType[sizeof...(JUS_TYPES)]; static const int32_t m_paramCount; public: using functionType = JUS_RETURN (*)(JUS_TYPES...); functionType m_function; TypeList(const std::string& _name, const std::string& _desc, functionType _fptr): CmdBase(_name, _desc), m_function(_fptr) { } std::string getPrototype() const override { std::string ret; ret += m_returnType.getName(); ret += " "; ret += m_name; ret += "("; for (size_t iii=0; iii& _params) override { std::string out; // check parameter number if (_params.size() != m_paramCount) { JUS_ERROR("Wrong number of Parameters ..."); out += "error:WRONG-PARAMETER-NUMBER;"; out += "error-help:request "; out += etk::to_string(_params.size()); out += " parameters and need "; out += etk::to_string(m_paramCount); out += " parameters. prototype function:"; out += getPrototype(); return out; } // check parameter compatibility for (size_t iii=0; iii const ParamType TypeList::m_returnType = createType(); template const ParamType TypeList::m_paramType[sizeof...(JUS_TYPES)] = {createType()...}; template const int32_t TypeList::m_paramCount = sizeof...(JUS_TYPES); template CmdBase* createCmd(const std::string& _name, const std::string& _desc, JUS_RETURN (*_fffp)(JUS_TYPES...)) { return new TypeList(_name, _desc, _fffp); } static double mulllll(double _val1) { double _val2 = 2.0f; JUS_ERROR("Call with parameter : " << _val1); return _val1*_val2; } static void mulllll2(std::string _value, int32_t _val1) { JUS_ERROR("Call with parameter : " << _value); JUS_ERROR(" parameter : " << _val1); } static std::string mulllll3(float _value, bool _val1) { JUS_ERROR("Call with parameter : " << _value); JUS_ERROR(" parameter : " << _val1); double _val2 = 1.0f; return "'il fait beau aujoud'hui ...'"; } static bool mulllll4() { return false; } namespace jus { class Service : public eproperty::Interface { public: eproperty::Value propertyIp; eproperty::Value propertyPort; private: jus::TcpString m_interfaceClient; uint32_t m_id; esignal::Connection m_dataCallback; std::vector m_newData; public: Service(); virtual ~Service(); // Genenric function call: ejson::Object callJson(const ejson::Object& _obj); void connect(); void disconnect(); private: void onClientData(const std::string& _value); std::string asyncRead(); private: void onPropertyChangeIp(); void onPropertyChangePort(); protected: void createSignatureInternal(std::vector& _signature) { // Finish recursive parse ... } template void createSignatureInternal(std::vector& _signature, const std::string& _param, _ARGS&&... _args) { _signature.push_back("string"); createSignatureInternal(_signature, std::forward<_ARGS>(_args)...); } template void createSignatureInternal(std::vector& _signature, const bool& _param, _ARGS&&... _args) { _signature.push_back("bool"); createSignatureInternal(_signature, std::forward<_ARGS>(_args)...); } template void createSignatureInternal(std::vector& _signature, const double& _param, _ARGS&&... _args) { _signature.push_back("double"); createSignatureInternal(_signature, std::forward<_ARGS>(_args)...); } template void createSignatureInternal(std::vector& _signature, const int32_t& _param, _ARGS&&... _args) { _signature.push_back("int32"); createSignatureInternal(_signature, std::forward<_ARGS>(_args)...); } template std::vector createSignature(_ARGS&&... _args) { std::vector signature; createSignatureInternal(signature, std::forward<_ARGS>(_args)...); return signature; } template void advertise(const std::string& _name, JUS_RETURN_VALUE (JUS_CLASS_TYPE::*_func)(const JUS_FUNC_ARGS_TYPE&... _args), const std::string& _desc) { //CmdBase* tmp = createCmd(_name, &mulllll); CmdBase* tmp = createCmd(_name, "desc", &mulllll); JUS_ERROR("Signature : " << tmp->getPrototype()); { ejson::Array param; param.add(ejson::Number(58.5)); ejson::Value out = tmp->executeJson(param); JUS_ERROR(" return: "); out.display(); } tmp = createCmd(_name, "desc", &mulllll2); JUS_ERROR("Signature2 : " << tmp->getPrototype()); { ejson::Array param; param.add(ejson::String("coucou")); param.add(ejson::Number(1563)); ejson::Value out = tmp->executeJson(param); JUS_ERROR(" return: "); out.display(); } tmp = createCmd(_name, "desc", &mulllll3); JUS_ERROR("Signature3 : " << tmp->getPrototype()); JUS_ERROR(" return: " << tmp->executeString(etk::split("3.5 false", ' '))); tmp = createCmd(_name, "desc", &mulllll4); JUS_ERROR("Signature4 : " << tmp->getPrototype()); /* std::vector plop = createSignature(_args): JUS_ERROR("signature:"); for (auto& it : plop) { JUS_ERROR(" - " << it); } */ } }; }