/** @file * @author Edouard DUPIN * @copyright 2016, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ #pragma once #include #include #include #include namespace zeus { /** * @brief Execute a call on the global function with a return value * @param[in] _interfaceClient Web interface to send data * @param[in] _obj Message input call (that have parameter already check) * @param[in] _func pointer on the function to call */ template void executeCall(ememory::SharedPtr _interfaceClient, ememory::SharedPtr _obj, ZEUS_RETURN (*_func)(ZEUS_TYPES...)) { if (_obj == null) { return; } ZEUS_RETURN ret; if (zeus::checkOrderFunctionParameter() == true) { // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; ret = _func(_obj->getParameter(idParam++)...); } else { int32_t idParam = int32_t(sizeof...(ZEUS_TYPES))-1; ret = _func(_obj->getParameter(idParam--)...); } if (_interfaceClient == null) { ZEUS_ERROR("Nullptr for _interfaceWeb"); return; } _interfaceClient->addAsync([=](WebServer* _interface) { _interface->answerValue(_obj->getTransactionId(), _obj->getDestination(), _obj->getSource(), ret); return true; }); } /** * @brief Execute a call on the global function with NO return value * @param[in] _interfaceClient Web interface to send data * @param[in] _obj Message input call (that have parameter already check) * @param[in] _func pointer on the function to call */ template void executeCall(ememory::SharedPtr _interfaceClient, ememory::SharedPtr _obj, void (*_func)(ZEUS_TYPES...)) { if (_obj == null) { return; } if (zeus::checkOrderFunctionParameter() == true) { // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; _func(_obj->getParameter(idParam++)...); } else { int32_t idParam = int32_t(sizeof...(ZEUS_TYPES))-1; _func(_obj->getParameter(idParam--)...); } if (_interfaceClient == null) { ZEUS_ERROR("Nullptr for _interfaceWeb"); return; } _interfaceClient->addAsync([=](WebServer* _interface) { _interface->answerVoid(_obj->getTransactionId(), _obj->getDestination(), _obj->getSource()); return true; }); } /** * @brief Chass that permit to declare a function that call global function */ template class AbstractFunctionTypeDirect: public zeus::AbstractFunction { protected: static const zeus::message::ParamType m_returnType; static const zeus::message::ParamType m_paramType[sizeof...(ZEUS_TYPES)]; public: using functionType = ZEUS_RETURN (*)(ZEUS_TYPES...); functionType m_function; /** * @brief Constructor * @param[in] _name Name of the function * @param[in] _fptr Pointer on the function */ AbstractFunctionTypeDirect(const etk::String& _name, functionType _fptr): AbstractFunction(_name), m_function(_fptr) { } etk::String getPrototypeReturn() const override { return m_returnType.getName(); } etk::Vector getPrototypeParam() const override { etk::Vector out; for (size_t iii=0; iii _interfaceClient, ememory::SharedPtr _obj, void* _class) override { if (_obj == null) { return; } if (_interfaceClient == null) { ZEUS_ERROR("Nullptr for _interfaceWeb"); return; } // check parameter number if (_obj->getNumberParameter() != sizeof...(ZEUS_TYPES)) { etk::String help = "request "; help += etk::toString(_obj->getNumberParameter()); help += " parameters and need "; help += etk::toString(sizeof...(ZEUS_TYPES)); help += " parameters. prototype function:"; help += getPrototype(); _interfaceClient->answerError(_obj->getTransactionId(), _obj->getDestination(), _obj->getSource(), "WRONG-PARAMETER-NUMBER", help); return; } // check parameter compatibility for (size_t iii=0; iiigetParameterType(iii)) == false) { _interfaceClient->answerError(_obj->getTransactionId(), _obj->getDestination(), _obj->getSource(), "WRONG-PARAMETER-TYPE", etk::String("Parameter id ") + etk::toString(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'"); return; } } ethread::metadataSet(zeus::g_threadKeyTransactionId, _obj->getTransactionId()); ethread::metadataSet(zeus::g_threadKeyTransactionSource, _obj->getSource()); ethread::metadataSet(zeus::g_threadKeyTransactionDestination, _obj->getDestination()); try { // execute cmd: zeus::executeCall(_interfaceClient, _obj, m_function); } catch (const etk::Exception& eee) { _interfaceClient->addAsync([=](WebServer* _interface) { _interface->answerError(_obj->getTransactionId(), _obj->getDestination(), _obj->getSource(), eee.which(), eee.what()); return true; }); } ethread::metadataRemove(zeus::g_threadKeyTransactionId); ethread::metadataRemove(zeus::g_threadKeyTransactionSource); ethread::metadataRemove(zeus::g_threadKeyTransactionDestination); } }; // specialization template const zeus::message::ParamType AbstractFunctionTypeDirect::m_returnType = zeus::message::createType(); // specialization template const zeus::message::ParamType AbstractFunctionTypeDirect::m_paramType[sizeof...(ZEUS_TYPES)] = {zeus::message::createType()...}; /** * @brief Create a function information with the function type * @param[in] _name Name of the function * @param[in] _fffp Pointer of the function * @return Abstract type of the function */ template zeus::AbstractFunction* createAbstractFunctionDirect(const etk::String& _name, ZEUS_RETURN (*_fffp)(ZEUS_TYPES...)) { return new AbstractFunctionTypeDirect(_name, _fffp); } }