File: Function.h

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,004 kB
  • sloc: ansic: 261,462; cpp: 140,405; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (178 lines) | stat: -rw-r--r-- 5,073 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#pragma once

#include "Blob.h"

namespace util {

	namespace fn {
		// Internal helpers for the function class.
		typedef Blob<2 * sizeof(void *)> PtrBlob; // Size is larger for complex fn ptrs sometimes

		// Do nothing
		template <class ReturnType, class ParameterType>
		ReturnType simpleNop(void *, const PtrBlob &ptr, ParameterType param) {
			return ReturnType();
		}

		template <class ReturnType>
		ReturnType simpleNopVoid(void *, const PtrBlob &ptr) {
			return ReturnType();
		}

		// Run a simple function pointer
		template <class ReturnType, class ParameterType>
		ReturnType simpleFnExecute(void *, const PtrBlob &ptr, ParameterType param) {
			typedef ReturnType (* FnPtr)(ParameterType);
			FnPtr fnPtr = ptr.get<FnPtr>();
			return (*fnPtr)(param);
		}

		template <class ReturnType>
		ReturnType simpleFnExecuteVoid(void *, const PtrBlob &ptr) {
			typedef ReturnType (* FnPtr)();
			FnPtr fnPtr = ptr.get<FnPtr>();
			return (*fnPtr)();
		}

		// Run a member function ptr
		template <class ReturnType, class ParameterType, class C>
		ReturnType memberFnExecute(void *thisPtr, const PtrBlob &ptr, ParameterType param) {
			typedef ReturnType (C:: *FnPtr)(ParameterType);
			FnPtr fnPtr = ptr.get<FnPtr>();
			C *cThisPtr = (C *)thisPtr;
			return (cThisPtr->*fnPtr)(param);
		}

		template <class ReturnType, class C>
		ReturnType memberFnExecuteVoid(void *thisPtr, const PtrBlob &ptr) {
			typedef ReturnType (C:: *FnPtr)();
			FnPtr fnPtr = ptr.get<FnPtr>();
			C *cThisPtr = (C *)thisPtr;
			return (cThisPtr->*fnPtr)();
		}
	}

	// Function pointer class. This class encapsulates a function pointer either to a simple C-style function
	// or to a member function. If it contains a member function to a class, it will also contain the "this" pointer
	// for that instance, so that functions encapsulated inside this object always can be treated as a simple C-style
	// function.
	// In the case of an empty function pointer, it will simply return ReturnType() for the specified return type.
	template <class ReturnType, class ParameterType = void>
	class Fn {
	public:
		// Create an empty fn ptr
		Fn() {
			thisPtr = null;
			toExecute = &fn::simpleNop<ReturnType, ParameterType>;
		}

		// Create from a simple function pointer.
		Fn(ReturnType (*fnPtr)(ParameterType)) {
			thisPtr = null;
			this->fnPtr.set(fnPtr);
			toExecute = &fn::simpleFnExecute<ReturnType, ParameterType>;
		}

		// Create from a member function.
		template <class C>
		Fn(C *thisPtr, ReturnType (C::* fnPtr)(ParameterType)) {
			this->thisPtr = thisPtr;
			this->fnPtr.set(fnPtr);
			toExecute = &fn::memberFnExecute<ReturnType, ParameterType, C>;
		}

		inline ReturnType operator ()(ParameterType p) const {
			return (*toExecute)(thisPtr, fnPtr, p);
		}

		bool operator ==(const Fn<ReturnType, ParameterType> &other) const {
			if (thisPtr != other.thisPtr) return false;
			if (fnPtr != other.fnPtr) return false;
			if (toExecute != other.toExecute) return false;
			return true;
		}
		inline bool operator !=(const Fn<ReturnType, ParameterType> &other) const { return !(*this == other); }

	private:
		void *thisPtr;
		fn::PtrBlob fnPtr;

		ReturnType (* toExecute)(void *, const fn::PtrBlob &, ParameterType);
	};

	// Specialization for <X, void>
	template <class ReturnType>
	class Fn<ReturnType, void> {
	public:
		// Create an empty fn ptr
		Fn() {
			thisPtr = null;
			toExecute = &fn::simpleNopVoid<ReturnType>;
		}

		// Create from a simple function pointer.
		Fn(ReturnType (*fnPtr)()) {
			thisPtr = null;
			this->fnPtr.set(fnPtr);
			toExecute = &fn::simpleFnExecuteVoid<ReturnType>;
		}

		// Create from a member function.
		template <class C>
		Fn(C *thisPtr, ReturnType (C::* fnPtr)()) {
			this->thisPtr = thisPtr;
			this->fnPtr.set(fnPtr);
			toExecute = &fn::memberFnExecuteVoid<ReturnType, C>;
		}

		inline ReturnType operator ()() const {
			return (*toExecute)(thisPtr, fnPtr);
		}

		bool operator ==(const Fn<ReturnType, void> &other) const {
			if (thisPtr != other.thisPtr) return false;
			if (fnPtr != other.fnPtr) return false;
			if (toExecute != other.toExecute) return false;
			return true;
		}
		inline bool operator !=(const Fn<ReturnType, void> &other) const { return !(*this == other); }

	private:
		void *thisPtr;
		fn::PtrBlob fnPtr;

		ReturnType (* toExecute)(void *, const fn::PtrBlob &);
	};

	// Create objects easily
	template <class A, class B>
	inline Fn<A, B> simpleFn(A (* p)(B)) {
		return Fn<A, B>(p);
	}

	template <class A>
	inline Fn<A, void> simpleVoidFn(A (* p)()) {
		return Fn<A, void>(p);
	}

	template <class A, class B, class C>
	inline Fn<A, B> memberFn(C *t, A (C:: *p)(B) const) {
		return Fn<A, B>(t, (A (C:: *)(B))p);
	}

	template <class A, class B, class C>
	inline Fn<A, B> memberFn(C *t, A (C:: *p)(B)) {
		return Fn<A, B>(t, p);
	}

	template <class A, class C>
	inline Fn<A, void> memberVoidFn(C *t, A (C:: *p)() const) {
		return Fn<A, void>(t, (A (C:: *)())p);
	}

	template <class A, class C>
	inline Fn<A, void> memberVoidFn(C *t, A (C:: *p)()) {
		return Fn<A, void>(t, p);
	}

}