// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information. #ifndef INCLUDED_GRAS_DETAIL_CALLABLE_HPP #define INCLUDED_GRAS_DETAIL_CALLABLE_HPP #include //PMCList namespace gras { /*********************************************************************** * Registration entry base class **********************************************************************/ struct GRAS_API CallableRegistryEntry { CallableRegistryEntry(void); virtual ~CallableRegistryEntry(void); virtual PMCC call(const PMCC &args) = 0; }; /*********************************************************************** * Registration for return with 0 args **********************************************************************/ template struct CallableRegistryEntryImpl0 : CallableRegistryEntry { typedef ReturnType(ClassType::*Fcn)(void); CallableRegistryEntryImpl0(ClassType *obj, Fcn fcn): _obj(obj), _fcn(fcn){} PMCC call(const PMCC &) { return PMC_M((_obj->*_fcn)()); } ClassType *_obj; Fcn _fcn; }; template void Callable::register_call(const std::string &key, ReturnType(ClassType::*fcn)(void)) { ClassType *obj = dynamic_cast(this); void *fr = new CallableRegistryEntryImpl0(obj, fcn); _register_call(key, fr); } template struct CallableRegistryEntryImplVoid0 : CallableRegistryEntry { typedef void(ClassType::*Fcn)(void); CallableRegistryEntryImplVoid0(ClassType *obj, Fcn fcn): _obj(obj), _fcn(fcn){} PMCC call(const PMCC &) { (_obj->*_fcn)(); return PMCC(); } ClassType *_obj; Fcn _fcn; }; template void Callable::register_call(const std::string &key, void(ClassType::*fcn)(void)) { ClassType *obj = dynamic_cast(this); void *fr = new CallableRegistryEntryImplVoid0(obj, fcn); _register_call(key, fr); } /*********************************************************************** * Registration for return with 1 args **********************************************************************/ template struct CallableRegistryEntryImpl1 : CallableRegistryEntry { typedef ReturnType(ClassType::*Fcn)(const Arg0 &); CallableRegistryEntryImpl1(ClassType *obj, Fcn fcn): _obj(obj), _fcn(fcn){} PMCC call(const PMCC &args) { const PMCList &a = args.as(); return PMC_M((_obj->*_fcn)(a[0].safe_as())); } ClassType *_obj; Fcn _fcn; }; template void Callable::register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &)) { ClassType *obj = dynamic_cast(this); void *fr = new CallableRegistryEntryImpl1(obj, fcn); _register_call(key, fr); } template struct CallableRegistryEntryImplVoid1 : CallableRegistryEntry { typedef void(ClassType::*Fcn)(const Arg0 &); CallableRegistryEntryImplVoid1(ClassType *obj, Fcn fcn): _obj(obj), _fcn(fcn){} PMCC call(const PMCC &args) { const PMCList &a = args.as(); (_obj->*_fcn)(a[0].safe_as()); return PMCC(); } ClassType *_obj; Fcn _fcn; }; template void Callable::register_call(const std::string &key, void(ClassType::*fcn)(const Arg0 &)) { ClassType *obj = dynamic_cast(this); void *fr = new CallableRegistryEntryImplVoid1(obj, fcn); _register_call(key, fr); } /*********************************************************************** * Registration for return with 2 args **********************************************************************/ template struct CallableRegistryEntryImpl2 : CallableRegistryEntry { typedef ReturnType(ClassType::*Fcn)(const Arg0 &, const Arg1 &); CallableRegistryEntryImpl2(ClassType *obj, Fcn fcn): _obj(obj), _fcn(fcn){} PMCC call(const PMCC &args) { const PMCList &a = args.as(); return PMC_M((_obj->*_fcn)(a[0].safe_as(), a[1].safe_as())); } ClassType *_obj; Fcn _fcn; }; template void Callable::register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &, const Arg1 &)) { ClassType *obj = dynamic_cast(this); void *fr = new CallableRegistryEntryImpl2(obj, fcn); _register_call(key, fr); } template struct CallableRegistryEntryImplVoid2 : CallableRegistryEntry { typedef void(ClassType::*Fcn)(const Arg0 &, const Arg1 &); CallableRegistryEntryImplVoid2(ClassType *obj, Fcn fcn): _obj(obj), _fcn(fcn){} PMCC call(const PMCC &args) { const PMCList &a = args.as(); (_obj->*_fcn)(a[0].safe_as(), a[1].safe_as()); return PMCC(); } ClassType *_obj; Fcn _fcn; }; template void Callable::register_call(const std::string &key, void(ClassType::*fcn)(const Arg0 &, const Arg1 &)) { ClassType *obj = dynamic_cast(this); void *fr = new CallableRegistryEntryImplVoid2(obj, fcn); _register_call(key, fr); } /*********************************************************************** * Registration for return with 3 args **********************************************************************/ template struct CallableRegistryEntryImpl3 : CallableRegistryEntry { typedef ReturnType(ClassType::*Fcn)(const Arg0 &, const Arg1 &, const Arg2 &); CallableRegistryEntryImpl3(ClassType *obj, Fcn fcn): _obj(obj), _fcn(fcn){} PMCC call(const PMCC &args) { const PMCList &a = args.as(); return PMC_M((_obj->*_fcn)(a[0].safe_as(), a[1].safe_as(), a[2].safe_as())); } ClassType *_obj; Fcn _fcn; }; template void Callable::register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &, const Arg1 &, const Arg2 &)) { ClassType *obj = dynamic_cast(this); void *fr = new CallableRegistryEntryImpl3(obj, fcn); _register_call(key, fr); } template struct CallableRegistryEntryImplVoid3 : CallableRegistryEntry { typedef void(ClassType::*Fcn)(const Arg0 &, const Arg1 &, const Arg2 &); CallableRegistryEntryImplVoid3(ClassType *obj, Fcn fcn): _obj(obj), _fcn(fcn){} PMCC call(const PMCC &args) { const PMCList &a = args.as(); (_obj->*_fcn)(a[0].safe_as(), a[1].safe_as(), a[2].safe_as()); return PMCC(); } ClassType *_obj; Fcn _fcn; }; template void Callable::register_call(const std::string &key, void(ClassType::*fcn)(const Arg0 &, const Arg1 &, const Arg2 &)) { ClassType *obj = dynamic_cast(this); void *fr = new CallableRegistryEntryImplVoid3(obj, fcn); _register_call(key, fr); } /*********************************************************************** * Call implementations with 0 args **********************************************************************/ template ReturnType Callable::x(const std::string &key) { PMCList args(0); PMCC r = _handle_call(key, PMC_M(args)); return r.safe_as(); } inline void Callable::x(const std::string &key) { PMCList args(0); _handle_call(key, PMC_M(args)); } /*********************************************************************** * Call implementations with 1 args **********************************************************************/ template ReturnType Callable::x(const std::string &key, const Arg0 &a0) { PMCList args(1); args[0] = PMC_M(a0); PMCC r = _handle_call(key, PMC_M(args)); return r.safe_as(); } template void Callable::x(const std::string &key, const Arg0 &a0) { PMCList args(1); args[0] = PMC_M(a0); _handle_call(key, PMC_M(args)); } /*********************************************************************** * Call implementations with 2 args **********************************************************************/ template ReturnType Callable::x(const std::string &key, const Arg0 &a0, const Arg1 &a1) { PMCList args(2); args[0] = PMC_M(a0); args[1] = PMC_M(a1); PMCC r = _handle_call(key, PMC_M(args)); return r.safe_as(); } template void Callable::x(const std::string &key, const Arg0 &a0, const Arg1 &a1) { PMCList args(2); args[0] = PMC_M(a0); args[1] = PMC_M(a1); _handle_call(key, PMC_M(args)); } /*********************************************************************** * Call implementations with 3 args **********************************************************************/ template ReturnType Callable::x(const std::string &key, 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); PMCC r = _handle_call(key, PMC_M(args)); return r.safe_as(); } template void Callable::x(const std::string &key, 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); _handle_call(key, PMC_M(args)); } } //namespace gras #endif /*INCLUDED_GRAS_DETAIL_CALLABLE_HPP*/