khanat-opennel-code/code/ryzom/common/src/game_share/object.h

620 lines
15 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef R2_OBJECT_H
#define R2_OBJECT_H
#include "nel/misc/types_nl.h"
#include "nel/misc/smart_ptr.h"
#include "nel/misc/time_nl.h"
#include "nel/misc/mem_stream.h"
#include <string>
#include <vector>
#include <list>
#include <map>
#include <queue>
namespace R2
{
class CObject;
class CObjectTable;
class CObjectString;
class CObjectRefId;
class CObjectNumber;
class CObjectInteger;
class CSerializeContext;
// vistor triggered at traversal of object tree. see CObject::visit
struct IObjectVisitor
{
virtual ~IObjectVisitor() { }
virtual void visit(CObjectRefId &/* obj */) {}
virtual void visit(CObjectString &/* obj */) {}
virtual void visit(CObjectNumber &/* obj */) {}
virtual void visit(CObjectInteger &/* obj */) {}
virtual void visit(CObjectTable &/* obj */) {}
};
class CObject : public NLMISC::CRefCount
{
public:
typedef NLMISC::CRefPtr<CObject> TRefPtr;
typedef NLMISC::CSmartPtr<CObject> TSmartPtr;
// recursively visit hierarchy of objects
void visit(IObjectVisitor &visitor);
virtual ~CObject();
virtual CObject* clone() const;
void serialize(std::string& out) const;
virtual void doSerialize(std::string& out, CSerializeContext& context) const = 0;
virtual const char *getTypeAsString() const = 0;
CObject* findAttr(const std::string & first) const;
CObject* findAttr(const std::string & first, const std::string & second) const;
CObject* findAttr(const std::string & first, const std::string & second, const std::string & third) const;
CObject* findAttr(const std::vector<std::string>& attrName ) const;
// test type
bool isNumber(const std::string & prop="") const;
bool isInteger(const std::string & prop="") const;
bool isString(const std::string & prop="") const;
bool isTable(const std::string & prop="") const;
bool isRefId(const std::string & prop="") const;
virtual bool insert(const std::string & key, CObject * value, sint32 position = -1);
// to Value
double toNumber(const std::string & prop="") const;
sint64 toInteger(const std::string & prop="") const;
std::string toString(const std::string & prop="") const;
CObjectTable* toTable(const std::string & prop="") const;
virtual sint32 findIndex(const CObject* child) const;
// find index from a key, or -1 if not found
virtual sint32 findIndex(const std::string &key) const;
// as table
virtual CObject* getAttr(const std::string & name) const;
virtual std::string getKey(uint32 pos) const;
virtual CObject* getValueAtPos(uint32 pos) const;
virtual uint32 getSize() const;
virtual CObject* take(sint32 pos);
virtual bool canTake(sint32 pos) const;
// add Value
void add(const std::string & key, CObject* value);
void add(CObject* value);
void add(const std::string& key, const std::string & value);
void add(const std::string& key, double value);
void add(const std::string& key, sint64 value);
// set Value
virtual bool set(const std::string& key, const std::string & value);
virtual bool set(const std::string& key, double value);
virtual bool set(const std::string& key, sint64 value);
virtual bool setObject(const std::string& key, CObject* value);
CObject* getParent() const;
void setParent(CObject* parent);
// tmp for debug
virtual void dump(const std::string prefix = "", uint depth = 0) const = 0;
/** In place copy of object "src" into this object
* Type and fields must match, otherwise error msg are printed
*/
void inPlaceCopy(const CObject &src);
virtual bool equal(const CObject* /* other */) const { return false; }
static std::string uint32ToInstanceId(uint32 id);
static uint32 instanceIdToUint32(const std::string& instanceId);
// set / get the 'ghost' flag, meaning that this objet only exist for the client
bool getGhost() const;
virtual void setGhost(bool ghost);
virtual void checkIntegrity() const {}
/** Find the shortest name for this object as a (instanceId, attrName, position) triplet
* \return false if such a name could not be found
*/
bool getShortestName(std::string &instanceId, std::string &attrName, sint32 &position) const;
bool getNameInParent(std::string &instanceId, std::string &attrName, sint32 &position) const;
protected:
explicit CObject();
virtual bool doIsNumber() const;
virtual bool doIsInteger() const;
virtual bool doIsString() const;
virtual bool doIsTable() const;
virtual bool doIsRefId() const;
virtual double doToNumber() const;
virtual sint64 doToInteger() const;
virtual std::string doToString() const;
virtual CObjectTable* doToTable() const;
public:
virtual void previsit(std::vector<TRefPtr> &sons);
public:
virtual void inPlaceCopyTo(CObject &dest) const = 0;
virtual void inPlaceCopy(const CObjectString &src);
virtual void inPlaceCopy(const CObjectNumber &src);
virtual void inPlaceCopy(const CObjectInteger &src);
virtual void inPlaceCopy(const CObjectTable &src);
protected:
void copyMismatchMsg(const CObject &src);
virtual void visitInternal(IObjectVisitor &visitor) = 0;
private:
CObject* _Parent;
protected:
bool _Ghost;
uint32 _Validation;
};
/*inline std::ostream& operator<<( std::ostream& os, const CObject& c )
{
c.serialize(os);
return os;
}*/
class CObjectString : public CObject
{
public:
explicit CObjectString(const std::string & value);
virtual const char *getTypeAsString() const;
virtual CObject* clone() const;
virtual bool set(const std::string& key, const std::string & value);
virtual bool setObject(const std::string& key, CObject* value);
const std::string &getValue() const { return _Value; }
virtual void dump(const std::string prefix = "", uint depth = 0) const;
virtual bool equal(const CObject* other) const;
protected:
virtual void visitInternal(IObjectVisitor &visitor);
virtual void doSerialize(std::string& out, CSerializeContext& context) const;
virtual std::string doToString() const;
virtual bool doIsString() const;
virtual void inPlaceCopyTo(CObject &dest) const;
virtual void inPlaceCopy(const CObjectString &src);
private:
std::string _Value;
};
// A single string from the server viewpoint
// From client viewpoint, derived class 'observes' a target object and tells when it has been deleted
// or created
class CObjectRefId : public CObjectString
{
public:
explicit CObjectRefId(const std::string & value);
~CObjectRefId();
virtual const char *getTypeAsString() const;
virtual CObject* clone() const;
virtual bool equal(const CObject* other) const;
protected:
virtual void visitInternal(IObjectVisitor &visitor);
virtual bool doIsRefId() const;
virtual void doSerialize(std::string& out, CSerializeContext& context) const;
};
class CObjectNumber : public CObject
{
public:
explicit CObjectNumber(double value);
virtual const char *getTypeAsString() const;
virtual bool set(const std::string& key, double value);
virtual bool set(const std::string& key, const std::string&value);
virtual bool setObject(const std::string& key, CObject* value);
virtual CObject* clone() const;
double getValue() const { return _Value; }
virtual void dump(const std::string prefix = "", uint depth = 0) const;
virtual bool equal(const CObject* other) const;
protected:
virtual void doSerialize(std::string& out, CSerializeContext& context) const;
virtual bool doIsNumber() const;
virtual double doToNumber() const;
virtual std::string doToString() const;
virtual void inPlaceCopyTo(CObject &dest) const;
virtual void inPlaceCopy(const CObjectNumber &src);
virtual void visitInternal(IObjectVisitor &visitor);
private:
double _Value;
};
class CObjectInteger : public CObject
{
public:
explicit CObjectInteger(sint64 value);
virtual const char *getTypeAsString() const;
virtual bool set(const std::string& key, sint64 value);
virtual bool set(const std::string& key, const std::string &value);
virtual bool setObject(const std::string& key, CObject* value);
virtual CObject* clone() const;
sint64 getValue() const { return _Value; }
virtual void dump(const std::string prefix = "", uint depth = 0) const;
virtual bool equal(const CObject* other) const;
protected:
virtual void doSerialize(std::string& out, CSerializeContext& context) const;
virtual bool doIsInteger() const;
virtual sint64 doToInteger() const;
virtual std::string doToString() const;
virtual void inPlaceCopyTo(CObject &dest) const;
virtual void inPlaceCopy(const CObjectInteger &src);
virtual void visitInternal(IObjectVisitor &visitor);
private:
sint64 _Value;
};
class CObjectTable: public CObject
{
public:
typedef NLMISC::CRefPtr<CObjectTable> TRefPtr;
typedef NLMISC::CRefPtr<const CObjectTable> TRefPtrConst;
explicit CObjectTable();
virtual ~CObjectTable();
virtual const char *getTypeAsString() const;
virtual bool insert(const std::string & key, CObject * value, sint32 pos);
virtual CObject* clone() const;
virtual void doSerialize(std::string& out, CSerializeContext& context) const;
virtual CObject* getAttr(const std::string & name) const;
virtual std::string getKey(uint32 pos) const;
virtual CObject* getValueAtPos(uint32 pos) const;
virtual sint32 findIndex(const CObject* child) const;
// find index from a key, or -1 if not found
virtual sint32 findIndex(const std::string &key) const;
virtual uint32 getSize() const;
virtual bool set(const std::string& key, const std::string & value);
virtual bool set(const std::string& key, double value);
virtual bool setObject(const std::string& key, CObject* value);
virtual CObject* take(sint32 pos);
virtual bool canTake(sint32 pos) const;
void clear();
void sort();
virtual void dump(const std::string prefix = "", uint depth = 0) const;
virtual bool equal(const CObject* other) const;
virtual void setGhost(bool ghost);
virtual void checkIntegrity() const;
protected:
virtual void visitInternal(IObjectVisitor &visitor);
virtual bool doIsTable() const;
virtual CObjectTable* doToTable() const;
virtual void inPlaceCopyTo(CObject &dest) const;
virtual void inPlaceCopy(const CObjectTable &src);
virtual void previsit(std::vector<CObject::TRefPtr> &sons);
/** Compute absolute position, return true if index is valid
* A negative index indicate an offset from the end of the table (-1 for the last element)
*/
protected:
typedef std::vector< std::pair<std::string, CObject*> > TContainer;
protected:
TContainer _Value;
};
class CTypedObject : public CObjectTable
{
public:
CTypedObject(const std::string & type);
virtual bool isOk() const;
};
class CNameGiver
{
public:
CNameGiver();
sint32 getNewId(const std::string& type="") ;
std::string getNewName(const std::string& type="", sint32 id = -1);
void setMaxId(const std::string& eid,sint32 id);
sint32 getMaxId(const std::string& eid);
void clear();
private:
std::map< std::string, sint32> _Value;
};
class CObjectGenerator;
// NB nico : added 'virtual' because client derives its own factory
class CObjectFactory
{
public:
CObjectFactory(const std::string & prefix);
void registerGenerator(CObject* classObject);
virtual ~CObjectFactory();
virtual CObject* newBasic(const std::string & type);
CObject* newAvanced(const std::string & type);
CObject* newComponent(const std::string & type);
CObjectGenerator* getGenerator(const std::string & type);
std::string getNewName(const std::string& type="") const;
void setMaxId(const std::string& eid,sint32 id);
void setPrefix(const std::string & prefix);
sint32 getMaxId(const std::string& eid) const;
void clear();
private:
CNameGiver* _NameGiver;
std::string _Prefix;
std::map<std::string, CObjectGenerator*> _Map;
};
class CObjectGenerator
{
public:
CObject* instanciate(CObjectFactory* factory) const;
CObjectGenerator(CObject* objectClass, CObjectFactory* factory):
_ObjectClass(objectClass){ createDefaultValues(factory);}
~CObjectGenerator();
CObject* getDefaultValue(const std::string & propName) const;
std::string getBaseClass() const;
protected:
void createDefaultValues(CObjectFactory* factory);
private:
typedef std::map<std::string, CObject* > TDefaultValues;
private:
CObject* _ObjectClass;
TDefaultValues _DefaultValues;
};
class CClass : public CObjectTable
{
public:
CClass(const std::string & classType);
void addAttribute(const std::string & name, const std::string & type);
void addAttribute(const std::string & name, const std::string & type, const std::string & defaultValue);
private:
std::string _ClassType;
};
class CClassAttribute: public CObjectTable
{
public:
CClassAttribute(const std::string & propName, const std::string& propType)
{
add("Name", propName);
add("Type", propType);
}
CClassAttribute(const std::string & propName, const std::string& propType, const std::string & defaultValue)
{
add("Name", propName);
add("Type", propType);
add("DefaultValue", defaultValue);
}
//virtual CObject* instanciate() const = 0;
virtual bool verify(CObject* /* prop */) const { return true;}
};
// Don't take ownership
class CObjectSerializer
{
public:
// for client : factory to use when reading objects
CObjectFactory *Factory;
// to force static serializer memory cleanup
static void releaseInstance();
protected:
CObjectSerializer(CObjectFactory *factory, CObject* data = 0);
public:
void serial(NLMISC::IStream& stream);
CObject* getData() const;
// make a copy of data (the caller must handle data)
void setData(CObject* data);
// :XXX: don't delete _Data
~CObjectSerializer();
static void serialStringInstanceId( NLMISC::IStream& stream, std::string& data);
bool isCompresed() const { return _Compressed;}
void compress();
void uncompress() const;
void swap(CObjectSerializer& other);
void setVersion(uint32 version) { _Version = version; }
uint32 getVersion() const { return _Version; }
private:
CObjectSerializer(const CObjectSerializer& lh);
CObjectSerializer& operator=(const CObjectSerializer& rh);
void uncompressImpl();
private:
CObject* _Data;
bool _Compressed;
bool _MustUncompress;
uint8* _CompressedBuffer;
uint32 _CompressedLen;
uint32 _UncompressedLen;
uint32 _Version;
public:
uint32 Level;
bool Log;
};
class CObjectSerializerClient : public CObjectSerializer
{
static CObjectFactory *_ClientObjecFactory;
public:
// constructor for client side serializer, we use the client side factory
CObjectSerializerClient(CObject *data=0)
: CObjectSerializer(_ClientObjecFactory, data)
{
nlassert(_ClientObjecFactory != NULL);
}
static void setClientObjectFactory(CObjectFactory *factory)
{
_ClientObjecFactory = factory;
}
};
class CObjectSerializerServer: public CObjectSerializer
{
public:
// constructor for server side serializer, we don't use object factory
CObjectSerializerServer(CObject *data=0)
: CObjectSerializer(NULL, data)
{}
};
} // namespace R2
#endif //R2_OBJECT_H