diff options
author | Josh Blum | 2013-07-07 11:50:03 -0700 |
---|---|---|
committer | Josh Blum | 2013-07-07 11:50:03 -0700 |
commit | c6373f53f4690d667e553ed7258e13c3b45aa323 (patch) | |
tree | 202bf0d31140c5567cad54dea697ad1dcbba6432 /include/gras | |
parent | e2a237e121edfb53378ae57d8faa71491d0f29f1 (diff) | |
download | sandhi-c6373f53f4690d667e553ed7258e13c3b45aa323.tar.gz sandhi-c6373f53f4690d667e553ed7258e13c3b45aa323.tar.bz2 sandhi-c6373f53f4690d667e553ed7258e13c3b45aa323.zip |
gras: created element factory
Diffstat (limited to 'include/gras')
-rw-r--r-- | include/gras/CMakeLists.txt | 2 | ||||
-rw-r--r-- | include/gras/detail/factory.hpp | 151 | ||||
-rw-r--r-- | include/gras/factory.hpp | 85 |
3 files changed, 238 insertions, 0 deletions
diff --git a/include/gras/CMakeLists.txt b/include/gras/CMakeLists.txt index 38cb233..72d2fa6 100644 --- a/include/gras/CMakeLists.txt +++ b/include/gras/CMakeLists.txt @@ -11,6 +11,7 @@ install(FILES block.i element.hpp element.i + factory.hpp gras.hpp hier_block.hpp hier_block.i @@ -39,6 +40,7 @@ install(FILES detail/block.hpp detail/chrono.hpp detail/element.hpp + detail/factory.hpp detail/sbuffer.hpp detail/work_buffer.hpp diff --git a/include/gras/detail/factory.hpp b/include/gras/detail/factory.hpp new file mode 100644 index 0000000..0487e76 --- /dev/null +++ b/include/gras/detail/factory.hpp @@ -0,0 +1,151 @@ +// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information. + +#ifndef INCLUDED_GRAS_DETAIL_FACTORY_HPP +#define INCLUDED_GRAS_DETAIL_FACTORY_HPP + +#include <PMC/Containers.hpp> //PMCList + +namespace gras +{ + +/*********************************************************************** + * Factory entry base class + **********************************************************************/ +struct GRAS_API FactoryRegistryEntry +{ + FactoryRegistryEntry(void); + virtual ~FactoryRegistryEntry(void); + virtual Element *make(const PMCC &args) = 0; +}; + +/*********************************************************************** + * Templated registration - 0 args + **********************************************************************/ +template <typename ReturnType> +struct FactoryRegistryEntryImpl0 : FactoryRegistryEntry +{ + typedef ReturnType(*Fcn)(void); + FactoryRegistryEntryImpl0(Fcn fcn):_fcn(fcn){} + Element *make(const PMCC &) + { + return _fcn(); + } + Fcn _fcn; +}; + +template <typename ReturnType> +void Factory::register_make(const std::string &name, ReturnType(*fcn)(void)) +{ + void *r = new FactoryRegistryEntryImpl0<ReturnType>(fcn); + Factory::_register_make(name, r); +} + +/*********************************************************************** + * Templated registration - 1 args + **********************************************************************/ +template <typename ReturnType, typename Arg0> +struct FactoryRegistryEntryImpl1 : FactoryRegistryEntry +{ + typedef ReturnType(*Fcn)(const Arg0 &); + FactoryRegistryEntryImpl1(Fcn fcn):_fcn(fcn){} + Element *make(const PMCC &args) + { + const PMCList &a = args.as<PMCList>(); + return _fcn(a[0].safe_as<Arg0>()); + } + Fcn _fcn; +}; + +template <typename ReturnType, typename Arg0> +void Factory::register_make(const std::string &name, ReturnType(*fcn)(const Arg0 &)) +{ + void *r = new FactoryRegistryEntryImpl1<ReturnType, Arg0>(fcn); + Factory::_register_make(name, r); +} + +/*********************************************************************** + * Templated registration - 2 args + **********************************************************************/ +template <typename ReturnType, typename Arg0, typename Arg1> +struct FactoryRegistryEntryImpl2 : FactoryRegistryEntry +{ + typedef ReturnType(*Fcn)(const Arg0 &, const Arg1 &); + FactoryRegistryEntryImpl2(Fcn fcn):_fcn(fcn){} + Element *make(const PMCC &args) + { + const PMCList &a = args.as<PMCList>(); + return _fcn(a[0].safe_as<Arg0>(), a[1].safe_as<Arg1>()); + } + Fcn _fcn; +}; + +template <typename ReturnType, typename Arg0, typename Arg1> +void Factory::register_make(const std::string &name, ReturnType(*fcn)(const Arg0 &, const Arg1 &)) +{ + void *r = new FactoryRegistryEntryImpl2<ReturnType, Arg0, Arg1>(fcn); + Factory::_register_make(name, r); +} + +/*********************************************************************** + * Templated registration - 3 args + **********************************************************************/ +template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2> +struct FactoryRegistryEntryImpl3 : FactoryRegistryEntry +{ + typedef ReturnType(*Fcn)(const Arg0 &, const Arg1 &, const Arg2 &); + FactoryRegistryEntryImpl3(Fcn fcn):_fcn(fcn){} + Element *make(const PMCC &args) + { + const PMCList &a = args.as<PMCList>(); + return _fcn(a[0].safe_as<Arg0>(), a[1].safe_as<Arg1>(), a[2].safe_as<Arg2>()); + } + Fcn _fcn; +}; + +template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2> +void Factory::register_make(const std::string &name, ReturnType(*fcn)(const Arg0 &, const Arg1 &, const Arg2 &)) +{ + void *r = new FactoryRegistryEntryImpl3<ReturnType, Arg0, Arg1, Arg2>(fcn); + Factory::_register_make(name, r); +} + +/*********************************************************************** + * Templated make implementations + **********************************************************************/ +inline +Element *Factory::make(const std::string &name) +{ + PMCList args(0); + return Factory::_make(name, PMC_M(args)); +} + +template <typename Arg0> +Element *Factory::make(const std::string &name, const Arg0 &a0) +{ + PMCList args(1); + args[0] = PMC_M(a0); + return Factory::_make(name, PMC_M(args)); +} + +template <typename Arg0, typename Arg1> +Element *Factory::make(const std::string &name, const Arg0 &a0, const Arg1 &a1) +{ + PMCList args(2); + args[0] = PMC_M(a0); + args[1] = PMC_M(a1); + return Factory::_make(name, PMC_M(args)); +} + +template <typename Arg0, typename Arg1, typename Arg2> +Element *Factory::make(const std::string &name, const Arg0 &a0, const Arg1 &a1, const Arg2 &a2) +{ + PMCList args(3); + args[0] = PMC_M(a0); + args[1] = PMC_M(a1); + args[2] = PMC_M(a2); + return Factory::_make(name, PMC_M(args)); +} + +} + +#endif /*INCLUDED_GRAS_DETAIL_FACTORY_HPP*/ diff --git a/include/gras/factory.hpp b/include/gras/factory.hpp new file mode 100644 index 0000000..926025e --- /dev/null +++ b/include/gras/factory.hpp @@ -0,0 +1,85 @@ +// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information. + +#ifndef INCLUDED_GRAS_FACTORY_HPP +#define INCLUDED_GRAS_FACTORY_HPP + +#include <gras/gras.hpp> +#include <gras/element.hpp> +#include <PMC/PMC.hpp> +#include <string> + +//! A fixture for static initialization code +#define GRAS_STATIC_BLOCK(name) \ + static struct name ## _static_fixture__ \ + { \ + name ## _static_fixture__(void); \ + } name ## _static_fixture_instance__; \ + name ## _static_fixture__::name ## _static_fixture__(void) + +/*! + * Register a block's factory function: + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY(name) \ + GRAS_STATIC_BLOCK(name) \ + {gras::Factory::register_make(#name, &name);} + +namespace gras +{ + +/*! + * Element factory: + * - Register factory functions into the global factory. + * - Call make() to create element from global factory. + * + * Example register a factory function: + * gras::Factory::register_make("make_my_block", &make_my_block); + * + * Example call into the factory: + * gras::Element *my_block = gras::Factory::make("make_my_block", arg0, arg1); + */ +class GRAS_API Factory : Callable +{ +public: + + /******************************************************************* + * Register API - don't look here, template magic, not helpful + ******************************************************************/ + template <typename ReturnType> + static void register_make(const std::string &name, ReturnType(*fcn)(void)); + + template <typename ReturnType, typename Arg0> + static void register_make(const std::string &name, ReturnType(*fcn)(const Arg0 &)); + + template <typename ReturnType, typename Arg0, typename Arg1> + static void register_make(const std::string &name, ReturnType(*fcn)(const Arg0 &, const Arg1 &)); + + template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2> + static void register_make(const std::string &name, ReturnType(*fcn)(const Arg0 &, const Arg1 &, const Arg2 &)); + + /******************************************************************* + * Make API - don't look here, template magic, not helpful + ******************************************************************/ + inline + static Element *make(const std::string &name); + + template <typename Arg0> + static Element *make(const std::string &name, const Arg0 &a0); + + template <typename Arg0, typename Arg1> + static Element *make(const std::string &name, const Arg0 &a0, const Arg1 &a1); + + template <typename Arg0, typename Arg1, typename Arg2> + static Element *make(const std::string &name, const Arg0 &a0, const Arg1 &a1, const Arg2 &a2); + +private: + static void _register_make(const std::string &, void *); + static Element *_make(const std::string &, const PMCC &); +}; + +} + +#include <gras/detail/factory.hpp> + +#endif /*INCLUDED_GRAS_FACTORY_HPP*/ |