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