#include "MongoSerializer.hpp"
namespace sprawl
{
namespace serialization
{
void MongoSerializerBase::Reset()
{
if(IsSaving())
{
this->m_bIsValid = true;
for(auto arraybuilder : m_arrayBuilders)
{
delete arraybuilder.second;
}
m_arrayBuilders.clear();
for(auto objbuilder : m_objectBuilders)
{
delete objbuilder.second;
}
m_objectBuilders.clear();
delete m_builder;
m_builder = new mongo::BSONObjBuilder();
}
else
{
m_arrays.clear();
m_objects.clear();
}
}
void MongoSerializerBase::EnsureVersion()
{
if(m_bWithMetadata)
{
//This shouldn't happen unless someone's being dumb.
//And even if they're being dumb, it shouldn't matter unless they're being extra dumb.
//...but some people are extra dumb.
if(m_builder->hasField("DataVersion"))
{
mongo::BSONObj obj = m_builder->obj();
obj = obj.removeField("DataVersion");
delete m_builder;
m_builder = new mongo::BSONObjBuilder();
m_builder->appendElements(obj);
}
m_builder->append("DataVersion", m_version);
}
}
SerializerBase& MongoSerializerBase::operator%(BinaryData&& var)
{
if(!var.PersistToDB || m_disableDepth)
{
return *this;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return *this;
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
mongo::BSONObjBuilder builder;
builder.appendBinData("binaryData", var.size, mongo::BinDataGeneral, var.val);
m_arrayBuilders.back().second->append(builder.obj());
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(var.name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", var.name.c_str());
}
m_objectBuilders.back().second->appendBinData(var.name.c_str(), var.size, mongo::BinDataGeneral, var.val);
}
else
{
if(m_builder->hasField(var.name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", var.name.c_str());
}
m_builder->appendBinData(var.name.c_str(), var.size, mongo::BinDataGeneral, var.val);
}
}
else
{
const char* str;
int size = 0;
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
str = m_arrays.back().second.front().Obj()["binaryData"].binData(size);
m_arrays.back().second.pop_front();
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
str = m_objects.back()[var.name.c_str()].binData(size);
}
else
{
str = m_obj[var.name.c_str()].binData(size);
}
if(var.size != (uint32_t)size)
{
m_bError = true;
return *this;
}
memcpy(var.val, str, size);
}
return *this;
}
uint32_t MongoSerializerBase::StartObject(String const& str, bool PersistToDB)
{
if(m_disableDepth || !PersistToDB)
{
m_disableDepth++;
return 0;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return 0;
}
if(IsSaving())
{
//Array fields don't care about name.
if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(str.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", str.c_str());
}
}
else if(m_arrayBuilders.empty() || m_stateTracker.empty() || m_stateTracker.back() != State::Array)
{
if(m_builder->hasField(str.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", str.c_str());
}
}
m_objectBuilders.push_back(std::make_pair(str, new mongo::BSONObjBuilder()));
m_stateTracker.push_back(State::Object);
return 0; //doesn't matter.
}
else
{
if(!m_arrays.empty() && !m_stateTracker.empty() && m_stateTracker.back() == State::Array && m_arrays.back().first == str)
{
mongo::BSONObj o = m_arrays.back().second.front().Obj();
m_arrays.back().second.pop_front();
m_objects.push_back(o);
}
else if(!m_objects.empty() && !m_stateTracker.empty() && m_stateTracker.back() == State::Object)
{
mongo::BSONObj o = m_objects.back();
m_objects.push_back(o[str.c_str()].Obj());
}
else
{
m_objects.push_back(m_obj[str.c_str()].Obj());
}
m_stateTracker.push_back(State::Object);
std::list<mongo::BSONElement> elements;
m_objects.back().elems(elements);
m_elementList.push_back(elements);
return m_objects.back().nFields();
}
}
void MongoSerializerBase::EndObject()
{
if(m_disableDepth)
{
m_disableDepth--;
return;
}
m_stateTracker.pop_back();
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
if(IsSaving())
{
sprawl::String key = m_objectBuilders.back().first;
mongo::BSONObj o = m_objectBuilders.back().second->obj();
delete m_objectBuilders.back().second;
m_objectBuilders.pop_back();
if(!m_arrayBuilders.empty() && !m_stateTracker.empty() && m_stateTracker.back() == State::Array)
{
m_arrayBuilders.back().second->append(o);
}
else if(!m_objectBuilders.empty() && !m_stateTracker.empty() && m_stateTracker.back() == State::Object)
{
m_objectBuilders.back().second->append(key.c_str(), o);
}
else
{
m_builder->append(key.c_str(), o);
}
}
else
{
m_objects.pop_back();
m_elementList.pop_back();
}
}
void MongoSerializerBase::StartArray(String const& str, uint32_t& size, bool PersistToDB)
{
if(m_disableDepth || !PersistToDB)
{
m_disableDepth++;
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
if(IsSaving())
{
//Array fields don't care about name.
if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(str.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", str.c_str());
}
}
else if(m_arrayBuilders.empty() || m_stateTracker.empty() || m_stateTracker.back() != State::Array)
{
if(m_builder->hasField(str.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", str.c_str());
}
}
m_arrayBuilders.push_back(std::make_pair(str, new mongo::BSONArrayBuilder()));
}
else
{
if(!m_arrays.empty() && !m_stateTracker.empty() && m_stateTracker.back() == State::Array && m_arrays.back().first == str)
{
std::vector<mongo::BSONElement> elements = m_arrays.back().second.front().Array();
m_arrays.back().second.pop_front();
m_arrays.push_back(std::make_pair(str, std::deque<mongo::BSONElement>(elements.begin(), elements.end())));
size = elements.size();
}
else if(!m_objects.empty() && !m_stateTracker.empty() && m_stateTracker.back() == State::Object)
{
mongo::BSONObj o = m_objects.back();
std::vector<mongo::BSONElement> elements = o[str.c_str()].Array();
m_arrays.push_back(std::make_pair(str, std::deque<mongo::BSONElement>(elements.begin(), elements.end())));
size = elements.size();
}
else
{
std::vector<mongo::BSONElement> elements = m_obj[str.c_str()].Array();
m_arrays.push_back(std::make_pair(str, std::deque<mongo::BSONElement>(elements.begin(), elements.end())));
size = elements.size();
}
}
m_stateTracker.push_back(State::Array);
}
void MongoSerializerBase::EndArray()
{
if(m_disableDepth)
{
m_disableDepth--;
return;
}
m_stateTracker.pop_back();
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
if(IsSaving())
{
sprawl::String key = m_arrayBuilders.back().first;
mongo::BSONArray arr = m_arrayBuilders.back().second->arr();
delete m_arrayBuilders.back().second;
m_arrayBuilders.pop_back();
if(!m_arrayBuilders.empty() && !m_stateTracker.empty() && m_stateTracker.back() == State::Array)
{
m_arrayBuilders.back().second->append(arr);
}
else if(!m_objectBuilders.empty() && !m_stateTracker.empty() && m_stateTracker.back() == State::Object)
{
m_objectBuilders.back().second->append(key.c_str(), arr);
}
else
{
m_builder->append(key.c_str(), arr);
}
}
else
{
m_arrays.pop_back();
}
}
String MongoSerializerBase::GetNextKey()
{
if(IsSaving())
{
return "";
}
if(!m_stateTracker.empty())
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
return "";
}
}
/*else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
return m_objects.back().firstElementFieldName();
}
else
{
m_bError = true;
return;
}
}
else
{
if(m_obj.nFields() == 0)
{
m_bError = true;
return;
}
return m_obj.firstElementFieldName();
}*/
if(!m_elementList.empty())
{
sprawl::String ret(m_elementList.back().front().fieldName());
m_elementList.back().pop_front();
return ret;
}
return "";
}
MongoSerializerBase::~MongoSerializerBase()
{
for(auto arraybuilder : m_arrayBuilders)
{
delete arraybuilder.second;
}
m_arrayBuilders.clear();
for(auto objbuilder : m_objectBuilders)
{
delete objbuilder.second;
}
delete m_builder;
}
void MongoSerializerBase::serialize(String* var, const uint32_t, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
m_arrayBuilders.back().second->append(var->toStdString());
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), var->toStdString());
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), var->toStdString());
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
*var = m_arrays.back().second.front().String();
m_arrays.back().second.pop_front();
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = m_objects.back()[name.c_str()].String();
}
else
{
*var = m_obj[name.c_str()].String();
}
}
}
void MongoSerializerBase::serialize(std::string* var, const uint32_t, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
m_arrayBuilders.back().second->append(*var);
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
*var = m_arrays.back().second.front().String();
m_arrays.back().second.pop_front();
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = m_objects.back()[name.c_str()].String();
}
else
{
*var = m_obj[name.c_str()].String();
}
}
}
void MongoSerializerBase::serialize(unsigned char* var, const uint32_t, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
m_arrayBuilders.back().second->append(*var);
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
std::string str;
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
str = m_arrays.back().second.front().String();
m_arrays.back().second.pop_front();
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
str = m_objects.back()[name.c_str()].String();
}
else
{
str = m_obj[name.c_str()].String();
}
strcpy((char*)var, str.c_str());
}
}
void MongoSerializerBase::serialize(unsigned short* var, const uint32_t bytes, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
bool bIsArray = false;
uint32_t size = 0;
if(bytes != sizeof(unsigned short int))
{
size = bytes/sizeof(unsigned short int);
bIsArray = true;
StartArray(name, size, PersistToDB);
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
m_arrayBuilders.back().second->append(var[i]);
}
}
else
{
m_arrayBuilders.back().second->append(*var);
}
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
var[i] = (unsigned short)m_arrays.back().second.front().Int();
m_arrays.back().second.pop_front();
}
}
else
{
*var = (unsigned short)m_arrays.back().second.front().Int();
m_arrays.back().second.pop_front();
}
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = (unsigned short)m_objects.back()[name.c_str()].Int();
}
else
{
*var = (unsigned short)m_obj[name.c_str()].Int();
}
}
if(bIsArray)
{
EndArray();
}
}
void MongoSerializerBase::serialize(unsigned long long* var, const uint32_t bytes, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
bool bIsArray = false;
uint32_t size = 0;
if(bytes != sizeof(unsigned long long int))
{
size = bytes/sizeof(unsigned long long int);
bIsArray = true;
StartArray(name, size, PersistToDB);
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
m_arrayBuilders.back().second->append((long long int)var[i]);
}
}
else
{
m_arrayBuilders.back().second->append((long long int)*var);
}
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), (long long int)*var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), (long long int)*var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
var[i] = m_arrays.back().second.front().Long();
m_arrays.back().second.pop_front();
}
}
else
{
*var = m_arrays.back().second.front().Long();
m_arrays.back().second.pop_front();
}
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = m_objects.back()[name.c_str()].Long();
}
else
{
*var = m_obj[name.c_str()].Long();
}
}
if(bIsArray)
{
EndArray();
}
}
void MongoSerializerBase::serialize(unsigned long* var, const uint32_t bytes, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
bool bIsArray = false;
uint32_t size = 0;
if(bytes != sizeof(unsigned long int))
{
size = bytes/sizeof(unsigned long int);
bIsArray = true;
StartArray(name, size, PersistToDB);
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
m_arrayBuilders.back().second->append((long long int)var[i]);
}
}
else
{
m_arrayBuilders.back().second->append((long long int)*var);
}
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), (long long int)*var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), (long long int)*var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
var[i] = (unsigned long)m_arrays.back().second.front().Long();
m_arrays.back().second.pop_front();
}
}
else
{
*var = (unsigned long)m_arrays.back().second.front().Long();
m_arrays.back().second.pop_front();
}
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = (unsigned long)m_objects.back()[name.c_str()].Long();
}
else
{
*var = (unsigned long)m_obj[name.c_str()].Long();
}
}
if(bIsArray)
{
EndArray();
}
}
void MongoSerializerBase::serialize(unsigned int* var, const uint32_t bytes, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
bool bIsArray = false;
uint32_t size = 0;
if(bytes != sizeof(unsigned int))
{
size = bytes/sizeof(unsigned int);
bIsArray = true;
StartArray(name, size, PersistToDB);
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
m_arrayBuilders.back().second->append(var[i]);
}
}
else
{
m_arrayBuilders.back().second->append(*var);
}
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
var[i] = m_arrays.back().second.front().Int();
m_arrays.back().second.pop_front();
}
}
else
{
*var = m_arrays.back().second.front().Int();
m_arrays.back().second.pop_front();
}
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = m_objects.back()[name.c_str()].Int();
}
else
{
*var = m_obj[name.c_str()].Int();
}
}
if(bIsArray)
{
EndArray();
}
}
void MongoSerializerBase::serialize(bool* var, const uint32_t bytes, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
bool bIsArray = false;
uint32_t size = 0;
if(bytes != sizeof(bool))
{
size = bytes/sizeof(bool);
bIsArray = true;
StartArray(name, size, PersistToDB);
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
m_arrayBuilders.back().second->append(var[i]);
}
}
else
{
m_arrayBuilders.back().second->append(*var);
}
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
var[i] = m_arrays.back().second.front().Bool();
m_arrays.back().second.pop_front();
}
}
else
{
*var = m_arrays.back().second.front().Bool();
m_arrays.back().second.pop_front();
}
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = m_objects.back()[name.c_str()].Bool();
}
else
{
*var = m_obj[name.c_str()].Bool();
}
}
if(bIsArray)
{
EndArray();
}
}
void MongoSerializerBase::serialize(double* var, const uint32_t bytes, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
bool bIsArray = false;
uint32_t size = 0;
if(bytes != sizeof(double))
{
size = bytes/sizeof(double);
bIsArray = true;
StartArray(name, size, PersistToDB);
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
m_arrayBuilders.back().second->append(var[i]);
}
}
else
{
m_arrayBuilders.back().second->append(*var);
}
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
var[i] = m_arrays.back().second.front().Double();
m_arrays.back().second.pop_front();
}
}
else
{
*var = m_arrays.back().second.front().Double();
m_arrays.back().second.pop_front();
}
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = m_objects.back()[name.c_str()].Double();
}
else
{
*var = m_obj[name.c_str()].Double();
}
}
if(bIsArray)
{
EndArray();
}
}
void MongoSerializerBase::serialize(float* var, const uint32_t bytes, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
bool bIsArray = false;
uint32_t size = 0;
if(bytes != sizeof(float))
{
size = bytes/sizeof(float);
bIsArray = true;
StartArray(name, size, PersistToDB);
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
m_arrayBuilders.back().second->append(var[i]);
}
}
else
{
m_arrayBuilders.back().second->append(*var);
}
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
var[i] = (float)m_arrays.back().second.front().Double();
m_arrays.back().second.pop_front();
}
}
else
{
*var = (float)m_arrays.back().second.front().Double();
m_arrays.back().second.pop_front();
}
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = (float)m_objects.back()[name.c_str()].Double();
}
else
{
*var = (float)m_obj[name.c_str()].Double();
}
}
if(bIsArray)
{
EndArray();
}
}
void MongoSerializerBase::serialize(char* var, const uint32_t, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
m_arrayBuilders.back().second->append(*var);
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
std::string str;
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
str = m_arrays.back().second.front().String();
m_arrays.back().second.pop_front();
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
str = m_objects.back()[name.c_str()].String();
}
else
{
str = m_obj[name.c_str()].String();
}
strcpy(var, str.c_str());
}
}
void MongoSerializerBase::serialize(short* var, const uint32_t bytes, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
bool bIsArray = false;
uint32_t size = 0;
if(bytes != sizeof(short int))
{
size = bytes/sizeof(short int);
bIsArray = true;
StartArray(name, size, PersistToDB);
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
m_arrayBuilders.back().second->append(var[i]);
}
}
else
{
m_arrayBuilders.back().second->append(*var);
}
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
var[i] = (short)m_arrays.back().second.front().Int();
m_arrays.back().second.pop_front();
}
}
else
{
*var = (short)m_arrays.back().second.front().Int();
m_arrays.back().second.pop_front();
}
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = (short)m_objects.back()[name.c_str()].Int();
}
else
{
*var = (short)m_obj[name.c_str()].Int();
}
}
if(bIsArray)
{
EndArray();
}
}
void MongoSerializerBase::serialize(long long* var, const uint32_t bytes, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
bool bIsArray = false;
uint32_t size = 0;
if(bytes != sizeof(long long int))
{
size = bytes/sizeof(long long int);
bIsArray = true;
StartArray(name, size, PersistToDB);
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
m_arrayBuilders.back().second->append(var[i]);
}
}
else
{
m_arrayBuilders.back().second->append(*var);
}
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
var[i] = m_arrays.back().second.front().Long();
m_arrays.back().second.pop_front();
}
}
else
{
*var = m_arrays.back().second.front().Long();
m_arrays.back().second.pop_front();
}
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = m_objects.back()[name.c_str()].Long();
}
else
{
*var = m_obj[name.c_str()].Long();
}
}
if(bIsArray)
{
EndArray();
}
}
void MongoSerializerBase::serialize(long* var, const uint32_t bytes, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
bool bIsArray = false;
uint32_t size = 0;
if(bytes != sizeof(long int))
{
size = bytes/sizeof(long int);
bIsArray = true;
StartArray(name, size, PersistToDB);
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
m_arrayBuilders.back().second->append((long long int)var[i]);
}
}
else
{
m_arrayBuilders.back().second->append((long long int)*var);
}
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), (long long int)*var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), (long long int)*var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
var[i] = (long)m_arrays.back().second.front().Long();
m_arrays.back().second.pop_front();
}
}
else
{
*var = (long)m_arrays.back().second.front().Long();
m_arrays.back().second.pop_front();
}
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = (long)m_objects.back()[name.c_str()].Long();
}
else
{
*var = (long)m_obj[name.c_str()].Long();
}
}
if(bIsArray)
{
EndArray();
}
}
void MongoSerializerBase::serialize(int* var, const uint32_t bytes, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
bool bIsArray = false;
uint32_t size = 0;
if(bytes != sizeof(int))
{
size = bytes/sizeof(int);
bIsArray = true;
StartArray(name, size, PersistToDB);
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
m_arrayBuilders.back().second->append(var[i]);
}
}
else
{
m_arrayBuilders.back().second->append(*var);
}
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
if(bIsArray)
{
for(uint32_t i=0; i<size; i++)
{
var[i] = m_arrays.back().second.front().Int();
m_arrays.back().second.pop_front();
}
}
else
{
*var = m_arrays.back().second.front().Int();
m_arrays.back().second.pop_front();
}
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = m_objects.back()[name.c_str()].Int();
}
else
{
*var = m_obj[name.c_str()].Int();
}
}
if(bIsArray)
{
EndArray();
}
}
void MongoSerializerBase::serialize(mongo::Date_t* var, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
m_arrayBuilders.back().second->append(*var);
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
*var = m_arrays.back().second.front().Date();
m_arrays.back().second.pop_front();
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = m_objects.back()[name.c_str()].Date();
}
else
{
*var = m_obj[name.c_str()].Date();
}
}
}
void MongoSerializerBase::serialize(mongo::BSONObj* var, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
m_arrayBuilders.back().second->append(*var);
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
*var = m_arrays.back().second.front().Obj().copy();
m_arrays.back().second.pop_front();
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = m_objects.back()[name.c_str()].Obj().copy();
}
else
{
*var = m_obj[name.c_str()].Obj().copy();
}
}
}
void MongoSerializerBase::serialize(mongo::OID* var, String const& name, bool PersistToDB)
{
if(!PersistToDB || m_disableDepth)
{
return;
}
if(!m_bIsValid)
{
m_bError = true;
}
if(m_bError)
{
return;
}
if(IsSaving())
{
if(!m_arrayBuilders.empty() && m_stateTracker.back() == State::Array)
{
m_arrayBuilders.back().second->append(*var);
}
else if(!m_objectBuilders.empty() && m_stateTracker.back() == State::Object)
{
if(m_objectBuilders.back().second->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_objectBuilders.back().second->append(name.c_str(), *var);
}
else
{
if(m_builder->hasField(name.c_str()))
{
SPRAWL_ABORT_MSG("Mongo serialization does not support duplicate keys: key %s was duplicated.", name.c_str());
}
m_builder->append(name.c_str(), *var);
}
}
else
{
if(!m_arrays.empty() && m_stateTracker.back() == State::Array)
{
*var = m_arrays.back().second.front().OID();
m_arrays.back().second.pop_front();
}
else if(!m_objects.empty() && m_stateTracker.back() == State::Object)
{
*var = m_objects.back()[name.c_str()].OID();
}
else
{
*var = m_obj[name.c_str()].OID();
}
}
}
SerializerBase& operator%(SerializerBase& s, SerializationData<mongo::OID>&& var)
{
if(s.IsMongoStream())
{
s.serialize(&var.val, var.name, var.PersistToDB);
}
else
{
if(s.IsLoading())
{
std::string str;
s % prepare_data(str, var.name, var.PersistToDB);
var.val.init(str);
}
else
{
s % prepare_data(var.val.str(), var.name, var.PersistToDB);
}
}
return s;
}
SerializerBase& operator%(SerializerBase& s, SerializationData<mongo::BSONObj>&& var)
{
if(s.IsMongoStream())
{
s.serialize(&var.val, var.name, var.PersistToDB);
}
else
{
if(s.IsLoading())
{
sprawl::String str;
s % prepare_data(str, var.name, var.PersistToDB);
if(s.IsBinary())
{
var.val = mongo::BSONObj(str.c_str()).copy();
}
else
{
var.val = mongo::fromjson(str.c_str());
}
}
else
{
if(s.IsBinary())
{
s % prepare_data(sprawl::String(var.val.objdata(), var.val.objsize()), var.name, var.PersistToDB);
}
else
{
s % prepare_data(var.val.jsonString(), var.name, var.PersistToDB);
}
}
}
return s;
}
SerializerBase& operator%(SerializerBase& s, SerializationData<mongo::Date_t>&& var)
{
if(s.IsMongoStream())
{
s.serialize(&var.val, var.name, var.PersistToDB);
}
else
{
if(s.IsLoading())
{
int64_t val;
s % prepare_data(val, var.name, var.PersistToDB);
var.val = mongo::Date_t(val);
}
else
{
s % prepare_data(var.val.millis, var.name, var.PersistToDB);
}
}
return s;
}
}
}
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #1 | 23398 | ququlala | "Forking branch Mainline of shadauxcat-libsprawl to ququlala-libsprawl." | ||
| //guest/ShadauxCat/Sprawl/Mainline/serialization/mongo/MongoSerializer.cpp | |||||
| #2 | 14783 | ShadauxCat |
Style corrections (placement of const) #review-14784 |
||
| #1 | 11496 | ShadauxCat | Initial checkin: Current states for csbuild and libSprawl | ||