summaryrefslogtreecommitdiff
path: root/Menes/Function.h
diff options
context:
space:
mode:
Diffstat (limited to 'Menes/Function.h')
-rw-r--r--Menes/Function.h154
1 files changed, 154 insertions, 0 deletions
diff --git a/Menes/Function.h b/Menes/Function.h
new file mode 100644
index 0000000..f058653
--- /dev/null
+++ b/Menes/Function.h
@@ -0,0 +1,154 @@
+/* Cydia - iPhone UIKit Front-End for Debian APT
+ * Copyright (C) 2008-2013 Jay Freeman (saurik)
+*/
+
+/* GNU General Public License, Version 3 {{{ */
+/*
+ * Cydia is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * Cydia is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Cydia. If not, see <http://www.gnu.org/licenses/>.
+**/
+/* }}} */
+
+#ifndef Menes_Function_H
+#define Menes_Function_H
+
+#include "CyteKit/UCPlatform.h"
+
+template <typename Result_, typename... Args_>
+class Function {
+ private:
+ class Abstract {
+ private:
+ unsigned references_;
+
+ public:
+ Abstract() :
+ references_(0)
+ {
+ }
+
+ Abstract(const Abstract &) = delete;
+ Abstract &operator =(const Abstract &) = delete;
+
+ virtual ~Abstract() {
+ }
+
+ void Retain() {
+ ++references_;
+ }
+
+ void Release() {
+ if (--references_ == 0)
+ delete this;
+ }
+
+ virtual Result_ operator()(Args_... args) const = 0;
+ };
+
+ template <typename Callable_>
+ class Concrete :
+ public Abstract
+ {
+ private:
+ Callable_ callable_;
+
+ public:
+ Concrete(const Callable_ &callable) :
+ callable_(callable)
+ {
+ }
+
+ virtual Result_ operator()(Args_... args) const {
+ return callable_(args...);
+ }
+ };
+
+ private:
+ Abstract *abstract_;
+
+ void Release() {
+ if (abstract_ != NULL)
+ abstract_->Release();
+ }
+
+ void Copy(Abstract *abstract) {
+ if (abstract != NULL)
+ abstract->Retain();
+ Release();
+ abstract_ = abstract;
+ }
+
+ template <typename Callable_>
+ void Assign(const Callable_ &callable) {
+ Copy(new Concrete<Callable_>(callable));
+ }
+
+ public:
+ Function() :
+ abstract_(NULL)
+ {
+ }
+
+ Function(decltype(nullptr)) :
+ Function()
+ {
+ }
+
+ Function(const Function &function) :
+ abstract_(function.abstract_)
+ {
+ abstract_->Retain();
+ }
+
+ template <typename Callable_>
+ Function(const Callable_ &callable) :
+ Function()
+ {
+ Assign(callable);
+ }
+
+ ~Function() {
+ Release();
+ }
+
+ Function &operator =(decltype(nullptr)) {
+ Clear();
+ return *this;
+ }
+
+ Function &operator =(const Function &function) {
+ Copy(function.abstract_);
+ return *this;
+ }
+
+ Result_ operator()(Args_... args) const {
+ return (*abstract_)(args...);
+ }
+
+ void Clear() {
+ Release();
+ abstract_ = NULL;
+ }
+
+ template <typename Callable_>
+ Function &operator =(const Callable_ &callable) {
+ Assign(callable);
+ return *this;
+ }
+
+ operator bool() const {
+ return abstract_ != NULL;
+ }
+};
+
+#endif//Menes_Function_H