1 /*
2    (C) Copyright 2000 Joel Vennin
3    Special Thanks to Rich Hickey
4 
5    Part of the Adonthell Project <http://adonthell.nongnu.org>
6 
7    Adonthell is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11 
12    Adonthell is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with Adonthell.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #ifndef _CALL_BACK_H_
22 #define _CALL_BACK_H_
23 
24 #include <string.h>
25 #include <stddef.h>
26 
27 class FunctorBase
28 {
29  protected:
30   typedef void (FunctorBase::*PMemFunc)();
31   typedef void (*PFunc)();
32   enum {MEM_FUNC_SIZE = sizeof(PMemFunc)};
33   union{
34     PFunc func;
35     char memFunc[MEM_FUNC_SIZE];
36   };
37   void *callee;
FunctorBase()38   FunctorBase():func(0),callee(0){}
FunctorBase(const void * c,PFunc f,const void * mf,size_t sz)39   FunctorBase(const void *c,PFunc f, const void *mf,size_t sz):callee((void *)c)
40     {
41       if(c)
42 	{
43 	  memcpy(memFunc,mf,sz);
44 	  if(sz<MEM_FUNC_SIZE)
45 	    memset(memFunc+sz,0,MEM_FUNC_SIZE-sz);
46 	}
47       else func = f;
48     }
49 
50  public:
51   operator bool()const{return callee||func;}
52   friend bool operator==(const FunctorBase &lhs,const FunctorBase &rhs);
53   friend bool operator!=(const FunctorBase &lhs,const FunctorBase &rhs);
54   friend bool operator<(const FunctorBase &lhs,const FunctorBase &rhs);
getFunc()55   PFunc	getFunc() const {return func;}
getCallee()56   void *getCallee() const {return callee;}
getMemFunc()57   const char *getMemFunc() const {return memFunc;}
58 };
59 
60 
61 class Functor0:public FunctorBase
62 {
63  private:
64   typedef void (*Thunk)(const FunctorBase &);
65   Thunk thunk;
66  protected:
Functor0(Thunk t,const void * c,PFunc f,const void * mf,size_t sz)67   Functor0(Thunk t,const void *c,PFunc f,const void *mf,size_t sz):FunctorBase(c,f,mf,sz),thunk(t){}
68  public:
Functor0()69   Functor0(){}
operator()70   void operator()()const
71    {
72       thunk(*this);
73     }
74 };
75 
76 
77 template <class Callee, class MemFunc>
78 class MemberTranslator0:public Functor0{
79  public:
MemberTranslator0(Callee & c,MemFunc & m)80   MemberTranslator0(Callee &c, MemFunc &m):Functor0(thunk,&c,0,&m,sizeof(MemFunc)){}
thunk(const FunctorBase & ftor)81   static void thunk(const FunctorBase &ftor)
82     {
83       Callee *callee = (Callee *)ftor.getCallee();
84       MemFunc &memFunc = (*(MemFunc*)(void *)(ftor.getMemFunc()));
85       (callee->*memFunc)();
86     }
87 };
88 
89 template <class Func>
90 class FunctionTranslator0:public Functor0{
91  public:
FunctionTranslator0(Func f)92   FunctionTranslator0(Func f):Functor0(thunk,0,(PFunc)f,0,0){}
thunk(const FunctorBase & ftor)93   static void thunk(const FunctorBase &ftor)
94     {
95       (Func(ftor.getFunc()))();
96     }
97 };
98 
99 template <class Callee,class TRT,class CallType>
100 inline MemberTranslator0<Callee,TRT (CallType::*)()>
makeFunctor(Callee & c,TRT (CallType::* f)())101 makeFunctor(Callee &c,TRT (CallType::* f)())
102 {
103   typedef TRT (CallType::*MemFunc)();
104   return MemberTranslator0<Callee,MemFunc>(c,f);
105 }
106 
107 
108 template <class Callee,class TRT,class CallType>
109 inline MemberTranslator0<const Callee,TRT (CallType::*)()const>
makeFunctor(const Callee & c,TRT (CallType::* f)()const)110 makeFunctor(const Callee &c, TRT (CallType::* f)()const)
111 {
112   typedef TRT (CallType::*MemFunc)()const;
113   return MemberTranslator0<const Callee,MemFunc>(c,f);
114 }
115 
116 template <class TRT>
117 inline FunctionTranslator0<TRT (*)()>
makeFunctor(TRT (* f)())118 makeFunctor(TRT (*f)())
119 {
120   return FunctionTranslator0<TRT (*)()>(f);
121 }
122 
123 
124 //NO ARG WITH RETURN
125 
126 template <class RT>
127 class Functor0wRet:public FunctorBase{
128 public:
Functor0wRet()129   Functor0wRet(){}
operator()130 	RT operator()()const
131 		{
132 		return thunk(*this);
133 		}
134 protected:
135 	typedef RT (*Thunk)(const FunctorBase &);
Functor0wRet(Thunk t,const void * c,PFunc f,const void * mf,size_t sz)136 	Functor0wRet(Thunk t,const void *c,PFunc f,const void *mf,size_t sz):
137 		FunctorBase(c,f,mf,sz),thunk(t){}
138 private:
139 	Thunk thunk;
140 };
141 
142 
143 template <class RT,class Callee, class MemFunc>
144 class MemberTranslator0wRet:public Functor0wRet<RT>{
145 public:
MemberTranslator0wRet(Callee & c,MemFunc & m)146 	MemberTranslator0wRet(Callee &c,MemFunc &m):
147 		Functor0wRet<RT>(thunk,&c,0,&m,sizeof(MemFunc)){}
thunk(const FunctorBase & ftor)148 	static RT thunk(const FunctorBase &ftor)
149 		{
150 		Callee *callee = (Callee *)ftor.getCallee();
151 		MemFunc &memFunc = (*(MemFunc*)(void *)(ftor.getMemFunc()));
152 		return ((callee->*memFunc)());
153 		}
154 };
155 
156 
157 template <class RT,class Func>
158 class FunctionTranslator0wRet:public Functor0wRet<RT>{
159 public:
FunctionTranslator0wRet(Func f)160 	FunctionTranslator0wRet(Func f):Functor0wRet<RT>(thunk,0,(typename FunctionTranslator0wRet<RT, Func>::PFunc)f,0,0){}
thunk(const FunctorBase & ftor)161 	static RT thunk(const FunctorBase &ftor)
162 		{
163 		return (Func(ftor.getFunc()))();
164 		}
165 };
166 
167 
168 
169 template <class RT,class Callee,class TRT,class CallType>
170 inline MemberTranslator0wRet<RT,Callee,TRT (CallType::*)()>
makeFunctor(Functor0wRet<RT> *,Callee & c,TRT (CallType::* f)())171 makeFunctor(Functor0wRet<RT>*,Callee &c,TRT (CallType::* f)())
172 {
173   typedef TRT (CallType::*MemFunc)();
174   return MemberTranslator0wRet<RT,Callee,MemFunc>(c,f);
175 }
176 
177 
178 
179 template <class RT,class Callee,class TRT,class CallType>
180 inline MemberTranslator0wRet<RT,const Callee,TRT (CallType::*)()const>
makeFunctor(Functor0wRet<RT> *,const Callee & c,TRT (CallType::* f)()const)181 makeFunctor(Functor0wRet<RT>*,const Callee &c, TRT (CallType::* f)()const)
182 {
183   typedef TRT (CallType::*MemFunc)()const;
184   return MemberTranslator0wRet<RT,const Callee,MemFunc>(c,f);
185 }
186 
187 
188 template <class RT,class TRT>
189 inline FunctionTranslator0wRet<RT,TRT (*)()>
makeFunctor(Functor0wRet<RT> *,TRT (* f)())190 makeFunctor(Functor0wRet<RT>*,TRT (*f)())
191 {
192   return FunctionTranslator0wRet<RT,TRT (*)()>(f);
193 }
194 
195 // 1 Argument, no return value
196 template <class P1> class Functor1 : public FunctorBase
197 {
198 public:
Functor1()199     Functor1() {}
operator()200     void operator () (P1 p1) const
201     {
202         thunk (*this, p1);
203     }
204 protected:
205     typedef void (*Thunk) (const FunctorBase &, P1);
Functor1(Thunk t,const void * c,PFunc f,const void * mf,size_t sz)206     Functor1 (Thunk t, const void *c, PFunc f, const void *mf, size_t sz)
207         : FunctorBase (c, f, mf, sz), thunk (t) { }
208 private:
209     Thunk thunk;
210 };
211 
212 template <class P1, class Callee, class MemFunc>
213 class MemberTranslator1 : public Functor1<P1>
214 {
215   public:
MemberTranslator1(Callee & c,MemFunc & m)216     MemberTranslator1 (Callee & c, MemFunc & m)
217         : Functor1<P1> (thunk, &c, 0, &m, sizeof (MemFunc)) { }
thunk(const FunctorBase & ftor,P1 p1)218     static void thunk (const FunctorBase & ftor, P1 p1)
219     {
220         Callee *callee = (Callee *) ftor.getCallee ();
221         MemFunc & memFunc (*(MemFunc *) (void *)(ftor.getMemFunc ()));
222         (callee->*memFunc) (p1);
223     }
224 };
225 
226 template <class P1, class Func>
227 class FunctionTranslator1 : public Functor1 <P1>
228 {
229 public:
FunctionTranslator1(Func f)230   FunctionTranslator1 (Func f) : Functor1 <P1> (thunk, 0, f, 0, 0) { }
thunk(const FunctorBase & ftor,P1 p1)231     static void thunk (const FunctorBase & ftor, P1 p1)
232     {
233         (Func (ftor.func)) (p1);
234     }
235 };
236 
237 template <class P1, class Callee, class TRT, class CallType>
238 inline MemberTranslator1 <P1, Callee, TRT (CallType::*)(P1)>
makeFunctor(Callee & c,TRT (CallType::* f)(P1))239 makeFunctor (Callee & c, TRT (CallType::* f) (P1))
240 {
241     typedef TRT (CallType::*MemFunc) (P1);
242     return MemberTranslator1 <P1, Callee, MemFunc> (c, f);
243 }
244 
245 template <class P1, class Callee, class TRT, class CallType, class TP1>
246 inline MemberTranslator1 <P1, const Callee, TRT (CallType::*) (TP1) const>
makeFunctor(const Callee & c,TRT (CallType::* const & f)(TP1)const)247 makeFunctor (const Callee & c, TRT (CallType::*const &f) (TP1) const)
248 {
249     typedef TRT (CallType::*MemFunc) (TP1) const;
250     return MemberTranslator1 <P1, const Callee, MemFunc> (c, f);
251 }
252 
253 template <class P1, class TRT, class TP1>
254 inline FunctionTranslator1 <P1, TRT (*)(TP1)>
makeFunctor(TRT (* f)(TP1))255 makeFunctor (TRT (*f) (TP1))
256 {
257     return FunctionTranslator1 <P1, TRT (*)(TP1) > (f);
258 }
259 
260 template <class P1, class MemFunc> class MemberOf1stArgTranslator1
261 : public Functor1 <P1>
262 {
263 public:
MemberOf1stArgTranslator1(MemFunc & m)264     MemberOf1stArgTranslator1 (MemFunc & m) :
265     Functor1 < P1 > (thunk, (void *)1, 0, &m, sizeof (MemFunc)) { }
thunk(const FunctorBase & ftor,P1 p1)266     static void thunk (const FunctorBase & ftor, P1 p1)
267     {
268         MemFunc & memFunc (*(MemFunc *) (void *)(ftor.memFunc));
269         (p1.*memFunc) ();
270     }
271 };
272 
273 template <class P1, class TRT, class CallType>
274 inline MemberOf1stArgTranslator1 <P1, TRT (CallType::*)()>
makeFunctor(TRT (CallType::* & f)())275 makeFunctor (TRT (CallType::* &f) ())
276 {
277     typedef TRT (CallType::*MemFunc) ();
278     return MemberOf1stArgTranslator1 <P1, MemFunc> (f);
279 }
280 
281 template <class P1, class TRT, class CallType>
282 inline MemberOf1stArgTranslator1 < P1, TRT (CallType::*)() const>
makeFunctor(TRT (CallType::* const & f)()const)283 makeFunctor (TRT (CallType::*const &f) () const)
284 {
285     typedef TRT (CallType::*MemFunc) () const;
286     return MemberOf1stArgTranslator1 <P1, MemFunc> (f);
287 }
288 
289 
290 #endif
291 
292 
293 
294 
295 
296 
297