1
0
mirror of https://github.com/anope/anope.git synced 2026-06-25 22:26:39 +02:00
Files
anope/include/serialize.h
T
Adam d33a0f75a5 Pretty large coding style cleanup, in source doc
cleanup, and allow protocol mods to depend on each
other
2012-11-22 00:50:33 -05:00

347 lines
7.9 KiB
C++

/*
*
* (C) 2003-2012 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*
* Based on the original code of Epona by Lara.
* Based on the original code of Services by Andy Church.
*
*/
#ifndef SERIALIZE_H
#define SERIALIZE_H
#include <sstream>
#include "anope.h"
#include "base.h"
namespace Serialize
{
enum DataType
{
DT_TEXT,
DT_INT
};
class CoreExport stringstream : public std::stringstream
{
private:
Serialize::DataType type;
unsigned _max;
public:
stringstream();
stringstream(const stringstream &ss);
Anope::string astr() const;
template<typename T> std::istream &operator>>(T &val)
{
std::istringstream is(this->str());
is >> val;
return *this;
}
std::istream &operator>>(Anope::string &val);
bool operator==(const stringstream &other) const;
bool operator!=(const stringstream &other) const;
stringstream &SetType(Serialize::DataType t);
Serialize::DataType GetType() const;
stringstream &SetMax(unsigned m);
unsigned GetMax() const;
};
typedef std::map<Anope::string, stringstream> Data;
extern void RegisterTypes();
class Type;
template<typename T> class Checker;
template<typename T> class Reference;
}
/** A serialziable object. Serializable objects can be serialized into
* a map of stringstreams (Serialize::Data), and then reconstructed or
* updated later at any time.
*/
class CoreExport Serializable : public virtual Base
{
private:
/* A list of every serializable item in Anope.
* Some of these are static and constructed at runtime,
* so this list must be on the heap, as it is not always
* constructed before other objects are if it isn't.
*/
static std::list<Serializable *> *SerializableItems;
/* The type of item this object is */
Serialize::Type *s_type;
private:
/* Iterator into serializable_items */
std::list<Serializable *>::iterator s_iter;
/* The last serialized form of this object commited to the database */
Serialize::Data last_commit;
/* The last time this object was commited to the database */
time_t last_commit_time;
Serializable();
protected:
Serializable(const Anope::string &serialize_type);
Serializable(const Serializable &);
virtual ~Serializable();
Serializable &operator=(const Serializable &);
public:
/* Unique ID (per type, not globally) for this object */
unsigned int id;
/* Destroys this object. This is effectively the same thing as
* delete, however it properly cleans up after this object.
*/
void Destroy();
/** Marks the object as potentially being updated "soon".
*/
void QueueUpdate();
bool IsCached();
void UpdateCache();
bool IsTSCached();
void UpdateTS();
/** Get the type of serializable object this is
* @return The serializable object type
*/
Serialize::Type* GetSerializableType() const;
virtual Serialize::Data Serialize() const = 0;
static const std::list<Serializable *> &GetItems();
};
/* A serializable type. There should be one of these classes for each type
* of class that inherits from Serialiable. Used for unserializing objects
* of this type, as it requires a function pointer to a static member function.
*/
class CoreExport Serialize::Type
{
typedef Serializable* (*unserialize_func)(Serializable *obj, Serialize::Data &);
static std::vector<Anope::string> TypeOrder;
static std::map<Anope::string, Serialize::Type *> Types;
/* The name of this type, should be a class name */
Anope::string name;
unserialize_func unserialize;
/* Owner of this type. Used for placing objects of this type in separate databases
* based on what module, if any, owns it.
*/
Module *owner;
/* The timesatmp for this type. All objects of this type are as up to date as
* this timestamp. if curtime == timestamp then we have the most up to date
* version of every object of this type.
*/
time_t timestamp;
public:
/* Map of Serializable::id to Serializable objects */
std::map<unsigned int, Serializable *> objects;
/** Creates a new serializable type
* @param n Type name
* @param f Func to unserialize objects
* @param owner Owner of this type. Leave NULL for the core.
*/
Type(const Anope::string &n, unserialize_func f, Module *owner = NULL);
~Type();
/** Gets the name for this type
* @return The name, eg "NickAlias"
*/
const Anope::string &GetName();
/** Unserialized an object.
* @param obj NULL if this object doesn't yet exist. If this isn't NULL, instead
* update the contents of this object.
* @param data The data to unserialize
* @return The unserialized object. If obj != NULL this should be obj.
*/
Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
/** Check if this object type has any pending changes and update them.
*/
void Check();
/** Gets the timestamp for the object type. That is, the time we know
* all objects of this type are updated at least to.
*/
time_t GetTimestamp() const;
/** Bumps object type timestamp to current time
*/
void UpdateTimestamp();
Module* GetOwner() const;
static Serialize::Type *Find(const Anope::string &name);
static const std::vector<Anope::string> &GetTypeOrder();
};
/** Should be used to hold lists and other objects of a specific type,
* but not a specific object. Used for ensuring that any access to
* this object type is always up to date. These are usually constructed
* at run time, before main is called, so no types are registered. This
* is why there are static Serialize::Type* variables in every function.
*/
template<typename T>
class Serialize::Checker
{
Anope::string name;
T obj;
public:
Checker(const Anope::string &n) : name(n) { }
inline const T* operator->() const
{
static Serialize::Type *type = Serialize::Type::Find(this->name);
if (type)
type->Check();
return &this->obj;
}
inline T* operator->()
{
static Serialize::Type *type = Serialize::Type::Find(this->name);
if (type)
type->Check();
return &this->obj;
}
inline const T& operator*() const
{
static Serialize::Type *type = Serialize::Type::Find(this->name);
if (type)
type->Check();
return this->obj;
}
inline T& operator*()
{
static Serialize::Type *type = Serialize::Type::Find(this->name);
if (type)
type->Check();
return this->obj;
}
inline operator const T&() const
{
static Serialize::Type *type = Serialize::Type::Find(this->name);
if (type)
type->Check();
return this->obj;
}
inline operator T&()
{
static Serialize::Type *type = Serialize::Type::Find(this->name);
if (type)
type->Check();
return this->obj;
}
};
/** Used to hold references to serializable objects. Reference should always be
* used when holding references to serializable objects for extended periods of time
* to ensure that the object it refers to it always up to date. This also behaves like
* Reference in that it will invalidate itself if the object it refers to is
* destructed.
*/
template<typename T>
class Serialize::Reference : public ReferenceBase
{
protected:
T *ref;
public:
Reference() : ref(NULL)
{
}
Reference(T *obj) : ref(obj)
{
if (obj)
obj->AddReference(this);
}
Reference(const Reference<T> &other) : ref(other.ref)
{
if (*this)
this->ref->AddReference(this);
}
~Reference()
{
if (*this)
this->ref->DelReference(this);
}
inline operator bool() const
{
if (!this->invalid)
return this->ref != NULL;
return false;
}
inline void operator=(T *newref)
{
if (*this)
this->ref->DelReference(this);
this->ref = newref;
this->invalid = false;
if (newref)
this->ref->AddReference(this);
}
inline operator T*() const
{
if (!this->invalid)
{
if (this->ref)
this->ref->QueueUpdate();
return this->ref;
}
return NULL;
}
inline T* operator*() const
{
if (!this->invalid)
{
if (this->ref)
this->ref->QueueUpdate();
return this->ref;
}
return NULL;
}
inline T* operator->() const
{
if (!this->invalid)
{
if (this->ref)
this->ref->QueueUpdate();
return this->ref;
}
return NULL;
}
};
#endif // SERIALIZE_H