// 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; void arg_check(const PMCList &args, const size_t nargs); }; /*********************************************************************** * Templated registration - 0 args **********************************************************************/ template <typename ReturnType> struct FactoryRegistryEntryImpl0 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(); FactoryRegistryEntryImpl0(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as<PMCList>(); this->arg_check(a, 0); return _fcn(); } Fcn _fcn; }; template <typename ReturnType> void Factory::register_make(const std::string &name, ReturnType(*fcn)()) { void *r = new FactoryRegistryEntryImpl0<ReturnType>(fcn); Factory::_register_make(name, r); } /*********************************************************************** * Templated registration - 1 args **********************************************************************/ template <typename ReturnType, typename A0> struct FactoryRegistryEntryImpl1 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(const A0 &); FactoryRegistryEntryImpl1(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as<PMCList>(); this->arg_check(a, 1); return _fcn(a[0].safe_as<A0>()); } Fcn _fcn; }; template <typename ReturnType, typename A0> void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &)) { void *r = new FactoryRegistryEntryImpl1<ReturnType, A0>(fcn); Factory::_register_make(name, r); } /*********************************************************************** * Templated registration - 2 args **********************************************************************/ template <typename ReturnType, typename A0, typename A1> struct FactoryRegistryEntryImpl2 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(const A0 &, const A1 &); FactoryRegistryEntryImpl2(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as<PMCList>(); this->arg_check(a, 2); return _fcn(a[0].safe_as<A0>(), a[1].safe_as<A1>()); } Fcn _fcn; }; template <typename ReturnType, typename A0, typename A1> void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &)) { void *r = new FactoryRegistryEntryImpl2<ReturnType, A0, A1>(fcn); Factory::_register_make(name, r); } /*********************************************************************** * Templated registration - 3 args **********************************************************************/ template <typename ReturnType, typename A0, typename A1, typename A2> struct FactoryRegistryEntryImpl3 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(const A0 &, const A1 &, const A2 &); FactoryRegistryEntryImpl3(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as<PMCList>(); this->arg_check(a, 3); return _fcn(a[0].safe_as<A0>(), a[1].safe_as<A1>(), a[2].safe_as<A2>()); } Fcn _fcn; }; template <typename ReturnType, typename A0, typename A1, typename A2> void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &)) { void *r = new FactoryRegistryEntryImpl3<ReturnType, A0, A1, A2>(fcn); Factory::_register_make(name, r); } /*********************************************************************** * Templated registration - 4 args **********************************************************************/ template <typename ReturnType, typename A0, typename A1, typename A2, typename A3> struct FactoryRegistryEntryImpl4 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(const A0 &, const A1 &, const A2 &, const A3 &); FactoryRegistryEntryImpl4(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as<PMCList>(); this->arg_check(a, 4); return _fcn(a[0].safe_as<A0>(), a[1].safe_as<A1>(), a[2].safe_as<A2>(), a[3].safe_as<A3>()); } Fcn _fcn; }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3> void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &)) { void *r = new FactoryRegistryEntryImpl4<ReturnType, A0, A1, A2, A3>(fcn); Factory::_register_make(name, r); } /*********************************************************************** * Templated registration - 5 args **********************************************************************/ template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4> struct FactoryRegistryEntryImpl5 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &); FactoryRegistryEntryImpl5(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as<PMCList>(); this->arg_check(a, 5); return _fcn(a[0].safe_as<A0>(), a[1].safe_as<A1>(), a[2].safe_as<A2>(), a[3].safe_as<A3>(), a[4].safe_as<A4>()); } Fcn _fcn; }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4> void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &)) { void *r = new FactoryRegistryEntryImpl5<ReturnType, A0, A1, A2, A3, A4>(fcn); Factory::_register_make(name, r); } /*********************************************************************** * Templated registration - 6 args **********************************************************************/ template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> struct FactoryRegistryEntryImpl6 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &); FactoryRegistryEntryImpl6(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as<PMCList>(); this->arg_check(a, 6); return _fcn(a[0].safe_as<A0>(), a[1].safe_as<A1>(), a[2].safe_as<A2>(), a[3].safe_as<A3>(), a[4].safe_as<A4>(), a[5].safe_as<A5>()); } Fcn _fcn; }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &)) { void *r = new FactoryRegistryEntryImpl6<ReturnType, A0, A1, A2, A3, A4, A5>(fcn); Factory::_register_make(name, r); } /*********************************************************************** * Templated registration - 7 args **********************************************************************/ template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> struct FactoryRegistryEntryImpl7 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &); FactoryRegistryEntryImpl7(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as<PMCList>(); this->arg_check(a, 7); return _fcn(a[0].safe_as<A0>(), a[1].safe_as<A1>(), a[2].safe_as<A2>(), a[3].safe_as<A3>(), a[4].safe_as<A4>(), a[5].safe_as<A5>(), a[6].safe_as<A6>()); } Fcn _fcn; }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &)) { void *r = new FactoryRegistryEntryImpl7<ReturnType, A0, A1, A2, A3, A4, A5, A6>(fcn); Factory::_register_make(name, r); } /*********************************************************************** * Templated registration - 8 args **********************************************************************/ template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> struct FactoryRegistryEntryImpl8 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &); FactoryRegistryEntryImpl8(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as<PMCList>(); this->arg_check(a, 8); return _fcn(a[0].safe_as<A0>(), a[1].safe_as<A1>(), a[2].safe_as<A2>(), a[3].safe_as<A3>(), a[4].safe_as<A4>(), a[5].safe_as<A5>(), a[6].safe_as<A6>(), a[7].safe_as<A7>()); } Fcn _fcn; }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &)) { void *r = new FactoryRegistryEntryImpl8<ReturnType, A0, A1, A2, A3, A4, A5, A6, A7>(fcn); Factory::_register_make(name, r); } /*********************************************************************** * Templated registration - 9 args **********************************************************************/ template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> struct FactoryRegistryEntryImpl9 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &); FactoryRegistryEntryImpl9(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as<PMCList>(); this->arg_check(a, 9); return _fcn(a[0].safe_as<A0>(), a[1].safe_as<A1>(), a[2].safe_as<A2>(), a[3].safe_as<A3>(), a[4].safe_as<A4>(), a[5].safe_as<A5>(), a[6].safe_as<A6>(), a[7].safe_as<A7>(), a[8].safe_as<A8>()); } Fcn _fcn; }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &)) { void *r = new FactoryRegistryEntryImpl9<ReturnType, A0, A1, A2, A3, A4, A5, A6, A7, A8>(fcn); Factory::_register_make(name, r); } /*********************************************************************** * Templated registration - 10 args **********************************************************************/ template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> struct FactoryRegistryEntryImpl10 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &); FactoryRegistryEntryImpl10(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as<PMCList>(); this->arg_check(a, 10); return _fcn(a[0].safe_as<A0>(), a[1].safe_as<A1>(), a[2].safe_as<A2>(), a[3].safe_as<A3>(), a[4].safe_as<A4>(), a[5].safe_as<A5>(), a[6].safe_as<A6>(), a[7].safe_as<A7>(), a[8].safe_as<A8>(), a[9].safe_as<A9>()); } Fcn _fcn; }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &)) { void *r = new FactoryRegistryEntryImpl10<ReturnType, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9>(fcn); Factory::_register_make(name, r); } /*********************************************************************** * Templated make implementations **********************************************************************/ inline Element *Factory::make(const std::string &name) { PMCList args(0); return Factory::_handle_make(name, PMC_M(args)); } template <typename A0> Element *Factory::make(const std::string &name, const A0 &a0) { PMCList args(1); args[0] = PMC_M(a0); return Factory::_handle_make(name, PMC_M(args)); } template <typename A0, typename A1> Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1) { PMCList args(2); args[0] = PMC_M(a0); args[1] = PMC_M(a1); return Factory::_handle_make(name, PMC_M(args)); } template <typename A0, typename A1, typename A2> Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2) { PMCList args(3); args[0] = PMC_M(a0); args[1] = PMC_M(a1); args[2] = PMC_M(a2); return Factory::_handle_make(name, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3> Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3) { PMCList args(4); args[0] = PMC_M(a0); args[1] = PMC_M(a1); args[2] = PMC_M(a2); args[3] = PMC_M(a3); return Factory::_handle_make(name, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3, typename A4> Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) { PMCList args(5); args[0] = PMC_M(a0); args[1] = PMC_M(a1); args[2] = PMC_M(a2); args[3] = PMC_M(a3); args[4] = PMC_M(a4); return Factory::_handle_make(name, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5) { PMCList args(6); args[0] = PMC_M(a0); args[1] = PMC_M(a1); args[2] = PMC_M(a2); args[3] = PMC_M(a3); args[4] = PMC_M(a4); args[5] = PMC_M(a5); return Factory::_handle_make(name, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6) { PMCList args(7); args[0] = PMC_M(a0); args[1] = PMC_M(a1); args[2] = PMC_M(a2); args[3] = PMC_M(a3); args[4] = PMC_M(a4); args[5] = PMC_M(a5); args[6] = PMC_M(a6); return Factory::_handle_make(name, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7) { PMCList args(8); args[0] = PMC_M(a0); args[1] = PMC_M(a1); args[2] = PMC_M(a2); args[3] = PMC_M(a3); args[4] = PMC_M(a4); args[5] = PMC_M(a5); args[6] = PMC_M(a6); args[7] = PMC_M(a7); return Factory::_handle_make(name, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8) { PMCList args(9); args[0] = PMC_M(a0); args[1] = PMC_M(a1); args[2] = PMC_M(a2); args[3] = PMC_M(a3); args[4] = PMC_M(a4); args[5] = PMC_M(a5); args[6] = PMC_M(a6); args[7] = PMC_M(a7); args[8] = PMC_M(a8); return Factory::_handle_make(name, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9) { PMCList args(10); args[0] = PMC_M(a0); args[1] = PMC_M(a1); args[2] = PMC_M(a2); args[3] = PMC_M(a3); args[4] = PMC_M(a4); args[5] = PMC_M(a5); args[6] = PMC_M(a6); args[7] = PMC_M(a7); args[8] = PMC_M(a8); args[9] = PMC_M(a9); return Factory::_handle_make(name, PMC_M(args)); } } #endif /*INCLUDED_GRAS_DETAIL_FACTORY_HPP*/