/*! \file piparsehelper.h * \ingroup IO * \~\brief * \~english Helper class to automate structs receive * \~russian Класс для автоматизации приема структур */ /* PIP - Platform Independent Primitives Helper class to automate structs receive Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PIPARSEHELPER_H #define PIPARSEHELPER_H #include "piobject.h" #include "pip_io_utils_export.h" /** \class PIParseHelper * \brief Helper class to automate structs receive * * * \section PIParseHelper_synopsis Synopsis * This class helps to deserialize and invoke neccessarily methods. * * Data packets with header and various data types can be automated by this class. * Every key value mapped to object member function, lambda-function or functor. * * This class can remove \b switch-case with deserialization code and * replace it with several \a assign() calls, binded to ready-to-use event handlers. * Moreover data type automatic takes from event handler or lambda argument. One should * only make \"PIByteArray & operator <<()\" with used types, deserialization will be * performed by %PIParseHelper. * * * \section PIParseHelper_usage Usage * * Create instance of %PIParseHelper, or subclass. * * In \a assign() methods you can use object member function, lambda-function * or functor with 0 or 1 arguments, * * * \section PIParseHelper_lambda Lambda-functions * \code assign(1, [this](const SomeStruct & s){}) \endcode * * * \section PIParseHelper_examples Examples * First example describes subclass variant. As one can see, it`s a single place to change * type of received data - event handler argument. * \snippet piparsehelper.cpp 0 * * Second example show separate variant: * \snippet piparsehelper.cpp 1 * **/ template class PIParseHelper { public: //! \brief Construct %PIParseHelper PIParseHelper() {} //! \brief Assign key \"key\" to lambda-function \"func\" without arguments void assign(Key key, std::function func) { auto lf = [func](PIByteArray) { func(); }; functions[key] << lf; } //! \brief Assign key \"key\" to lambda-function \"func\" with 1 argument template void assign(Key key, std::function func) { auto lf = [func](PIByteArray data) { if (!data.isEmpty()) { T v; data >> v; func(v); } }; functions[key] << lf; } //! \brief Assign key \"key\" to member function of object \"obj\" without arguments template void assign(Key key, O * obj, void (O::*member_func)()) { auto lf = [member_func, obj](PIByteArray) { (obj->*member_func)(); }; functions[key] << lf; } //! \brief Assign key \"key\" to member function of object \"obj\" with 1 argument template void assign(Key key, O * obj, void (O::*member_func)(const T &)) { auto lf = [member_func, obj](PIByteArray data) { if (!data.isEmpty()) { T v; data >> v; (obj->*member_func)(v); } }; functions[key] << lf; } //! \brief Assign key \"key\" to functor \"func\" with 0 or 1 argument template void assign(Key key, L func) { return assign(key, toStdFunction(func)); } //! \brief Deserialize data and invoke assigned to \"key\" methods void parse(Key key, PIByteArray ba) { auto fl = functions.value(key); for (auto f: fl) f(ba); } private: PIMap>> functions; }; #endif // PIPARSEHELPER_H