serialize.h

Go to the documentation of this file.
00001 /*
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church.
00010  *
00011  */
00012 
00013 #ifndef SERIALIZE_H
00014 #define SERIALIZE_H
00015 
00016 #include <sstream>
00017 
00018 #include "anope.h"
00019 #include "base.h"
00020 
00021 namespace Serialize
00022 {
00023         class Data
00024         {
00025          public:
00026                 enum Type
00027                 {
00028                         DT_TEXT,
00029                         DT_INT
00030                 };
00031 
00032                 virtual ~Data() { }
00033 
00034                 virtual std::iostream& operator[](const Anope::string &key) = 0;
00035                 virtual std::set<Anope::string> KeySet() const { throw CoreException("Not supported"); }
00036                 virtual size_t Hash() const { throw CoreException("Not supported"); }
00037 
00038                 virtual void SetType(const Anope::string &key, Type t) { }
00039                 virtual Type GetType(const Anope::string &key) const { return DT_TEXT; }
00040         };
00041 
00042         extern void RegisterTypes();
00043         extern void CheckTypes();
00044 
00045         class Type;
00046         template<typename T> class Checker;
00047         template<typename T> class Reference;
00048 }
00049 
00054 class CoreExport Serializable : public virtual Base
00055 {
00056  private:
00057         /* A list of every serializable item in Anope.
00058          * Some of these are static and constructed at runtime,
00059          * so this list must be on the heap, as it is not always
00060          * constructed before other objects are if it isn't.
00061          */
00062         static std::list<Serializable *> *SerializableItems;
00063         /* The type of item this object is */
00064         Serialize::Type *s_type;
00065  private:
00066         /* Iterator into serializable_items */
00067         std::list<Serializable *>::iterator s_iter;
00068         /* The hash of the last serialized form of this object commited to the database */
00069         size_t last_commit;
00070         /* The last time this object was commited to the database */
00071         time_t last_commit_time;
00072 
00073  protected:
00074         Serializable(const Anope::string &serialize_type);
00075         Serializable(const Serializable &);
00076 
00077         Serializable &operator=(const Serializable &);
00078 
00079  public:
00080         virtual ~Serializable();
00081 
00082         /* Unique ID (per type, not globally) for this object */
00083         unsigned int id;
00084 
00087         void QueueUpdate();
00088 
00089         bool IsCached(Serialize::Data &);
00090         void UpdateCache(Serialize::Data &);
00091 
00092         bool IsTSCached();
00093         void UpdateTS();
00094 
00098         Serialize::Type* GetSerializableType() const { return this->s_type; }
00099 
00100         virtual void Serialize(Serialize::Data &data) const = 0;
00101 
00102         static const std::list<Serializable *> &GetItems();
00103 };
00104 
00105 /* A serializable type. There should be one of these classes for each type
00106  * of class that inherits from Serialiable. Used for unserializing objects
00107  * of this type, as it requires a function pointer to a static member function.
00108  */
00109 class CoreExport Serialize::Type
00110 {
00111         typedef Serializable* (*unserialize_func)(Serializable *obj, Serialize::Data &);
00112 
00113         static std::vector<Anope::string> TypeOrder;
00114         static std::map<Anope::string, Serialize::Type *> Types;
00115 
00116         /* The name of this type, should be a class name */
00117         Anope::string name;
00118         unserialize_func unserialize;
00119         /* Owner of this type. Used for placing objects of this type in separate databases
00120          * based on what module, if any, owns it.
00121          */
00122         Module *owner;
00123 
00124         /* The timesatmp for this type. All objects of this type are as up to date as
00125          * this timestamp. if curtime == timestamp then we have the most up to date
00126          * version of every object of this type.
00127          */
00128         time_t timestamp;
00129 
00130  public:
00131         /* Map of Serializable::id to Serializable objects */
00132         std::map<unsigned int, Serializable *> objects;
00133 
00139         Type(const Anope::string &n, unserialize_func f, Module *owner = NULL);
00140         ~Type();
00141 
00145         const Anope::string &GetName() { return this->name; }
00146 
00153         Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
00154 
00157         void Check();
00158 
00162         time_t GetTimestamp() const;
00163 
00166         void UpdateTimestamp();
00167 
00168         Module* GetOwner() const { return this->owner; }
00169 
00170         static Serialize::Type *Find(const Anope::string &name);
00171 
00172         static const std::vector<Anope::string> &GetTypeOrder();
00173 
00174         static const std::map<Anope::string, Serialize::Type *>& GetTypes();
00175 };
00176 
00183 template<typename T>
00184 class Serialize::Checker
00185 {
00186         Anope::string name;
00187         T obj;
00188         mutable Serialize::Type *type;
00189 
00190         inline void Check() const
00191         {
00192                 if (!type)
00193                         type = Serialize::Type::Find(this->name);
00194                 if (type)
00195                         type->Check();
00196         }
00197 
00198  public:
00199         Checker(const Anope::string &n) : name(n), type(NULL) { }
00200 
00201         inline const T* operator->() const
00202         {
00203                 this->Check();
00204                 return &this->obj;
00205         }
00206         inline T* operator->()
00207         {
00208                 this->Check();
00209                 return &this->obj;
00210         }
00211 
00212         inline const T& operator*() const
00213         {
00214                 this->Check();
00215                 return this->obj;
00216         }
00217         inline T& operator*()
00218         {
00219                 this->Check();
00220                 return this->obj;
00221         }
00222 
00223         inline operator const T&() const
00224         {
00225                 this->Check();
00226                 return this->obj;
00227         }
00228         inline operator T&()
00229         {
00230                 this->Check();
00231                 return this->obj;
00232         }
00233 };
00234 
00241 template<typename T>
00242 class Serialize::Reference : public ReferenceBase
00243 {
00244  protected:
00245         T *ref;
00246 
00247  public:
00248         Reference() : ref(NULL)
00249         {
00250         }
00251 
00252         Reference(T *obj) : ref(obj)
00253         {
00254                 if (obj)
00255                         obj->AddReference(this);
00256         }
00257 
00258         Reference(const Reference<T> &other) : ReferenceBase(other), ref(other.ref)
00259         {
00260                 if (ref && !invalid)
00261                         this->ref->AddReference(this);
00262         }
00263 
00264         ~Reference()
00265         {
00266                 if (ref && !invalid)
00267                         this->ref->DelReference(this);
00268         }
00269 
00270         inline Reference<T>& operator=(const Reference<T> &other)
00271         {
00272                 if (this != &other)
00273                 {
00274                         if (ref && !invalid)
00275                                 this->ref->DelReference(this);
00276 
00277                         this->ref = other.ref;
00278                         this->invalid = other.invalid;
00279 
00280                         if (ref && !invalid)
00281                                 this->ref->AddReference(this);
00282                 }
00283                 return *this;
00284         }
00285 
00286         inline operator bool() const
00287         {
00288                 if (!this->invalid)
00289                         return this->ref != NULL;
00290                 return false;
00291         }
00292 
00293         inline operator T*() const
00294         {
00295                 if (!this->invalid)
00296                 {
00297                         if (this->ref)
00298                                 // This can invalidate me
00299                                 this->ref->QueueUpdate();
00300                         if (!this->invalid)
00301                                 return this->ref;
00302                 }
00303                 return NULL;
00304         }
00305 
00306         inline T* operator*() const
00307         {
00308                 if (!this->invalid)
00309                 {
00310                         if (this->ref)
00311                                 // This can invalidate me
00312                                 this->ref->QueueUpdate();
00313                         if (!this->invalid)
00314                                 return this->ref;
00315                 }
00316                 return NULL;
00317         }
00318 
00319         inline T* operator->() const
00320         {
00321                 if (!this->invalid)
00322                 {
00323                         if (this->ref)
00324                                 // This can invalidate me
00325                                 this->ref->QueueUpdate();
00326                         if (!this->invalid)
00327                                 return this->ref;
00328                 }
00329                 return NULL;
00330         }
00331 };
00332 
00333 #endif // SERIALIZE_H