Thread: [Cppunit-cvs] cppunit2/include/cpptl reflection.h,NONE,1.1 reflection.inl,NONE,1.1
Brought to you by:
blep
From: Baptiste L. <bl...@us...> - 2005-03-03 08:14:32
|
Update of /cvsroot/cppunit/cppunit2/include/cpptl In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29959 Added Files: reflection.h reflection.inl Log Message: * Simple reflection support --- NEW FILE: reflection.inl --- #ifndef CPPTL_REFLECTION_INL_INCLUDED # define CPPTL_REFLECTION_INL_INCLUDED namespace CppTL { namespace Reflect { // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // Class Class // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// inline Class & Class::create( const ConstString &name, TypeId type ) { ClassPtr class_( new Class( name, type ) ); registry()[ name ] = class_; return *class_; } inline const Class * Class::findClass( const ConstString &name ) { ClassesByName::const_iterator it = registry().find( name ); if ( it == registry().end() ) return 0; return it->second.get(); } inline Class::Class( const ConstString &name, TypeId type ) : name_( name ) , type_( type ) { } inline Class::ClassesByName & Class::registry() { static ClassesByName classes_; return classes_; } inline ConstString Class::getName() const { return name_; } inline const Method * Class::findMethod( const ConstString &name ) const { MethodsByName::const_iterator it = methodsByName_.find( name ); if ( it == methodsByName_.end() ) return 0; return it->second.get(); } inline void Class::addMethod( const ConstString &name, const Invokable &invokable ) { MethodPtr method( new Method( name, invokable ) ); methodsByName_[name] = method; } // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // Class Method // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// inline Method::Method( const ConstString &name, const Invokable &invokable ) : name_( name ) , invokable_( invokable ) { } inline void Method::invoke( const Any &object, const ArgValues &args, Any &result ) const { MethodCall call( *this, object, args, result ); invokable_.invoke( call ); } inline ConstString Method::getName() const { return name_; } inline size_type Method::getArgCount() const { return invokable_.argTypes_.size(); } inline TypeId Method::getArgType( size_type index ) const { return invokable_.argTypes_.at(index); } inline TypeId Method::getReturnType() const { return typeId( Type<void>() ); } inline AnyEnumerator<TypeId> Method::getArgTypes() const { return Enum::anyContainer( invokable_.argTypes_, Type<TypeId>() ); } // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // Class Invokable // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// inline Invokable::Invokable( const InvokableBasePtr &invokable ) : invokable_( invokable ) , returnType_( typeId( Type<void>() ) ) { } inline void Invokable::invoke( MethodCall &call ) const { invokable_->invoke( call ); } } } // namespace CppTL { namespace Reflect { #endif // CPPTL_REFLECTION_INL_INCLUDED --- NEW FILE: reflection.h --- #ifndef CPPTL_REFLECTION_H_INCLUDED # define CPPTL_REFLECTION_H_INCLUDED # include <cpptl/conststring.h> # include <cpptl/enumerator.h> # include <cpptl/sharedptr.h> # include <cpptl/any.h> # include <map> # include <vector> namespace CppTL { namespace Reflect { // Forwards class Class; class Invokable; class InvokableBase; class Method; struct MethodCall; typedef SharedPtr<InvokableBase> InvokableBasePtr; typedef std::vector<Any> ArgValues; struct MethodCall { MethodCall( const Method &method, const Any &holder, const ArgValues &args, Any &result ) : method_( method ) , holder_( holder ) , args_( args ) , result_( result ) { } const Method &method_; const Any &holder_; const ArgValues &args_; Any &result_; }; class Invokable { public: Invokable( const InvokableBasePtr &invokable ); virtual ~Invokable() { } void invoke( MethodCall &call ) const; TypeId returnType_; std::vector<TypeId> argTypes_; InvokableBasePtr invokable_; }; class InvokableBase { public: virtual ~InvokableBase() { } virtual void invoke( MethodCall &call ) const = 0; }; template<class Object> class Invokable0 : public InvokableBase { public: typedef void (Object::*Member)(); Invokable0( Member member ) : member_( member ) { } void invoke( MethodCall &call ) const { Object &object = *any_cast( call.holder_, Type<Object *>() ); (object.*member_)(); } private: Member member_; }; template<class Object ,class Arg1> class Invokable1 : public InvokableBase { public: typedef void (Object::*Member)( Arg1 a1 ); Invokable1( Member member ) : member_( member ) { } void invoke( MethodCall &call ) const { Object &object = *any_cast( call.holder_, Type<Object *>() ); (object.*member_)( any_cast( call.args_.at(0), Type<Arg1>() ) ); } private: Member member_; }; template<class Object ,class Arg1 ,class Arg2> class Invokable2: public InvokableBase { public: typedef void (Object::*Member)( Arg1 a1, Arg2 a2 ); Invokable2( Member member ) : member_( member ) { } void invoke( MethodCall &call ) const { Object &object = *any_cast( call.holder_, Type<Object *>() ); (object.*member_)( any_cast( call.args_.at(0), Type<Arg1>() ), any_cast( call.args_.at(1), Type<Arg2>() ) ); } private: Member member_; }; template<class Object> Invokable makeInvokable( void (Object::*member)() ) { Invokable invokable( InvokableBasePtr( new Invokable0<Object>( member ) ) ); return invokable; } template<class Object, class Arg1> Invokable makeInvokable( void (Object::*member)( Arg1 a1 ) ) { Invokable invokable( InvokableBasePtr( new Invokable1<Object,Arg1>( member ) ) ); invokable.argTypes_.push_back( typeId( Type<Arg1>() ) ); return invokable; } template<class Object, class Arg1, class Arg2> Invokable makeInvokable( void (Object::*member)( Arg1 a1, Arg2 a2 ) ) { Invokable invokable( InvokableBasePtr( new Invokable2<Object,Arg1,Arg2>( member ) ) ); invokable.argTypes_.push_back( typeId( Type<Arg1>() ) ); invokable.argTypes_.push_back( typeId( Type<Arg2>() ) ); return invokable; } class Method { public: Method( const ConstString &name, const Invokable &invokable ); void invoke( const Any &object, const ArgValues &args, Any &result ) const; ConstString getName() const; size_type getArgCount() const; TypeId getArgType( size_type index ) const; TypeId getReturnType() const; AnyEnumerator<TypeId> getArgTypes() const; private: Class *class_; ConstString name_; Invokable invokable_; }; template<class Holder> Any invokeWithArgValues( const Holder &object, const Method &method, const ArgValues &args ) { Any actualObject = makeAny( &*object ); Any result; method.invoke( actualObject, args, result ); return result; } class Class { public: static Class &create( const ConstString &name, TypeId type ); static const Class *findClass( const ConstString &name ); ConstString getName() const; const Method *findMethod( const ConstString &name ) const; void addMethod( const ConstString &name, const Invokable &invokable ); private: typedef SharedPtr<Class> ClassPtr; typedef SharedPtr<Method> MethodPtr; typedef std::map<ConstString,ClassPtr> ClassesByName; typedef std::map<ConstString,MethodPtr> MethodsByName; static ClassesByName ®istry(); Class( const ConstString &name, TypeId type ); MethodsByName methodsByName_; ConstString name_; TypeId type_; }; template<class ClassType> class AutoRegisterClass { public: AutoRegisterClass() { ClassType::registerClassReflection(); } }; # define CPPTL_REFLECT_CLASS_BEGIN( ClassType ) \ typedef ClassType _Reflection_SelfType; \ static void registerClassReflection() \ { \ ::CppTL::Reflect::Class &class_ = ::CppTL::Reflect::Class::create( #ClassType, \ ::CppTL::typeId( ::CppTL::Type<ClassType>() ) ); //# define CPPTL_REFLECT_CLASS_EXTEND( ClassType ) # define CPPTL_REFLECT_METHOD( method ) \ { \ ::CppTL::Reflect::Invokable invokable = ::CppTL::Reflect::makeInvokable( \ &_Reflection_SelfType::method ); \ class_.addMethod( #method, invokable ); \ } # define CPPTL_REFLECT_CLASS_END() \ } # define CPPTL_REFLECT_REGISTER_CLASS( ClassType ) \ static ::CppTL::Reflect::AutoRegisterClass<ClassType> \ CPPUT_MAKE_UNIQUE_NAME(cpptlReflectRegisterClass); } } // namespace CppTL { namespace Reflect # include <cpptl/reflection.inl> #endif // CPPTL_REFLECTION_H_INCLUDED |