]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/base.cpp
Merge pull request #96 from Justasic/insp20
[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_config.h"
24 #include "base.h"
25 #include <time.h>
26 #include "inspircd.h"
27 #include <typeinfo>
28
29 classbase::classbase()
30 {
31         if (ServerInstance && ServerInstance->Logs)
32                 ServerInstance->Logs->Log("CULLLIST", DEBUG, "classbase::+ @%p", (void*)this);
33 }
34
35 CullResult classbase::cull()
36 {
37         if (ServerInstance && ServerInstance->Logs)
38                 ServerInstance->Logs->Log("CULLLIST", DEBUG, "classbase::-%s @%p",
39                         typeid(*this).name(), (void*)this);
40         return CullResult();
41 }
42
43 classbase::~classbase()
44 {
45         if (ServerInstance && ServerInstance->Logs)
46                 ServerInstance->Logs->Log("CULLLIST", DEBUG, "classbase::~ @%p", (void*)this);
47 }
48
49 CullResult::CullResult()
50 {
51 }
52
53 // This trick detects heap allocations of refcountbase objects
54 static void* last_heap = NULL;
55
56 void* refcountbase::operator new(size_t size)
57 {
58         last_heap = ::operator new(size);
59         return last_heap;
60 }
61
62 void refcountbase::operator delete(void* obj)
63 {
64         if (last_heap == obj)
65                 last_heap = NULL;
66         ::operator delete(obj);
67 }
68
69 refcountbase::refcountbase() : refcount(0)
70 {
71         if (this != last_heap)
72                 throw CoreException("Reference allocate on the stack!");
73 }
74
75 refcountbase::~refcountbase()
76 {
77         if (refcount && ServerInstance && ServerInstance->Logs)
78                 ServerInstance->Logs->Log("CULLLIST", DEBUG, "refcountbase::~ @%p with refcount %d",
79                         (void*)this, refcount);
80 }
81
82 usecountbase::~usecountbase()
83 {
84         if (usecount && ServerInstance && ServerInstance->Logs)
85                 ServerInstance->Logs->Log("CULLLIST", DEBUG, "usecountbase::~ @%p with refcount %d",
86                         (void*)this, usecount);
87 }
88
89 ServiceProvider::~ServiceProvider()
90 {
91 }
92
93 ExtensionItem::ExtensionItem(const std::string& Key, Module* mod) : ServiceProvider(mod, Key, SERVICE_METADATA)
94 {
95 }
96
97 ExtensionItem::~ExtensionItem()
98 {
99 }
100
101 void* ExtensionItem::get_raw(const Extensible* container) const
102 {
103         Extensible::ExtensibleStore::const_iterator i =
104                 container->extensions.find(const_cast<ExtensionItem*>(this));
105         if (i == container->extensions.end())
106                 return NULL;
107         return i->second;
108 }
109
110 void* ExtensionItem::set_raw(Extensible* container, void* value)
111 {
112         std::pair<Extensible::ExtensibleStore::iterator,bool> rv =
113                 container->extensions.insert(std::make_pair(this, value));
114         if (rv.second)
115         {
116                 return NULL;
117         }
118         else
119         {
120                 void* old = rv.first->second;
121                 rv.first->second = value;
122                 return old;
123         }
124 }
125
126 void* ExtensionItem::unset_raw(Extensible* container)
127 {
128         Extensible::ExtensibleStore::iterator i = container->extensions.find(this);
129         if (i == container->extensions.end())
130                 return NULL;
131         void* rv = i->second;
132         container->extensions.erase(i);
133         return rv;
134 }
135
136 void ExtensionManager::Register(ExtensionItem* item)
137 {
138         types.insert(std::make_pair(item->name, item));
139 }
140
141 void ExtensionManager::BeginUnregister(Module* module, std::vector<reference<ExtensionItem> >& list)
142 {
143         std::map<std::string, reference<ExtensionItem> >::iterator i = types.begin();
144         while (i != types.end())
145         {
146                 std::map<std::string, reference<ExtensionItem> >::iterator me = i++;
147                 ExtensionItem* item = me->second;
148                 if (item->creator == module)
149                 {
150                         list.push_back(item);
151                         types.erase(me);
152                 }
153         }
154 }
155
156 ExtensionItem* ExtensionManager::GetItem(const std::string& name)
157 {
158         std::map<std::string, reference<ExtensionItem> >::iterator i = types.find(name);
159         if (i == types.end())
160                 return NULL;
161         return i->second;
162 }
163
164 void Extensible::doUnhookExtensions(const std::vector<reference<ExtensionItem> >& toRemove)
165 {
166         for(std::vector<reference<ExtensionItem> >::const_iterator i = toRemove.begin(); i != toRemove.end(); ++i)
167         {
168                 ExtensionItem* item = *i;
169                 ExtensibleStore::iterator e = extensions.find(item);
170                 if (e != extensions.end())
171                 {
172                         item->free(e->second);
173                         extensions.erase(e);
174                 }
175         }
176 }
177
178 static struct DummyExtensionItem : LocalExtItem
179 {
180         DummyExtensionItem() : LocalExtItem("", NULL) {}
181         void free(void*) {}
182 } dummy;
183
184 Extensible::Extensible()
185 {
186         extensions[&dummy] = NULL;
187 }
188
189 CullResult Extensible::cull()
190 {
191         for(ExtensibleStore::iterator i = extensions.begin(); i != extensions.end(); ++i)
192         {
193                 i->first->free(i->second);
194         }
195         extensions.clear();
196         return classbase::cull();
197 }
198
199 Extensible::~Extensible()
200 {
201         if (!extensions.empty() && ServerInstance && ServerInstance->Logs)
202                 ServerInstance->Logs->Log("CULLLIST", DEBUG,
203                         "Extensible destructor called without cull @%p", (void*)this);
204 }
205
206 LocalExtItem::LocalExtItem(const std::string& Key, Module* mod) : ExtensionItem(Key, mod)
207 {
208 }
209
210 LocalExtItem::~LocalExtItem()
211 {
212 }
213
214 std::string LocalExtItem::serialize(SerializeFormat format, const Extensible* container, void* item) const
215 {
216         return "";
217 }
218
219 void LocalExtItem::unserialize(SerializeFormat format, Extensible* container, const std::string& value)
220 {
221 }
222
223 LocalStringExt::LocalStringExt(const std::string& Key, Module* Owner)
224         : SimpleExtItem<std::string>(Key, Owner) { }
225
226 LocalStringExt::~LocalStringExt()
227 {
228 }
229
230 std::string LocalStringExt::serialize(SerializeFormat format, const Extensible* container, void* item) const
231 {
232         if (item && format == FORMAT_USER)
233                 return *static_cast<std::string*>(item);
234         return "";
235 }
236
237 LocalIntExt::LocalIntExt(const std::string& Key, Module* mod) : LocalExtItem(Key, mod)
238 {
239 }
240
241 LocalIntExt::~LocalIntExt()
242 {
243 }
244
245 std::string LocalIntExt::serialize(SerializeFormat format, const Extensible* container, void* item) const
246 {
247         if (format != FORMAT_USER)
248                 return "";
249         return ConvToStr(reinterpret_cast<intptr_t>(item));
250 }
251
252 intptr_t LocalIntExt::get(const Extensible* container) const
253 {
254         return reinterpret_cast<intptr_t>(get_raw(container));
255 }
256
257 intptr_t LocalIntExt::set(Extensible* container, intptr_t value)
258 {
259         if (value)
260                 return reinterpret_cast<intptr_t>(set_raw(container, reinterpret_cast<void*>(value)));
261         else
262                 return reinterpret_cast<intptr_t>(unset_raw(container));
263 }
264
265 void LocalIntExt::free(void*)
266 {
267 }
268
269 StringExtItem::StringExtItem(const std::string& Key, Module* mod) : ExtensionItem(Key, mod)
270 {
271 }
272
273 StringExtItem::~StringExtItem()
274 {
275 }
276
277 std::string* StringExtItem::get(const Extensible* container) const
278 {
279         return static_cast<std::string*>(get_raw(container));
280 }
281
282 std::string StringExtItem::serialize(SerializeFormat format, const Extensible* container, void* item) const
283 {
284         return item ? *static_cast<std::string*>(item) : "";
285 }
286
287 void StringExtItem::unserialize(SerializeFormat format, Extensible* container, const std::string& value)
288 {
289         if (value.empty())
290                 unset(container);
291         else
292                 set(container, value);
293 }
294
295 void StringExtItem::set(Extensible* container, const std::string& value)
296 {
297         void* old = set_raw(container, new std::string(value));
298         delete static_cast<std::string*>(old);
299 }
300
301 void StringExtItem::unset(Extensible* container)
302 {
303         void* old = unset_raw(container);
304         delete static_cast<std::string*>(old);
305 }
306
307 void StringExtItem::free(void* item)
308 {
309         delete static_cast<std::string*>(item);
310 }
311
312 ModuleException::ModuleException(const std::string &message, Module* who)
313         : CoreException(message, who ? who->ModuleSourceFile : "A Module")
314 {
315 }
316