mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
More work on new serializer code.
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include <map>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
|
||||
SField sfInvalid(-1), sfGeneric(0);
|
||||
@@ -19,13 +20,46 @@ static boost::mutex SField::mapMutex;
|
||||
|
||||
SField::ref SField::getField(int code);
|
||||
{
|
||||
int type = code >> 16;
|
||||
int field = code % 0xffff;
|
||||
|
||||
if ((type <= 0) || (type >= 256) || (field <= 0) || (field >= 256
|
||||
return sfInvalid;
|
||||
|
||||
boost::mutex::scoped_lock sl(mapMutex);
|
||||
|
||||
std::map<int, SField*> it = unknownFieldMap.Find(code);
|
||||
if (it != codeToField.end())
|
||||
return *(it->second);
|
||||
|
||||
return *(new SField(code, static_cast<SerializedTypeID>(code>>16), code&0xffff, NULL));
|
||||
switch(type)
|
||||
{ // types we are willing to dynamically extend
|
||||
|
||||
#define FIELD(name, type, index)
|
||||
#define TYPE(name, type, index) case sf##name:
|
||||
#include "SerializeProto.h"
|
||||
#undef FIELD
|
||||
#undef TYPE
|
||||
|
||||
break;
|
||||
default:
|
||||
return sfInvalid;
|
||||
}
|
||||
|
||||
return *(new SField(code, static_cast<SerializedTypeID>(type), field, NULL));
|
||||
}
|
||||
|
||||
SField::ref SField::getField(int type, int value)
|
||||
{
|
||||
return getField(FIELD_CODE(type, value));
|
||||
}
|
||||
|
||||
std::string SField::getName() cosnt
|
||||
{
|
||||
if (fieldName != NULL)
|
||||
return fieldName;
|
||||
if (fieldValue == 0)
|
||||
return "";
|
||||
return boost::lexical_cast<std::string>(static_cast<int>(fieldType)) + "/" +
|
||||
boost::lexical_cast<std::string>(fieldValue);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef __FIELDNAMES__
|
||||
#define __FIELDNAMES__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#define FIELD_CODE(type, index) ((static_cast<int>(type) << 16) | index)
|
||||
@@ -55,11 +57,18 @@ public:
|
||||
SField(int fc) : fieldCode(fc), fieldType(STI_UNKNOWN), fieldValue(0), fieldName(NULL) { ; }
|
||||
|
||||
static SField::ref getField(int fieldCode);
|
||||
static SField::ref getField(int fieldType, int fieldValue);
|
||||
static SField::ref getField(SerializedTypeID type, int value) { return getField(FIELD_CODE(type, value)); }
|
||||
|
||||
std::string getName() const;
|
||||
bool hasName() const { return (fieldName != NULL) || (fieldValue != 0); }
|
||||
|
||||
bool isGeneric() const { return fieldCode == 0; }
|
||||
bool isInvalid() const { return fieldCode == -1; }
|
||||
bool isKnown() const { return fieldType != STI_UNKNOWN; }
|
||||
|
||||
bool operator==(const SField& f) const { return fieldCode == f.fieldCode; }
|
||||
bool operator!=(const SField& f) const { return fieldCode != f.fieldCode; }
|
||||
};
|
||||
|
||||
extern SField sfInvalid, sfGeneric;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
std::auto_ptr<SerializedType> STObject::makeDefaultObject(SerializedTypeID id, SField::ref name)
|
||||
{
|
||||
assert((id == STI_NOTPRESENT) || (id == name.fieldType));
|
||||
|
||||
switch(id)
|
||||
{
|
||||
case STI_NOTPRESENT:
|
||||
@@ -48,6 +50,12 @@ std::auto_ptr<SerializedType> STObject::makeDefaultObject(SerializedTypeID id, S
|
||||
case STI_PATHSET:
|
||||
return std::auto_ptr<SerializedType>(new STPathSet(name));
|
||||
|
||||
case STI_OBJECT:
|
||||
return std::auto_ptr<SerializedType>(new STObject(name));
|
||||
|
||||
case STI_ARRAY:
|
||||
return std::auto_ptr<SerializedType>(new STArray(name));
|
||||
|
||||
default:
|
||||
throw std::runtime_error("Unknown object type");
|
||||
}
|
||||
@@ -105,7 +113,7 @@ std::auto_ptr<SerializedType> STObject::makeDeserializedObject(SerializedTypeID
|
||||
}
|
||||
}
|
||||
|
||||
void STObject::set(const SOElement* elem)
|
||||
void STObject::set(SOElement::ptr elem)
|
||||
{
|
||||
mData.empty();
|
||||
mType.empty();
|
||||
@@ -114,39 +122,70 @@ void STObject::set(const SOElement* elem)
|
||||
{
|
||||
mType.push_back(elem);
|
||||
if (elem->flags == SOE_OPTIONAL)
|
||||
giveObject(makeDefaultObject(STI_NOTPRESENT, elem));
|
||||
giveObject(makeDefaultObject(STI_NOTPRESENT, elem->e_field));
|
||||
else
|
||||
giveObject(makeDefaultObject(elem->e_field, elem));
|
||||
giveObject(makeDefaultObject(elem->e_field.fieldType, elem->e_field));
|
||||
++elem;
|
||||
}
|
||||
}
|
||||
|
||||
STObject::STObject(const SOElement* elem, SField::ref name) : SerializedType(name)
|
||||
{
|
||||
set(elem);
|
||||
}
|
||||
|
||||
void STObject::set(SField::ref name, SerializerIterator& sit, int depth = 0)
|
||||
void STObject::setType(SOElement::ptrList t)
|
||||
{
|
||||
mData.empty();
|
||||
mType.empty();
|
||||
|
||||
fName = name;
|
||||
|
||||
while(1)
|
||||
{
|
||||
int type, field.
|
||||
sit.getFieldID(type, field);
|
||||
if ((type == STI_ARRAY) && (field == 1))
|
||||
return;
|
||||
SField::ref fn = SField::getField(type, field);
|
||||
giveObject(makeDeserializedObject(static_cast<SerializedTypeID> type, fn, sit, depth + 1);
|
||||
}
|
||||
while (t->flags != SOE_END)
|
||||
mType.push_back(t++);
|
||||
}
|
||||
|
||||
STObject::STObject(const SOElement* elem, SerializerIterator& sit, SField::refname) : SerializedType(name)
|
||||
bool STObject::isValidForType()
|
||||
{
|
||||
set(elem, sit);
|
||||
BOOST_FOREACH(SOElement::ptr elem, mType)
|
||||
{ // are any required elemnents missing
|
||||
if ((elem->flags == SOE_REQUIRED) && (getPField(elem->e_field) == NULL))
|
||||
{
|
||||
Log(lsWARNING) << getName() << " missing required element " << elem->e_field.fieldName;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const SerializedType& elem, mData)
|
||||
{ // are any non-permitted elements present
|
||||
if (!isFieldAllowed(elem.getFName()))
|
||||
{
|
||||
Log(lsWARNING) << getName() << " has non-permitted element " << elem.getName();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool STObject::isFieldAllowed(SField::ref field)
|
||||
{
|
||||
BOOST_FOREACH(SOElement::ptr elem, mType)
|
||||
{ // are any required elemnents missing
|
||||
if (elem->e_field == field)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool STObject::set(SOElement::ptrList elem, SerializerIterator& sit, int depth)
|
||||
{ // return true = terminated with end-of-object
|
||||
setType(elem);
|
||||
|
||||
mData.empty();
|
||||
while (!sit.empty())
|
||||
{
|
||||
int type, field;
|
||||
sit.getFieldID(type, field);
|
||||
if ((type == STI_OBJECT) && (field == 1)) // end of object indicator
|
||||
return true;
|
||||
SField::ref fn = SField::getField(type, field);
|
||||
if (fn.isInvalid())
|
||||
throw std::runtime_error("Unknown field");
|
||||
giveObject(makeDeserializedObject(fn.fieldType, fn, sit, depth + 1));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string STObject::getFullText() const
|
||||
|
||||
@@ -11,34 +11,48 @@
|
||||
|
||||
// Serializable object/array types
|
||||
|
||||
struct SOElement
|
||||
class SOElement
|
||||
{ // An element in the description of a serialized object
|
||||
public:
|
||||
typedef SOElement const * ptr; // used to point to one element
|
||||
typedef SOElement const * ptrList; // used to point to a terminated list of elements
|
||||
|
||||
SField::ref e_field;
|
||||
SOE_Flags flags;
|
||||
const SOE_Flags flags;
|
||||
};
|
||||
|
||||
class STObject : public SerializedType
|
||||
{
|
||||
protected:
|
||||
boost::ptr_vector<SerializedType> mData;
|
||||
std::vector<const SOElement*> mType;
|
||||
std::vector<SOElement::ptr> mType;
|
||||
|
||||
STObject* duplicate() const { return new STObject(*this); }
|
||||
static STObject* construct(SerializerIterator&, SField::ref);
|
||||
|
||||
public:
|
||||
STObject(SField *n = NULL) : SerializedType(n) { ; }
|
||||
STObject(const SOElement *t, SField *n = NULL);
|
||||
STObject(const SOElement *t, SerializerIterator& u, SField *n = NULL);
|
||||
STObject() { ; }
|
||||
|
||||
STObject(SField::ref name) : SerializedType(name) { ; }
|
||||
|
||||
STObject(SOElement::ptrList type, SField::ref name) : SerializedType(name)
|
||||
{ set(type); }
|
||||
|
||||
STObject(SOElement::ptrList type, SerializerIterator& sit, SField::ref name) : SerializedType(name)
|
||||
{ set(type, sit); }
|
||||
|
||||
virtual ~STObject() { ; }
|
||||
|
||||
static std::auto_ptr<SerializedType> deserialize(SerializerIterator& sit, SField::ref name)
|
||||
{ return std::auto_ptr<SerializedType>(construct(sit, name)); }
|
||||
|
||||
void set(const SOElement* t);
|
||||
void set(const SOElement* t, SerializerIterator& u, int depth = 0);
|
||||
void setType(SOElement const * t);
|
||||
bool isValidForType();
|
||||
bool isFieldAllowed(SField::ref);
|
||||
|
||||
void set(SOElement::ptrList);
|
||||
bool set(SOElement::ptrList, SerializerIterator& u, int depth = 0);
|
||||
|
||||
int getLength() const;
|
||||
virtual SerializedTypeID getSType() const { return STI_OBJECT; }
|
||||
virtual bool isEquivalent(const SerializedType& t) const;
|
||||
|
||||
@@ -111,8 +125,8 @@ public:
|
||||
SerializedType* makeFieldPresent(SField::ref field);
|
||||
void makeFieldAbsent(SField::ref field);
|
||||
|
||||
static std::auto_ptr<SerializedType> makeDefaultObject(SerializedTypeID id, SField *name);
|
||||
static std::auto_ptr<SerializedType> makeDeserializedObject(SerializedTypeID id, SField *name,
|
||||
static std::auto_ptr<SerializedType> makeDefaultObject(SerializedTypeID id, SField::ref name);
|
||||
static std::auto_ptr<SerializedType> makeDeserializedObject(SerializedTypeID id, SField::ref name,
|
||||
SerializerIterator&, int depth);
|
||||
|
||||
static void unitTest();
|
||||
@@ -138,6 +152,7 @@ protected:
|
||||
public:
|
||||
|
||||
STArray() { ; }
|
||||
STArray(SField::ref f) : SerializedType(f) { ; }
|
||||
STArray(SField::ref f, const vector& v) : SerializedType(f), value(v) { ; }
|
||||
STArray(vector& v) : value(v) { ; }
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ public:
|
||||
SerializedTransaction(TransactionType type);
|
||||
|
||||
// STObject functions
|
||||
int getLength() const;
|
||||
SerializedTypeID getSType() const { return STI_TRANSACTION; }
|
||||
std::string getFullText() const;
|
||||
std::string getText() const;
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
{ return std::auto_ptr<SerializedType>(new SerializedType(name)); }
|
||||
|
||||
void setFName(SField::ref n) { fName = &n; assert(fName); }
|
||||
SField::ref getFName() { return *fName; }
|
||||
SField::ref getFName() const { return *fName; }
|
||||
const char *getName() const { return fName->fieldName; }
|
||||
|
||||
virtual SerializedTypeID getSType() const { return STI_NOTPRESENT; }
|
||||
|
||||
Reference in New Issue
Block a user