More work on new serializer code.

This commit is contained in:
JoelKatz
2012-09-25 22:47:59 -07:00
parent 8a5a9e0925
commit e0587a44b8
6 changed files with 134 additions and 38 deletions

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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) { ; }

View File

@@ -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;

View File

@@ -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; }