// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information. #ifndef INCLUDED_GRAS_DETAIL_FACTORY_HPP #define INCLUDED_GRAS_DETAIL_FACTORY_HPP #include //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 struct FactoryRegistryEntryImpl0 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(); FactoryRegistryEntryImpl0(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as(); this->arg_check(a, 0); return _fcn(); } Fcn _fcn; }; template void register_factory(const std::string &path, ReturnType(*fcn)()) { void *r = new FactoryRegistryEntryImpl0(fcn); _register_factory(path, r); } /*********************************************************************** * Templated registration - 1 args **********************************************************************/ template struct FactoryRegistryEntryImpl1 : FactoryRegistryEntry { typedef ReturnType(*Fcn)(const A0 &); FactoryRegistryEntryImpl1(Fcn fcn):_fcn(fcn){} Element *make(const PMCC &args) { const PMCList &a = args.as(); this->arg_check(a, 1); return _fcn(a[0].safe_as()); } Fcn _fcn; }; template void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &)) { void *r = new FactoryRegistryEntryImpl1(fcn); _register_factory(path, r); } /*********************************************************************** * Templated registration - 2 args **********************************************************************/ template 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(); this->arg_check(a, 2); return _fcn(a[0].safe_as(), a[1].safe_as()); } Fcn _fcn; }; template void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &)) { void *r = new FactoryRegistryEntryImpl2(fcn); _register_factory(path, r); } /*********************************************************************** * Templated registration - 3 args **********************************************************************/ template 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(); this->arg_check(a, 3); return _fcn(a[0].safe_as(), a[1].safe_as(), a[2].safe_as()); } Fcn _fcn; }; template void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &)) { void *r = new FactoryRegistryEntryImpl3(fcn); _register_factory(path, r); } /*********************************************************************** * Templated registration - 4 args **********************************************************************/ template 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(); this->arg_check(a, 4); return _fcn(a[0].safe_as(), a[1].safe_as(), a[2].safe_as(), a[3].safe_as()); } Fcn _fcn; }; template void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &)) { void *r = new FactoryRegistryEntryImpl4(fcn); _register_factory(path, r); } /*********************************************************************** * Templated registration - 5 args **********************************************************************/ template 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(); this->arg_check(a, 5); return _fcn(a[0].safe_as(), a[1].safe_as(), a[2].safe_as(), a[3].safe_as(), a[4].safe_as()); } Fcn _fcn; }; template void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &)) { void *r = new FactoryRegistryEntryImpl5(fcn); _register_factory(path, r); } /*********************************************************************** * Templated registration - 6 args **********************************************************************/ template 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(); this->arg_check(a, 6); return _fcn(a[0].safe_as(), a[1].safe_as(), a[2].safe_as(), a[3].safe_as(), a[4].safe_as(), a[5].safe_as()); } Fcn _fcn; }; template void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &)) { void *r = new FactoryRegistryEntryImpl6(fcn); _register_factory(path, r); } /*********************************************************************** * Templated registration - 7 args **********************************************************************/ template 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(); this->arg_check(a, 7); return _fcn(a[0].safe_as(), a[1].safe_as(), a[2].safe_as(), a[3].safe_as(), a[4].safe_as(), a[5].safe_as(), a[6].safe_as()); } Fcn _fcn; }; template void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &)) { void *r = new FactoryRegistryEntryImpl7(fcn); _register_factory(path, r); } /*********************************************************************** * Templated registration - 8 args **********************************************************************/ template 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(); this->arg_check(a, 8); return _fcn(a[0].safe_as(), a[1].safe_as(), a[2].safe_as(), a[3].safe_as(), a[4].safe_as(), a[5].safe_as(), a[6].safe_as(), a[7].safe_as()); } Fcn _fcn; }; template void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &)) { void *r = new FactoryRegistryEntryImpl8(fcn); _register_factory(path, r); } /*********************************************************************** * Templated registration - 9 args **********************************************************************/ template 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(); this->arg_check(a, 9); return _fcn(a[0].safe_as(), a[1].safe_as(), a[2].safe_as(), a[3].safe_as(), a[4].safe_as(), a[5].safe_as(), a[6].safe_as(), a[7].safe_as(), a[8].safe_as()); } Fcn _fcn; }; template void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &)) { void *r = new FactoryRegistryEntryImpl9(fcn); _register_factory(path, r); } /*********************************************************************** * Templated registration - 10 args **********************************************************************/ template 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(); this->arg_check(a, 10); return _fcn(a[0].safe_as(), a[1].safe_as(), a[2].safe_as(), a[3].safe_as(), a[4].safe_as(), a[5].safe_as(), a[6].safe_as(), a[7].safe_as(), a[8].safe_as(), a[9].safe_as()); } Fcn _fcn; }; template void register_factory(const std::string &path, 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(fcn); _register_factory(path, r); } /*********************************************************************** * Templated make implementations **********************************************************************/ inline Element *make(const std::string &path) { PMCList args(0); return _handle_make(path, PMC_M(args)); } template Element *make(const std::string &path, const A0 &a0) { PMCList args(1); args[0] = PMC_M(a0); return _handle_make(path, PMC_M(args)); } template Element *make(const std::string &path, const A0 &a0, const A1 &a1) { PMCList args(2); args[0] = PMC_M(a0); args[1] = PMC_M(a1); return _handle_make(path, PMC_M(args)); } template Element *make(const std::string &path, 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 _handle_make(path, PMC_M(args)); } template Element *make(const std::string &path, 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 _handle_make(path, PMC_M(args)); } template Element *make(const std::string &path, 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 _handle_make(path, PMC_M(args)); } template Element *make(const std::string &path, 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 _handle_make(path, PMC_M(args)); } template Element *make(const std::string &path, 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 _handle_make(path, PMC_M(args)); } template Element *make(const std::string &path, 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 _handle_make(path, PMC_M(args)); } template Element *make(const std::string &path, 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 _handle_make(path, PMC_M(args)); } template Element *make(const std::string &path, 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 _handle_make(path, PMC_M(args)); } } #endif /*INCLUDED_GRAS_DETAIL_FACTORY_HPP*/