1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
/*
*
* (C) 2003-2012 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*
*/
#ifndef EXTENSIBLE_H
#define EXTENSIBLE_H
#include "anope.h"
/* All items added to Extensible must inherit from this.
*/
class CoreExport ExtensibleItem
{
public:
virtual ~ExtensibleItem() { }
/* Called when this ExtensibleItem is being deleted. This should
* clean up things (eg, delete this;) if necessary.
*/
virtual void OnDelete() { delete this; }
};
/** Common class used to Extensible::Extend non-pointers from, as it doesn't delete
* itself when removed. Eg, obj->Extend(key, new ExtensibleItemClass<Anope::string>(value));
*/
template<typename T> struct CoreExport ExtensibleItemClass : T, ExtensibleItem
{
ExtensibleItemClass(const T& t) : T(t) { }
};
/* Used to attach arbitrary objects to this object using unique keys */
class CoreExport Extensible
{
private:
typedef std::map<Anope::string, ExtensibleItem *> extensible_map;
extensible_map extension_items;
public:
/** Default constructor, does nothing
*/
Extensible() { }
/** Destructor, deletes all of the extensible items in this object
* then clears the map
*/
virtual ~Extensible()
{
for (extensible_map::iterator it = extension_items.begin(), it_end = extension_items.end(); it != it_end; ++it)
if (it->second)
it->second->OnDelete();
extension_items.clear();
}
/** Extend an Extensible class.
*
* @param key The key parameter is an arbitary string which identifies the extension data
* @param p This parameter is a pointer to an ExtensibleItem or ExtensibleItemBase derived class
*
* You must provide a key to store the data as via the parameter 'key'.
* The data will be inserted into the map. If the data already exists, you may not insert it
* twice, Extensible::Extend will return false in this case.
*
* @return Returns true on success, false if otherwise
*/
void Extend(const Anope::string &key, ExtensibleItem *p)
{
this->Shrink(key);
this->extension_items[key] = p;
}
/** Shrink an Extensible class.
*
* @param key The key parameter is an arbitary string which identifies the extension data
*
* You must provide a key name. The given key name will be removed from the classes data. If
* you provide a nonexistent key (case is important) then the function will return false.
* @return Returns true on success.
*/
bool Shrink(const Anope::string &key)
{
extensible_map::iterator it = this->extension_items.find(key);
if (it != this->extension_items.end())
{
if (it->second != NULL)
it->second->OnDelete();
/* map::size_type map::erase( const key_type& key );
* returns the number of elements removed, std::map
* is single-associative so this should only be 0 or 1
*/
return this->extension_items.erase(key) > 0;
}
return false;
}
/** Get an extension item.
*
* @param key The key parameter is an arbitary string which identifies the extension data
* @return The item found
*/
template<typename T> T GetExt(const Anope::string &key) const
{
extensible_map::const_iterator it = this->extension_items.find(key);
if (it != this->extension_items.end())
return anope_dynamic_reinterpret_cast<T>(it->second);
return NULL;
}
/** Check if an extension item exists.
*
* @param key The key parameter is an arbitary string which identifies the extension data
* @return True if the item was found.
*/
bool HasExt(const Anope::string &key) const
{
return this->extension_items.count(key) > 0;
}
/** Get a list of all extension items names.
* @param list A deque of strings to receive the list
* @return This function writes a list of all extension items stored
* in this object by name into the given deque and returns void.
*/
void GetExtList(std::deque<Anope::string> &list) const
{
for (extensible_map::const_iterator it = extension_items.begin(), it_end = extension_items.end(); it != it_end; ++it)
list.push_back(it->first);
}
};
#endif // EXTENSIBLE_H
|