]> git.saurik.com Git - cydia.git/blob - Menes/Function.h
Cytore values need to be _packed (I got lucky :D).
[cydia.git] / Menes / Function.h
1 /* Cydia - iPhone UIKit Front-End for Debian APT
2 * Copyright (C) 2008-2015 Jay Freeman (saurik)
3 */
4
5 /* GNU General Public License, Version 3 {{{ */
6 /*
7 * Cydia is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation, either version 3 of the License,
10 * or (at your option) any later version.
11 *
12 * Cydia is distributed in the hope that it will be useful, but
13 * 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 Cydia. If not, see <http://www.gnu.org/licenses/>.
19 **/
20 /* }}} */
21
22 #ifndef Menes_Function_H
23 #define Menes_Function_H
24
25 #include "CyteKit/UCPlatform.h"
26
27 template <typename Result_, typename... Args_>
28 class Function {
29 private:
30 class Abstract {
31 private:
32 unsigned references_;
33
34 public:
35 Abstract() :
36 references_(0)
37 {
38 }
39
40 Abstract(const Abstract &) = delete;
41 Abstract &operator =(const Abstract &) = delete;
42
43 virtual ~Abstract() {
44 }
45
46 void Retain() {
47 ++references_;
48 }
49
50 void Release() {
51 if (--references_ == 0)
52 delete this;
53 }
54
55 virtual Result_ operator()(Args_... args) const = 0;
56 };
57
58 template <typename Callable_>
59 class Concrete :
60 public Abstract
61 {
62 private:
63 Callable_ callable_;
64
65 public:
66 Concrete(const Callable_ &callable) :
67 callable_(callable)
68 {
69 }
70
71 virtual Result_ operator()(Args_... args) const {
72 return callable_(args...);
73 }
74 };
75
76 private:
77 Abstract *abstract_;
78
79 void Release() {
80 if (abstract_ != NULL)
81 abstract_->Release();
82 }
83
84 void Copy(Abstract *abstract) {
85 if (abstract != NULL)
86 abstract->Retain();
87 Release();
88 abstract_ = abstract;
89 }
90
91 template <typename Callable_>
92 void Assign(const Callable_ &callable) {
93 Copy(new Concrete<Callable_>(callable));
94 }
95
96 public:
97 Function() :
98 abstract_(NULL)
99 {
100 }
101
102 Function(decltype(nullptr)) :
103 Function()
104 {
105 }
106
107 Function(const Function &function) :
108 abstract_(function.abstract_)
109 {
110 abstract_->Retain();
111 }
112
113 template <typename Callable_>
114 Function(const Callable_ &callable) :
115 Function()
116 {
117 Assign(callable);
118 }
119
120 ~Function() {
121 Release();
122 }
123
124 Function &operator =(decltype(nullptr)) {
125 Clear();
126 return *this;
127 }
128
129 Function &operator =(const Function &function) {
130 Copy(function.abstract_);
131 return *this;
132 }
133
134 Result_ operator()(Args_... args) const {
135 return (*abstract_)(args...);
136 }
137
138 void Clear() {
139 Release();
140 abstract_ = NULL;
141 }
142
143 template <typename Callable_>
144 Function &operator =(const Callable_ &callable) {
145 Assign(callable);
146 return *this;
147 }
148
149 operator bool() const {
150 return abstract_ != NULL;
151 }
152 };
153
154 #endif//Menes_Function_H