]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/base.cpp
Rename <chanhistory:notice> to <chanhistory:prefixmsg>.
[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 #ifdef INSPIRCD_ENABLE_RTTI
33         if (ServerInstance)
34                 ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "classbase::+%s @%p", typeid(*this).name(), (void*)this);
35 #endif
36 }
37
38 CullResult classbase::cull()
39 {
40 #ifdef INSPIRCD_ENABLE_RTTI
41         if (ServerInstance)
42                 ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "classbase::-%s @%p", typeid(*this).name(), (void*)this);
43 #endif
44         return CullResult();
45 }
46
47 classbase::~classbase()
48 {
49 #ifdef INSPIRCD_ENABLE_RTTI
50         if (ServerInstance)
51                 ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "classbase::~%s @%p", typeid(*this).name(), (void*)this);
52 #endif
53 }
54
55 CullResult::CullResult()
56 {
57 }
58
59 // This trick detects heap allocations of refcountbase objects
60 static void* last_heap = NULL;
61
62 void* refcountbase::operator new(size_t size)
63 {
64         last_heap = ::operator new(size);
65         return last_heap;
66 }
67
68 void refcountbase::operator delete(void* obj)
69 {
70         if (last_heap == obj)
71                 last_heap = NULL;
72         ::operator delete(obj);
73 }
74
75 refcountbase::refcountbase() : refcount(0)
76 {
77         if (this != last_heap)
78                 throw CoreException("Reference allocate on the stack!");
79 }
80
81 refcountbase::~refcountbase()
82 {
83         if (refcount && ServerInstance)
84                 ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "refcountbase::~ @%p with refcount %d",
85                         (void*)this, refcount);
86 }
87
88 usecountbase::~usecountbase()
89 {
90         if (usecount && ServerInstance)
91                 ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "usecountbase::~ @%p with refcount %d",
92                         (void*)this, usecount);
93 }
94
95 ServiceProvider::~ServiceProvider()
96 {
97 }
98
99 void ServiceProvider::RegisterService()
100 {
101 }
102
103 ExtensionItem::ExtensionItem(const std::string& Key, ExtensibleType exttype, Module* mod)
104         : ServiceProvider(mod, Key, SERVICE_METADATA)
105         , type(exttype)
106 {
107 }
108
109 ExtensionItem::~ExtensionItem()
110 {
111 }
112
113 void* ExtensionItem::get_raw(const Extensible* container) const
114 {
115         Extensible::ExtensibleStore::const_iterator i =
116                 container->extensions.find(const_cast<ExtensionItem*>(this));
117         if (i == container->extensions.end())
118                 return NULL;
119         return i->second;
120 }
121
122 void* ExtensionItem::set_raw(Extensible* container, void* value)
123 {
124         std::pair<Extensible::ExtensibleStore::iterator,bool> rv =
125                 container->extensions.insert(std::make_pair(this, value));
126         if (rv.second)
127         {
128                 return NULL;
129         }
130         else
131         {
132                 void* old = rv.first->second;
133                 rv.first->second = value;
134                 return old;
135         }
136 }
137
138 void* ExtensionItem::unset_raw(Extensible* container)
139 {
140         Extensible::ExtensibleStore::iterator i = container->extensions.find(this);
141         if (i == container->extensions.end())
142                 return NULL;
143         void* rv = i->second;
144         container->extensions.erase(i);
145         return rv;
146 }
147
148 void ExtensionItem::RegisterService()
149 {
150         if (!ServerInstance->Extensions.Register(this))
151                 throw ModuleException("Extension already exists: " + name);
152 }
153
154 bool ExtensionManager::Register(ExtensionItem* item)
155 {
156         return types.insert(std::make_pair(item->name, item)).second;
157 }
158
159 void ExtensionManager::BeginUnregister(Module* module, std::vector<reference<ExtensionItem> >& list)
160 {
161         ExtMap::iterator i = types.begin();
162         while (i != types.end())
163         {
164                 ExtMap::iterator me = i++;
165                 ExtensionItem* item = me->second;
166                 if (item->creator == module)
167                 {
168                         list.push_back(item);
169                         types.erase(me);
170                 }
171         }
172 }
173
174 ExtensionItem* ExtensionManager::GetItem(const std::string& name)
175 {
176         ExtMap::iterator i = types.find(name);
177         if (i == types.end())
178                 return NULL;
179         return i->second;
180 }
181
182 void Extensible::doUnhookExtensions(const std::vector<reference<ExtensionItem> >& toRemove)
183 {
184         for(std::vector<reference<ExtensionItem> >::const_iterator i = toRemove.begin(); i != toRemove.end(); ++i)
185         {
186                 ExtensionItem* item = *i;
187                 ExtensibleStore::iterator e = extensions.find(item);
188                 if (e != extensions.end())
189                 {
190                         item->free(this, e->second);
191                         extensions.erase(e);
192                 }
193         }
194 }
195
196 Extensible::Extensible()
197         : culled(false)
198 {
199 }
200
201 CullResult Extensible::cull()
202 {
203         FreeAllExtItems();
204         culled = true;
205         return classbase::cull();
206 }
207
208 void Extensible::FreeAllExtItems()
209 {
210         for(ExtensibleStore::iterator i = extensions.begin(); i != extensions.end(); ++i)
211         {
212                 i->first->free(this, i->second);
213         }
214         extensions.clear();
215 }
216
217 Extensible::~Extensible()
218 {
219         if ((!extensions.empty() || !culled) && ServerInstance)
220                 ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "Extensible destructor called without cull @%p", (void*)this);
221 }
222
223 void ExtensionItem::FromInternal(Extensible* container, const std::string& value)
224 {
225         FromNetwork(container, value);
226 }
227
228 void ExtensionItem::FromNetwork(Extensible* container, const std::string& value)
229 {
230 }
231
232 std::string ExtensionItem::ToHuman(const Extensible* container, void* item) const
233 {
234         // Try to use the network form by default.
235         std::string ret = ToNetwork(container, item);
236
237         // If there's no network form then fall back to the internal form.
238         if (ret.empty())
239                 ret = ToInternal(container, item);
240
241         return ret;
242 }
243
244 std::string ExtensionItem::ToInternal(const Extensible* container, void* item) const
245 {
246         return ToNetwork(container, item);
247 }
248
249 std::string ExtensionItem::ToNetwork(const Extensible* container, void* item) const
250 {
251         return std::string();
252 }
253
254 std::string ExtensionItem::serialize(SerializeFormat format, const Extensible* container, void* item) const
255 {
256         // Wrap the deprecated API with the new API.
257         switch (format)
258         {
259                 case FORMAT_USER:
260                         return ToHuman(container, item);
261                 case FORMAT_INTERNAL:
262                 case FORMAT_PERSIST:
263                         return ToInternal(container, item);
264                 case FORMAT_NETWORK:
265                         return ToNetwork(container, item);
266         }
267         return "";
268 }
269
270
271 void ExtensionItem::unserialize(SerializeFormat format, Extensible* container, const std::string& value)
272 {
273         // Wrap the deprecated API with the new API.
274         switch (format)
275         {
276                 case FORMAT_USER:
277                         break;
278                 case FORMAT_INTERNAL:
279                 case FORMAT_PERSIST:
280                         FromInternal(container, value);
281                         break;
282                 case FORMAT_NETWORK:
283                         FromNetwork(container, value);
284                         break;
285         }
286 }
287
288 LocalStringExt::LocalStringExt(const std::string& Key, ExtensibleType exttype, Module* Owner)
289         : SimpleExtItem<std::string>(Key, exttype, Owner)
290 {
291 }
292
293 LocalStringExt::~LocalStringExt()
294 {
295 }
296
297 std::string LocalStringExt::ToInternal(const Extensible* container, void* item) const
298 {
299         return item ? *static_cast<std::string*>(item) : std::string(); 
300 }
301
302 void LocalStringExt::FromInternal(Extensible* container, const std::string& value)
303 {
304         set(container, value);
305 }
306
307 LocalIntExt::LocalIntExt(const std::string& Key, ExtensibleType exttype, Module* mod)
308         : ExtensionItem(Key, exttype, mod)
309 {
310 }
311
312 LocalIntExt::~LocalIntExt()
313 {
314 }
315
316 std::string LocalIntExt::ToInternal(const Extensible* container, void* item) const
317 {
318         return ConvToStr(reinterpret_cast<intptr_t>(item));
319 }
320
321 void LocalIntExt::FromInternal(Extensible* container, const std::string& value)
322 {
323         set(container, ConvToNum<intptr_t>(value));
324 }
325
326 intptr_t LocalIntExt::get(const Extensible* container) const
327 {
328         return reinterpret_cast<intptr_t>(get_raw(container));
329 }
330
331 intptr_t LocalIntExt::set(Extensible* container, intptr_t value)
332 {
333         if (value)
334                 return reinterpret_cast<intptr_t>(set_raw(container, reinterpret_cast<void*>(value)));
335         else
336                 return reinterpret_cast<intptr_t>(unset_raw(container));
337 }
338
339 void LocalIntExt::free(Extensible* container, void* item)
340 {
341 }
342
343 StringExtItem::StringExtItem(const std::string& Key, ExtensibleType exttype, Module* mod)
344         : ExtensionItem(Key, exttype, mod)
345 {
346 }
347
348 StringExtItem::~StringExtItem()
349 {
350 }
351
352 std::string* StringExtItem::get(const Extensible* container) const
353 {
354         return static_cast<std::string*>(get_raw(container));
355 }
356
357 std::string StringExtItem::ToNetwork(const Extensible* container, void* item) const
358 {
359         return item ? *static_cast<std::string*>(item) : std::string();
360 }
361
362 void StringExtItem::FromNetwork(Extensible* container, const std::string& value)
363 {
364         if (value.empty())
365                 unset(container);
366         else
367                 set(container, value);
368 }
369
370 void StringExtItem::set(Extensible* container, const std::string& value)
371 {
372         void* old = set_raw(container, new std::string(value));
373         free(container, old);
374 }
375
376 void StringExtItem::unset(Extensible* container)
377 {
378         void* old = unset_raw(container);
379         free(container, old);
380 }
381
382 void StringExtItem::free(Extensible* container, void* item)
383 {
384         delete static_cast<std::string*>(item);
385 }
386
387 ModuleException::ModuleException(const std::string &message, Module* who)
388         : CoreException(message, who ? who->ModuleSourceFile : "A Module")
389 {
390 }