anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
extensible.h (5972B)
1 /* 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 */ 8 9 #ifndef EXTENSIBLE_H 10 #define EXTENSIBLE_H 11 12 #include "anope.h" 13 #include "serialize.h" 14 #include "service.h" 15 #include "logger.h" 16 17 class Extensible; 18 19 class CoreExport ExtensibleBase : public Service 20 { 21 protected: 22 std::map<Extensible *, void *> items; 23 24 ExtensibleBase(Module *m, const Anope::string &n); 25 ~ExtensibleBase(); 26 27 public: 28 virtual void Unset(Extensible *obj) = 0; 29 30 /* called when an object we are keep track of is serializing */ 31 virtual void ExtensibleSerialize(const Extensible *, const Serializable *, Serialize::Data &) const { } 32 virtual void ExtensibleUnserialize(Extensible *, Serializable *, Serialize::Data &) { } 33 }; 34 35 class CoreExport Extensible 36 { 37 public: 38 std::set<ExtensibleBase *> extension_items; 39 40 virtual ~Extensible(); 41 42 void UnsetExtensibles(); 43 44 template<typename T> T* GetExt(const Anope::string &name) const; 45 bool HasExt(const Anope::string &name) const; 46 47 template<typename T> T* Extend(const Anope::string &name, const T &what); 48 template<typename T> T* Extend(const Anope::string &name); 49 template<typename T> T* Require(const Anope::string &name); 50 template<typename T> void Shrink(const Anope::string &name); 51 52 static void ExtensibleSerialize(const Extensible *, const Serializable *, Serialize::Data &data); 53 static void ExtensibleUnserialize(Extensible *, Serializable *, Serialize::Data &data); 54 }; 55 56 template<typename T> 57 class BaseExtensibleItem : public ExtensibleBase 58 { 59 protected: 60 virtual T *Create(Extensible *) = 0; 61 62 public: 63 BaseExtensibleItem(Module *m, const Anope::string &n) : ExtensibleBase(m, n) { } 64 65 ~BaseExtensibleItem() 66 { 67 while (!items.empty()) 68 { 69 std::map<Extensible *, void *>::iterator it = items.begin(); 70 Extensible *obj = it->first; 71 T *value = static_cast<T *>(it->second); 72 73 obj->extension_items.erase(this); 74 items.erase(it); 75 delete value; 76 } 77 } 78 79 T* Set(Extensible *obj, const T &value) 80 { 81 T* t = Set(obj); 82 if (t) 83 *t = value; 84 return t; 85 } 86 87 T* Set(Extensible *obj) 88 { 89 T* t = Create(obj); 90 Unset(obj); 91 items[obj] = t; 92 obj->extension_items.insert(this); 93 return t; 94 } 95 96 void Unset(Extensible *obj) anope_override 97 { 98 T *value = Get(obj); 99 items.erase(obj); 100 obj->extension_items.erase(this); 101 delete value; 102 } 103 104 T* Get(const Extensible *obj) const 105 { 106 std::map<Extensible *, void *>::const_iterator it = items.find(const_cast<Extensible *>(obj)); 107 if (it != items.end()) 108 return static_cast<T *>(it->second); 109 return NULL; 110 } 111 112 bool HasExt(const Extensible *obj) const 113 { 114 return items.find(const_cast<Extensible *>(obj)) != items.end(); 115 } 116 117 T* Require(Extensible *obj) 118 { 119 T* t = Get(obj); 120 if (t) 121 return t; 122 123 return Set(obj); 124 } 125 }; 126 127 template<typename T> 128 class ExtensibleItem : public BaseExtensibleItem<T> 129 { 130 protected: 131 T* Create(Extensible *obj) anope_override 132 { 133 return new T(obj); 134 } 135 public: 136 ExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<T>(m, n) { } 137 }; 138 139 template<typename T> 140 class PrimitiveExtensibleItem : public BaseExtensibleItem<T> 141 { 142 protected: 143 T* Create(Extensible *obj) anope_override 144 { 145 return new T(); 146 } 147 public: 148 PrimitiveExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<T>(m, n) { } 149 }; 150 151 template<> 152 class PrimitiveExtensibleItem<bool> : public BaseExtensibleItem<bool> 153 { 154 protected: 155 bool* Create(Extensible *) anope_override 156 { 157 return NULL; 158 } 159 public: 160 PrimitiveExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<bool>(m, n) { } 161 }; 162 163 template<typename T> 164 class SerializableExtensibleItem : public PrimitiveExtensibleItem<T> 165 { 166 public: 167 SerializableExtensibleItem(Module *m, const Anope::string &n) : PrimitiveExtensibleItem<T>(m, n) { } 168 169 void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override 170 { 171 T* t = this->Get(e); 172 data[this->name] << *t; 173 } 174 175 void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override 176 { 177 T t; 178 if (data[this->name] >> t) 179 this->Set(e, t); 180 else 181 this->Unset(e); 182 } 183 }; 184 185 template<> 186 class SerializableExtensibleItem<bool> : public PrimitiveExtensibleItem<bool> 187 { 188 public: 189 SerializableExtensibleItem(Module *m, const Anope::string &n) : PrimitiveExtensibleItem<bool>(m, n) { } 190 191 void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override 192 { 193 data[this->name] << true; 194 } 195 196 void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override 197 { 198 bool b = false; 199 data[this->name] >> b; 200 if (b) 201 this->Set(e); 202 else 203 this->Unset(e); 204 } 205 }; 206 207 template<typename T> 208 struct ExtensibleRef : ServiceReference<BaseExtensibleItem<T> > 209 { 210 ExtensibleRef(const Anope::string &n) : ServiceReference<BaseExtensibleItem<T> >("Extensible", n) { } 211 }; 212 213 template<typename T> 214 T* Extensible::GetExt(const Anope::string &name) const 215 { 216 ExtensibleRef<T> ref(name); 217 if (ref) 218 return ref->Get(this); 219 220 Log(LOG_DEBUG) << "GetExt for nonexistent type " << name << " on " << static_cast<const void *>(this); 221 return NULL; 222 } 223 224 template<typename T> 225 T* Extensible::Extend(const Anope::string &name, const T &what) 226 { 227 T* t = Extend<T>(name); 228 if (t) 229 *t = what; 230 return t; 231 } 232 233 template<typename T> 234 T* Extensible::Extend(const Anope::string &name) 235 { 236 ExtensibleRef<T> ref(name); 237 if (ref) 238 return ref->Set(this); 239 240 Log(LOG_DEBUG) << "Extend for nonexistent type " << name << " on " << static_cast<void *>(this); 241 return NULL; 242 } 243 244 template<typename T> 245 T* Extensible::Require(const Anope::string &name) 246 { 247 if (HasExt(name)) 248 return GetExt<T>(name); 249 else 250 return Extend<T>(name); 251 } 252 253 template<typename T> 254 void Extensible::Shrink(const Anope::string &name) 255 { 256 ExtensibleRef<T> ref(name); 257 if (ref) 258 ref->Unset(this); 259 else 260 Log(LOG_DEBUG) << "Shrink for nonexistent type " << name << " on " << static_cast<void *>(this); 261 } 262 263 #endif // EXTENSIBLE_H