callback.h

Go to the documentation of this file.
00001 
00006 /*
00007  Copyright (C) 2001-2006, William Joseph.
00008  All Rights Reserved.
00009 
00010  This file is part of GtkRadiant.
00011 
00012  GtkRadiant is free software; you can redistribute it and/or modify
00013  it under the terms of the GNU General Public License as published by
00014  the Free Software Foundation; either version 2 of the License, or
00015  (at your option) any later version.
00016 
00017  GtkRadiant is distributed in the hope that it will be useful,
00018  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  GNU General Public License for more details.
00021 
00022  You should have received a copy of the GNU General Public License
00023  along with GtkRadiant; if not, write to the Free Software
00024  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00025  */
00026 
00027 #if !defined(INCLUDED_GENERIC_CLOSURE_H)
00028 #define INCLUDED_GENERIC_CLOSURE_H
00029 
00030 #include <cstddef>
00031 #include "functional.h"
00032 #include "callbackfwd.h"
00033 
00034 template<typename Type>
00035 inline void* convertToOpaque (Type* t)
00036 {
00037     return t;
00038 }
00039 template<typename Type>
00040 inline void* convertToOpaque (const Type* t)
00041 {
00042     return const_cast<Type*> (t);
00043 }
00044 template<typename Type>
00045 inline void* convertToOpaque (Type& t)
00046 {
00047     return &t;
00048 }
00049 template<typename Type>
00050 inline void* convertToOpaque (const Type& t)
00051 {
00052     return const_cast<Type*> (&t);
00053 }
00054 
00055 template<typename Type>
00056 class ConvertFromOpaque
00057 {
00058 };
00059 
00060 template<typename Type>
00061 class ConvertFromOpaque<Type&>
00062 {
00063     public:
00064         static Type& apply (void* p)
00065         {
00066             return *static_cast<Type*> (p);
00067         }
00068 };
00069 
00070 template<typename Type>
00071 class ConvertFromOpaque<const Type&>
00072 {
00073     public:
00074         static const Type& apply (void* p)
00075         {
00076             return *static_cast<Type*> (p);
00077         }
00078 };
00079 
00080 template<typename Type>
00081 class ConvertFromOpaque<Type*>
00082 {
00083     public:
00084         static Type* apply (void* p)
00085         {
00086             return static_cast<Type*> (p);
00087         }
00088 };
00089 
00090 template<typename Type>
00091 class ConvertFromOpaque<const Type*>
00092 {
00093     public:
00094         static const Type* apply (void* p)
00095         {
00096             return static_cast<Type*> (p);
00097         }
00098 };
00099 
00100 template<typename Caller>
00101 class BindFirstOpaque
00102 {
00103         typedef typename Caller::first_argument_type FirstBound;
00104         FirstBound firstBound;
00105     public:
00106         typedef typename Caller::result_type result_type;
00107         explicit BindFirstOpaque (FirstBound firstBound) :
00108             firstBound(firstBound)
00109         {
00110         }
00111         result_type operator() () const
00112         {
00113             return Caller::call(firstBound);
00114         }
00115         FirstBound getBound () const
00116         {
00117             return firstBound;
00118         }
00119         static result_type thunk (void* environment)
00120         {
00121             return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment));
00122         }
00123         void* getEnvironment () const
00124         {
00125             return convertToOpaque(firstBound);
00126         }
00127 };
00128 
00129 template<typename Caller>
00130 class BindFirstOpaque1
00131 {
00132         typedef typename Caller::first_argument_type FirstBound;
00133         FirstBound firstBound;
00134     public:
00135         typedef typename Caller::second_argument_type first_argument_type;
00136         typedef typename Caller::result_type result_type;
00137         explicit BindFirstOpaque1 (FirstBound firstBound) :
00138             firstBound(firstBound)
00139         {
00140         }
00141         result_type operator() (first_argument_type a1) const
00142         {
00143             return Caller::call(firstBound, a1);
00144         }
00145         FirstBound getBound () const
00146         {
00147             return firstBound;
00148         }
00149         static result_type thunk (void* environment, first_argument_type a1)
00150         {
00151             return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), a1);
00152         }
00153         void* getEnvironment () const
00154         {
00155             return convertToOpaque(firstBound);
00156         }
00157 };
00158 
00159 template<typename Caller>
00160 class BindFirstOpaque2
00161 {
00162         typedef typename Caller::first_argument_type FirstBound;
00163         FirstBound firstBound;
00164     public:
00165         typedef typename Caller::second_argument_type first_argument_type;
00166         typedef typename Caller::third_argument_type second_argument_type;
00167         typedef typename Caller::result_type result_type;
00168         explicit BindFirstOpaque2 (FirstBound firstBound) :
00169             firstBound(firstBound)
00170         {
00171         }
00172         result_type operator() (first_argument_type a1, second_argument_type a2) const
00173         {
00174             return Caller::call(firstBound, a1, a2);
00175         }
00176         FirstBound getBound () const
00177         {
00178             return firstBound;
00179         }
00180         static result_type thunk (void* environment, first_argument_type a1, second_argument_type a2)
00181         {
00182             return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), a1, a2);
00183         }
00184         void* getEnvironment () const
00185         {
00186             return convertToOpaque(firstBound);
00187         }
00188 };
00189 
00190 template<typename Caller>
00191 class BindFirstOpaque3
00192 {
00193         typedef typename Caller::first_argument_type FirstBound;
00194         FirstBound firstBound;
00195     public:
00196         typedef typename Caller::second_argument_type first_argument_type;
00197         typedef typename Caller::third_argument_type second_argument_type;
00198         typedef typename Caller::fourth_argument_type third_argument_type;
00199         typedef typename Caller::result_type result_type;
00200         explicit BindFirstOpaque3 (FirstBound firstBound) :
00201             firstBound(firstBound)
00202         {
00203         }
00204         result_type operator() (first_argument_type a1, second_argument_type a2, third_argument_type a3) const
00205         {
00206             return Caller::call(firstBound, a1, a2, a3);
00207         }
00208         FirstBound getBound () const
00209         {
00210             return firstBound;
00211         }
00212         static result_type thunk (void* environment, first_argument_type a1, second_argument_type a2,
00213                 third_argument_type a3)
00214         {
00215             return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), a1, a2, a3);
00216         }
00217         void* getEnvironment () const
00218         {
00219             return convertToOpaque(firstBound);
00220         }
00221 };
00222 
00223 template<typename Thunk_>
00224 class CallbackBase
00225 {
00226         void* m_environment;
00227         Thunk_ m_thunk;
00228     public:
00229         typedef Thunk_ Thunk;
00230         CallbackBase (void* environment, Thunk function) :
00231             m_environment(environment), m_thunk(function)
00232         {
00233         }
00234         void* getEnvironment () const
00235         {
00236             return m_environment;
00237         }
00238         Thunk getThunk () const
00239         {
00240             return m_thunk;
00241         }
00242 };
00243 
00244 template<typename Thunk>
00245 inline bool operator== (const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other)
00246 {
00247     return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk();
00248 }
00249 template<typename Thunk>
00250 inline bool operator!= (const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other)
00251 {
00252     return !(self == other);
00253 }
00254 template<typename Thunk>
00255 inline bool operator< (const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other)
00256 {
00257     return self.getEnvironment() < other.getEnvironment() || (!(other.getEnvironment() < self.getEnvironment())
00258             && self.getThunk() < other.getThunk());
00259 }
00260 
00265 template<typename Result>
00266 class Callback0: public CallbackBase<Result(*) (void*)>
00267 {
00268         typedef CallbackBase<Result(*) (void*)> Base;
00269         static Result nullThunk (void*)
00270         {
00271         }
00272 
00273     public:
00274         typedef Result result_type;
00275 
00276         Callback0 () :
00277             Base(0, nullThunk)
00278         {
00279         }
00280         template<typename Caller>
00281         Callback0 (const BindFirstOpaque<Caller>& caller) :
00282             Base(caller.getEnvironment(), BindFirstOpaque<Caller>::thunk)
00283         {
00284         }
00285         Callback0 (void* environment, typename Base::Thunk function) :
00286             Base(environment, function)
00287         {
00288         }
00289         result_type operator() () const
00290         {
00291             return Base::getThunk()(Base::getEnvironment());
00292         }
00293 };
00294 
00295 template<typename Caller>
00296 inline Callback0<typename Caller::result_type> makeCallback0 (const Caller& caller,
00297         typename Caller::first_argument_type callee)
00298 {
00299     return Callback0<typename Caller::result_type> (BindFirstOpaque<Caller> (callee));
00300 }
00301 template<typename Caller>
00302 inline Callback0<typename Caller::result_type> makeStatelessCallback0 (const Caller& caller)
00303 {
00304     return makeCallback0(Caller0To1<Caller> (), 0);
00305 }
00306 
00307 typedef Callback0<void> Callback;
00308 
00313 template<typename FirstArgument, typename Result>
00314 class Callback1: public CallbackBase<Result(*) (void*, FirstArgument)>
00315 {
00316         typedef CallbackBase<Result(*) (void*, FirstArgument)> Base;
00317         static Result nullThunk (void*, FirstArgument)
00318         {
00319         }
00320 
00321     public:
00322         typedef FirstArgument first_argument_type;
00323         typedef Result result_type;
00324 
00325         Callback1 () :
00326             Base(0, nullThunk)
00327         {
00328         }
00329         template<typename Caller>
00330         Callback1 (const BindFirstOpaque1<Caller>& caller) :
00331             Base(caller.getEnvironment(), BindFirstOpaque1<Caller>::thunk)
00332         {
00333         }
00334         Callback1 (void* environment, typename Base::Thunk function) :
00335             Base(environment, function)
00336         {
00337         }
00338         result_type operator() (FirstArgument firstArgument) const
00339         {
00340             return Base::getThunk()(Base::getEnvironment(), firstArgument);
00341         }
00342 };
00343 
00344 template<typename Caller>
00345 inline Callback1<typename Caller::second_argument_type, typename Caller::result_type> makeCallback1 (
00346         const Caller& caller, typename Caller::first_argument_type callee)
00347 {
00348     return Callback1<typename Caller::second_argument_type, typename Caller::result_type> (BindFirstOpaque1<Caller> (
00349             callee));
00350 }
00351 template<typename Caller>
00352 inline Callback1<typename Caller::second_argument_type, typename Caller::result_type> makeStatelessCallback1 (
00353         const Caller& caller)
00354 {
00355     return makeCallback1(Caller1To2<Caller> (), 0);
00356 }
00357 
00361 template<typename FirstArgument, typename SecondArgument, typename Result>
00362 class Callback2: public CallbackBase<Result(*) (void*, FirstArgument, SecondArgument)>
00363 {
00364         typedef CallbackBase<Result(*) (void*, FirstArgument, SecondArgument)> Base;
00365         static Result nullThunk (void*, FirstArgument, SecondArgument)
00366         {
00367         }
00368 
00369     public:
00370         typedef FirstArgument first_argument_type;
00371         typedef SecondArgument second_argument_type;
00372         typedef Result result_type;
00373 
00374         Callback2 () :
00375             Base(0, nullThunk)
00376         {
00377         }
00378         template<typename Caller>
00379         Callback2 (const BindFirstOpaque2<Caller>& caller) :
00380             Base(caller.getEnvironment(), BindFirstOpaque2<Caller>::thunk)
00381         {
00382         }
00383         Callback2 (void* environment, typename Base::Thunk function) :
00384             Base(environment, function)
00385         {
00386         }
00387         result_type operator() (FirstArgument firstArgument, SecondArgument secondArgument) const
00388         {
00389             return Base::getThunk()(Base::getEnvironment(), firstArgument, secondArgument);
00390         }
00391 };
00392 
00393 template<typename Caller>
00394 inline Callback2<typename Caller::second_argument_type, typename Caller::third_argument_type,
00395         typename Caller::result_type> makeCallback2 (const Caller& caller, typename Caller::first_argument_type callee)
00396 {
00397     return Callback2<typename Caller::second_argument_type, typename Caller::third_argument_type,
00398             typename Caller::result_type> (BindFirstOpaque2<Caller> (callee));
00399 }
00400 template<typename Caller>
00401 inline Callback2<typename Caller::first_argument_type, typename Caller::second_argument_type,
00402         typename Caller::result_type> makeStatelessCallback2 (const Caller& caller)
00403 {
00404     return makeCallback2(Caller2To3<Caller> (), 0);
00405 }
00406 
00410 template<typename FirstArgument, typename SecondArgument, typename ThirdArgument, typename Result>
00411 class Callback3: public CallbackBase<Result(*) (void*, FirstArgument, SecondArgument, ThirdArgument)>
00412 {
00413         typedef CallbackBase<Result(*) (void*, FirstArgument, SecondArgument, ThirdArgument)> Base;
00414         static Result nullThunk (void*, FirstArgument, SecondArgument, ThirdArgument)
00415         {
00416         }
00417 
00418     public:
00419         typedef FirstArgument first_argument_type;
00420         typedef SecondArgument second_argument_type;
00421         typedef ThirdArgument third_argument_type;
00422         typedef Result result_type;
00423 
00424         Callback3 () :
00425             Base(0, nullThunk)
00426         {
00427         }
00428         template<typename Caller>
00429         Callback3 (const BindFirstOpaque3<Caller>& caller) :
00430             Base(caller.getEnvironment(), BindFirstOpaque3<Caller>::thunk)
00431         {
00432         }
00433         Callback3 (void* environment, typename Base::Thunk function) :
00434             Base(environment, function)
00435         {
00436         }
00437         result_type operator() (FirstArgument firstArgument, SecondArgument secondArgument, ThirdArgument thirdArgument) const
00438         {
00439             return Base::getThunk()(Base::getEnvironment(), firstArgument, secondArgument, thirdArgument);
00440         }
00441 };
00442 
00443 template<typename Caller>
00444 inline Callback3<typename Caller::second_argument_type, typename Caller::third_argument_type,
00445         typename Caller::fourth_argument_type, typename Caller::result_type> makeCallback3 (const Caller& caller,
00446         typename Caller::first_argument_type callee)
00447 {
00448     return Callback3<typename Caller::second_argument_type, typename Caller::third_argument_type,
00449             typename Caller::fourth_argument_type, typename Caller::result_type> (BindFirstOpaque3<Caller> (callee));
00450 }
00451 template<typename Caller>
00452 inline Callback3<typename Caller::first_argument_type, typename Caller::second_argument_type,
00453         typename Caller::third_argument_type, typename Caller::result_type> makeStatelessCallback3 (
00454         const Caller& caller)
00455 {
00456     return makeCallback3(Caller3To4<Caller> (), 0);
00457 }
00458 
00464 template<typename Environment, void(Environment::*member) ()>
00465 class MemberCaller: public BindFirstOpaque<Member<Environment, void, member> >
00466 {
00467     public:
00468         MemberCaller (Environment& environment) :
00469             BindFirstOpaque<Member<Environment, void, member> > (environment)
00470         {
00471         }
00472 };
00473 
00479 template<typename Environment, void(Environment::*member) () const>
00480 class ConstMemberCaller: public BindFirstOpaque<ConstMember<Environment, void, member> >
00481 {
00482     public:
00483         ConstMemberCaller (const Environment& environment) :
00484             BindFirstOpaque<ConstMember<Environment, void, member> > (environment)
00485         {
00486         }
00487 };
00488 
00492 template<typename Environment, typename FirstArgument, void(Environment::*member) (FirstArgument)>
00493 class MemberCaller1: public BindFirstOpaque1<Member1<Environment, FirstArgument, void, member> >
00494 {
00495     public:
00496         MemberCaller1 (Environment& environment) :
00497             BindFirstOpaque1<Member1<Environment, FirstArgument, void, member> > (environment)
00498         {
00499         }
00500 };
00501 
00505 template<typename Environment, typename FirstArgument, void(Environment::*member) (FirstArgument) const>
00506 class ConstMemberCaller1: public BindFirstOpaque1<ConstMember1<Environment, FirstArgument, void, member> >
00507 {
00508     public:
00509         ConstMemberCaller1 (const Environment& environment) :
00510             BindFirstOpaque1<ConstMember1<Environment, FirstArgument, void, member> > (environment)
00511         {
00512         }
00513 };
00514 
00520 template<typename Environment, void(*func) (Environment&)>
00521 class ReferenceCaller: public BindFirstOpaque<Function1<Environment&, void, func> >
00522 {
00523     public:
00524         ReferenceCaller (Environment& environment) :
00525             BindFirstOpaque<Function1<Environment&, void, func> > (environment)
00526         {
00527         }
00528 };
00529 
00535 template<typename Environment, void(*func) (const Environment&)>
00536 class ConstReferenceCaller: public BindFirstOpaque<Function1<const Environment&, void, func> >
00537 {
00538     public:
00539         ConstReferenceCaller (const Environment& environment) :
00540             BindFirstOpaque<Function1<const Environment&, void, func> > (environment)
00541         {
00542         }
00543 };
00544 
00548 template<typename Environment, typename FirstArgument, void(*func) (Environment&, FirstArgument)>
00549 class ReferenceCaller1: public BindFirstOpaque1<Function2<Environment&, FirstArgument, void, func> >
00550 {
00551     public:
00552         ReferenceCaller1 (Environment& environment) :
00553             BindFirstOpaque1<Function2<Environment&, FirstArgument, void, func> > (environment)
00554         {
00555         }
00556 };
00557 
00561 template<typename Environment, typename FirstArgument, void(*func) (const Environment&, FirstArgument)>
00562 class ConstReferenceCaller1: public BindFirstOpaque1<Function2<const Environment&, FirstArgument, void, func> >
00563 {
00564     public:
00565         ConstReferenceCaller1 (const Environment& environment) :
00566             BindFirstOpaque1<Function2<const Environment&, FirstArgument, void, func> > (environment)
00567         {
00568         }
00569 };
00570 
00574 template<typename Environment, void(*func) (const Environment*)>
00575 class ConstPointerCaller: public BindFirstOpaque<Function1<const Environment*, void, func> >
00576 {
00577     public:
00578         ConstPointerCaller (const Environment* environment) :
00579             BindFirstOpaque<Function1<const Environment*, void, func> > (environment)
00580         {
00581         }
00582 };
00583 
00587 template<typename Environment, typename FirstArgument, void(*func) (const Environment*, FirstArgument)>
00588 class ConstPointerCaller1: public BindFirstOpaque1<Function2<const Environment*, FirstArgument, void, func> >
00589 {
00590     public:
00591         ConstPointerCaller1 (const Environment* environment) :
00592             BindFirstOpaque1<Function2<const Environment*, FirstArgument, void, func> > (environment)
00593         {
00594         }
00595 };
00596 
00600 template<void(*func) ()>
00601 class FreeCaller: public BindFirstOpaque<Caller0To1<Function0<void, func> > >
00602 {
00603     public:
00604         FreeCaller () :
00605             BindFirstOpaque<Caller0To1<Function0<void, func> > > (0)
00606         {
00607         }
00608 };
00609 
00613 template<typename FirstArgument, void(*func) (FirstArgument)>
00614 class FreeCaller1: public BindFirstOpaque1<Caller1To2<Function1<FirstArgument, void, func> > >
00615 {
00616     public:
00617         FreeCaller1 () :
00618             BindFirstOpaque1<Caller1To2<Function1<FirstArgument, void, func> > > (0)
00619         {
00620         }
00621 };
00622 
00627 template<typename Functor>
00628 inline Callback makeCallback (Functor& functor)
00629 {
00630     return Callback(MemberCaller<Functor, &Functor::operator()> (functor));
00631 }
00632 
00637 template<typename Functor>
00638 inline Callback makeCallback (const Functor& functor)
00639 {
00640     return Callback(ConstMemberCaller<Functor, &Functor::operator()> (functor));
00641 }
00642 
00647 template<typename Functor>
00648 inline Callback1<typename Functor::first_argument_type> makeCallback1 (Functor& functor)
00649 {
00650     typedef typename Functor::first_argument_type FirstArgument;
00651     return Callback1<FirstArgument> (MemberCaller1<Functor, FirstArgument, &Functor::operator()> (functor));
00652 }
00653 
00658 template<typename Functor>
00659 inline Callback1<typename Functor::first_argument_type> makeCallback1 (const Functor& functor)
00660 {
00661     typedef typename Functor::first_argument_type FirstArgument;
00662     return Callback1<FirstArgument> (ConstMemberCaller1<Functor, FirstArgument, &Functor::operator()> (functor));
00663 }
00664 
00665 typedef Callback1<bool> BoolImportCallback;
00666 typedef Callback1<const BoolImportCallback&> BoolExportCallback;
00667 
00668 typedef Callback1<int> IntImportCallback;
00669 typedef Callback1<const IntImportCallback&> IntExportCallback;
00670 
00671 typedef Callback1<float> FloatImportCallback;
00672 typedef Callback1<const FloatImportCallback&> FloatExportCallback;
00673 
00674 typedef Callback1<const char*> StringImportCallback;
00675 typedef Callback1<const StringImportCallback&> StringExportCallback;
00676 
00677 typedef Callback1<std::size_t> SizeImportCallback;
00678 typedef Callback1<const SizeImportCallback&> SizeExportCallback;
00679 
00680 template<bool(*BoolFunction) ()>
00681 class BoolFunctionExport
00682 {
00683     public:
00684         static void apply (const BoolImportCallback& importCallback)
00685         {
00686             importCallback(BoolFunction());
00687         }
00688 };
00689 
00690 #endif

Generated by  doxygen 1.6.2