]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/base.cpp
Specify which Extensible subclass an ExtensionItem is valid for
[user/henk/code/inspircd.git] / src / base.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
5  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
6  *   Copyright (C) 2004-2006 Craig Edwards <craigedwards@brainbox.cc>
7  *   Copyright (C) 2006 Oliver Lupton <oliverlupton@gmail.com>
8  *
9  * This file is part of InspIRCd.  InspIRCd is free software: you can
10  * redistribute it and/or modify it under the terms of the GNU General Public
11  * License as published by the Free Software Foundation, version 2.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22
23 #include "inspircd.h"
24 #include "base.h"
25 #include <time.h>
26 #include <typeinfo>
27
28 classbase::classbase()
29 {
30         if (ServerInstance)
31                 ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "classbase::+ @%p", (void*)this);
32 }
33
34 CullResult classbase::cull()
35 {
36         if (ServerInstance)
37                 ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "classbase::-%s @%p",
38                         typeid(*this).name(), (void*)this);
39         return CullResult();
40 }
41
42 classbase::~classbase()
43 {
44         if (ServerInstance)
45                 ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "classbase::~ @%p", (void*)this);
46 }
47
48 CullResult::CullResult()
49 {
50 }
51
52 // This trick detects heap allocations of refcountbase objects
53 static void* last_heap = NULL;
54
55 void* refcountbase::operator new(size_t size)
56 {
57         last_heap = ::operator new(size);
58         return last_heap;
59 }
60
61 void refcountbase::operator delete(void* obj)
62 {
63         if (last_heap == obj)
64                 last_heap = NULL;
65         ::operator delete(obj);
66 }
67
68 refcountbase::refcountbase() : refcount(0)
69 {
70         if (this != last_heap)
71                 throw CoreException("Reference allocate on the stack!");
72 }
73
74 refcountbase::~refcountbase()
75 {
76         if (refcount && ServerInstance)
77                 ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "refcountbase::~ @%p with refcount %d",
78                         (void*)this, refcount);
79 }
80
81 usecountbase::~usecountbase()
82 {
83         if (usecount && ServerInstance)
84                 ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "usecountbase::~ @%p with refcount %d",
85                         (void*)this, usecount);
86 }
87
88 ServiceProvider::~ServiceProvider()
89 {
90 }
91
92 ExtensionItem::ExtensionItem(const std::string& Key, ExtensibleType exttype, Module* mod)
93         : ServiceProvider(mod, Key, SERVICE_METADATA)
94         , type(exttype)
95 {
96 }
97
98 ExtensionItem::~ExtensionItem()
99 {
100 }
101
102 void* ExtensionItem::get_raw(const Extensible* container) const
103 {
104         Extensible::ExtensibleStore::const_iterator i =
105                 container->extensions.find(const_cast<ExtensionItem*>(this));
106         if (i == container->extensions.end())
107                 return NULL;
108         return i->second;
109 }
110
111 void* ExtensionItem::set_raw(Extensible* container, void* value)
112 {
113         std::pair<Extensible::ExtensibleStore::iterator,bool> rv =
114                 container->extensions.insert(std::make_pair(this, value));
115         if (rv.second)
116         {
117                 return NULL;
118         }
119         else
120         {
121                 void* old = rv.first->second;
122                 rv.first->second = value;
123                 return old;
124         }
125 }
126
127 void* ExtensionItem::unset_raw(Extensible* container)
128 {
129         Extensible::ExtensibleStore::iterator i = container->extensions.find(this);
130         if (i == container->extensions.end())
131                 return NULL;
132         void* rv = i->second;
133         container->extensions.erase(i);
134         return rv;
135 }
136
137 bool ExtensionManager::Register(ExtensionItem* item)
138 {
139         return types.insert(std::make_pair(item->name, item)).second;
140 }
141
142 void ExtensionManager::BeginUnregister(Module* module, std::vector<reference<ExtensionItem> >& list)
143 {
144         std::map<std::string, reference<ExtensionItem> >::iterator i = types.begin();
145         while (i != types.end())
146         {
147                 std::map<std::string, reference<ExtensionItem> >::iterator me = i++;
148                 ExtensionItem* item = me->second;
149                 if (item->creator == module)
150                 {
151                         list.push_back(item);
152                         types.erase(me);
153                 }
154         }
155 }
156
157 ExtensionItem* ExtensionManager::GetItem(const std::string& name)
158 {
159         std::map<std::string, reference<ExtensionItem> >::iterator i = types.find(name);
160         if (i == types.end())
161                 return NULL;
162         return i->second;
163 }
164
165 void Extensible::doUnhookExtensions(const std::vector<reference<ExtensionItem> >& toRemove)
166 {
167         for(std::vector<reference<ExtensionItem> >::const_iterator i = toRemove.begin(); i != toRemove.end(); ++i)
168         {
169                 ExtensionItem* item = *i;
170                 ExtensibleStore::iterator e = extensions.find(item);
171                 if (e != extensions.end())
172                 {
173                         item->free(e->second);
174                         extensions.erase(e);
175                 }
176         }
177 }
178
179 Extensible::Extensible()
180         : culled(false)
181 {
182 }
183
184 CullResult Extensible::cull()
185 {
186         FreeAllExtItems();
187         culled = true;
188         return classbase::cull();
189 }
190
191 void Extensible::FreeAllExtItems()
192 {
193         for(ExtensibleStore::iterator i = extensions.begin(); i != extensions.end(); ++i)
194         {
195                 i->first->free(i->second);
196         }
197         extensions.clear();
198 }
199
200 Extensible::~Extensible()
201 {
202         if ((!extensions.empty() || !culled) && ServerInstance)
203                 ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "Extensible destructor called without cull @%p", (void*)this);
204 }
205
206 LocalExtItem::LocalExtItem(const std::string& Key, ExtensibleType exttype, Module* mod)
207         : ExtensionItem(Key, exttype, mod)
208 {
209 }
210
211 LocalExtItem::~LocalExtItem()
212 {
213 }
214
215 std::string LocalExtItem::serialize(SerializeFormat format, const Extensible* container, void* item) const
216 {
217         return "";
218 }
219
220 void LocalExtItem::unserialize(SerializeFormat format, Extensible* container, const std::string& value)
221 {
222 }
223
224 LocalStringExt::LocalStringExt(const std::string& Key, ExtensibleType exttype, Module* Owner)
225         : SimpleExtItem<std::string>(Key, exttype, Owner)
226 {
227 }
228
229 LocalStringExt::~LocalStringExt()
230 {
231 }
232
233 std::string LocalStringExt::serialize(SerializeFormat format, const Extensible* container, void* item) const
234 {
235         if (item && format == FORMAT_USER)
236                 return *static_cast<std::string*>(item);
237         return "";
238 }
239
240 LocalIntExt::LocalIntExt(const std::string& Key, ExtensibleType exttype, Module* mod)
241         : LocalExtItem(Key, exttype, mod)
242 {
243 }
244
245 LocalIntExt::~LocalIntExt()
246 {
247 }
248
249 std::string LocalIntExt::serialize(SerializeFormat format, const Extensible* container, void* item) const
250 {
251         if (format != FORMAT_USER)
252                 return "";
253         return ConvToStr(reinterpret_cast<intptr_t>(item));
254 }
255
256 intptr_t LocalIntExt::get(const Extensible* container) const
257 {
258         return reinterpret_cast<intptr_t>(get_raw(container));
259 }
260
261 intptr_t LocalIntExt::set(Extensible* container, intptr_t value)
262 {
263         if (value)
264                 return reinterpret_cast<intptr_t>(set_raw(container, reinterpret_cast<void*>(value)));
265         else
266                 return reinterpret_cast<intptr_t>(unset_raw(container));
267 }
268
269 void LocalIntExt::free(void*)
270 {
271 }
272
273 StringExtItem::StringExtItem(const std::string& Key, ExtensibleType exttype, Module* mod)
274         : ExtensionItem(Key, exttype, mod)
275 {
276 }
277
278 StringExtItem::~StringExtItem()
279 {
280 }
281
282 std::string* StringExtItem::get(const Extensible* container) const
283 {
284         return static_cast<std::string*>(get_raw(container));
285 }
286
287 std::string StringExtItem::serialize(SerializeFormat format, const Extensible* container, void* item) const
288 {
289         return item ? *static_cast<std::string*>(item) : "";
290 }
291
292 void StringExtItem::unserialize(SerializeFormat format, Extensible* container, const std::string& value)
293 {
294         if (value.empty())
295                 unset(container);
296         else
297                 set(container, value);
298 }
299
300 void StringExtItem::set(Extensible* container, const std::string& value)
301 {
302         void* old = set_raw(container, new std::string(value));
303         delete static_cast<std::string*>(old);
304 }
305
306 void StringExtItem::unset(Extensible* container)
307 {
308         void* old = unset_raw(container);
309         delete static_cast<std::string*>(old);
310 }
311
312 void StringExtItem::free(void* item)
313 {
314         delete static_cast<std::string*>(item);
315 }
316
317 ModuleException::ModuleException(const std::string &message, Module* who)
318         : CoreException(message, who ? who->ModuleSourceFile : "A Module")
319 {
320 }