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