1 /*
2 * InspIRCd -- Internet Relay Chat Daemon
3 *
4 * Copyright (C) 2019-2020 Sadie Powell <sadie@witchery.services>
5 * Copyright (C) 2013-2015 Attila Molnar <attilamolnar@hush.com>
6 *
7 * This file is part of InspIRCd. InspIRCd is free software: you can
8 * redistribute it and/or modify it under the terms of the GNU General Public
9 * License as published by the Free Software Foundation, version 2.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 * details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21 #pragma once
22
23 #include "base.h"
24
25 class CoreExport dynamic_reference_base : public interfacebase, public insp::intrusive_list_node<dynamic_reference_base>
26 {
27 public:
28 class CaptureHook
29 {
30 public:
31 /** Called when the target of the dynamic_reference has been acquired
32 */
33 virtual void OnCapture() = 0;
34 };
35
36 private:
37 std::string name;
38 CaptureHook* hook;
39 void resolve();
40 protected:
41 ServiceProvider* value;
42 public:
43 ModuleRef creator;
44 dynamic_reference_base(Module* Creator, const std::string& Name);
45 ~dynamic_reference_base();
GetProvider()46 inline const std::string& GetProvider() const { return name; }
47 void SetProvider(const std::string& newname);
48
49 /** Set handler to call when the target object becomes available
50 * @param h Handler to call
51 */
SetCaptureHook(CaptureHook * h)52 void SetCaptureHook(CaptureHook* h) { hook = h; }
53
54 void check();
55 operator bool() const { return (value != NULL); }
56 static void reset_all();
57 };
58
check()59 inline void dynamic_reference_base::check()
60 {
61 if (!value)
62 throw ModuleException("Dynamic reference to '" + name + "' failed to resolve. Are you missing a module?");
63 }
64
65 template<typename T>
66 class dynamic_reference : public dynamic_reference_base
67 {
68 public:
dynamic_reference(Module * Creator,const std::string & Name)69 dynamic_reference(Module* Creator, const std::string& Name)
70 : dynamic_reference_base(Creator, Name) {}
71
72 inline T* operator->()
73 {
74 check();
75 return static_cast<T*>(value);
76 }
77
78 T* operator*()
79 {
80 return operator->();
81 }
82
83 const T* operator->() const
84 {
85 return static_cast<T*>(value);
86 }
87
88 const T* operator*() const
89 {
90 return operator->();
91 }
92 };
93
94 template<typename T>
95 class dynamic_reference_nocheck : public dynamic_reference_base
96 {
97 public:
dynamic_reference_nocheck(Module * Creator,const std::string & Name)98 dynamic_reference_nocheck(Module* Creator, const std::string& Name)
99 : dynamic_reference_base(Creator, Name) {}
100
101 T* operator->()
102 {
103 return static_cast<T*>(value);
104 }
105
106 T* operator*()
107 {
108 return operator->();
109 }
110
111 const T* operator->() const
112 {
113 return static_cast<T*>(value);
114 }
115
116 const T* operator*() const
117 {
118 return operator->();
119 }
120 };
121
122 class ModeHandler;
123 class ChanModeReference : public dynamic_reference_nocheck<ModeHandler>
124 {
125 public:
ChanModeReference(Module * mod,const std::string & modename)126 ChanModeReference(Module* mod, const std::string& modename)
127 : dynamic_reference_nocheck<ModeHandler>(mod, "mode/" + modename) {}
128 };
129
130 class UserModeReference : public dynamic_reference_nocheck<ModeHandler>
131 {
132 public:
UserModeReference(Module * mod,const std::string & modename)133 UserModeReference(Module* mod, const std::string& modename)
134 : dynamic_reference_nocheck<ModeHandler>(mod, "umode/" + modename) {}
135 };
136