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