Hide list of children completely in structured data

* This makes it easier to enforce object ownership, as well as gives us options
  for e.g. generating structure data on demand lazily.
This commit is contained in:
baldurk
2020-10-23 15:55:44 +01:00
parent 117e16041a
commit 394896a3c9
15 changed files with 317 additions and 246 deletions
@@ -268,10 +268,10 @@ void PersistantConfig::applyValues(const QVariantMap &values)
SDObject *debug = RENDERDOC_SetConfigSetting("DXBC.Debug.SearchDirPaths");
debug->DeleteChildren();
debug->data.children.resize(searchPaths.size());
debug->ReserveChildren(searchPaths.size());
for(int i = 0; i < searchPaths.size(); i++)
debug->data.children[i] = makeSDString("$el", searchPaths[i]);
debug->AddAndOwnChild(makeSDString("$el", searchPaths[i]));
}
if(settings.contains(lit("d3d12ShaderDebugging")))
+5 -6
View File
@@ -1332,17 +1332,16 @@ void CombineUsageEvents(ICaptureContext &ctx, const rdcarray<EventUsage> &usage,
callback(start, end, us);
}
void addStructuredObjects(RDTreeWidgetItem *parent, const StructuredObjectList &objs,
bool parentIsArray)
void addStructuredChildren(RDTreeWidgetItem *parent, const SDObject &parentObj)
{
for(const SDObject *obj : objs)
for(const SDObject *obj : parentObj)
{
if(obj->type.flags & SDTypeFlags::Hidden)
continue;
QVariant param;
if(parentIsArray)
if(parentObj.type.basetype == SDBasic::Array)
param = QFormatStr("[%1]").arg(parent->childCount());
else
param = obj->name;
@@ -1377,11 +1376,11 @@ void addStructuredObjects(RDTreeWidgetItem *parent, const StructuredObjectList &
case SDBasic::Chunk:
case SDBasic::Struct:
param = QFormatStr("%1()").arg(obj->type.name);
addStructuredObjects(item, obj->data.children, false);
addStructuredChildren(item, *obj);
break;
case SDBasic::Array:
param = QFormatStr("%1[]").arg(obj->type.name);
addStructuredObjects(item, obj->data.children, true);
addStructuredChildren(item, *obj);
break;
case SDBasic::Null: param = lit("NULL"); break;
case SDBasic::Buffer: param = lit("(%1 bytes)").arg(obj->type.byteSize); break;
+1 -2
View File
@@ -126,8 +126,7 @@ void CombineUsageEvents(
class RDTreeWidgetItem;
void addStructuredObjects(RDTreeWidgetItem *parent, const StructuredObjectList &objs,
bool parentIsArray);
void addStructuredChildren(RDTreeWidgetItem *parent, const SDObject &parentObj);
struct PointerTypeRegistry
{
+4
View File
@@ -52,6 +52,10 @@
%rename("string") "SDObjectData::str";
// convenience - in C++ we have both duplicating and non-duplicating adds, but in python we only
// expose the duplicating add. Rename it to be simpler
%rename("AddChild") "SDObject::DuplicateAndAddChild";
%begin %{
#undef slots
%}
@@ -130,13 +130,14 @@ struct ExtRefcount<SDChunk *> : public ActiveRefcounter<SDChunk>
{
// dec ref any python-owned objects in the children array, so the default destructor doesn't
// just delete them.
for(size_t i = 0; i < c->data.children.size(); i++)
if(ActiveRefcounter<SDObject>::HasPyObject(c->data.children[i]))
ActiveRefcounter<SDObject>::Dec(c->data.children[i]);
for(size_t i = 0; i < c->NumChildren(); i++)
if(ActiveRefcounter<SDObject>::HasPyObject(c->GetChild(i)))
ActiveRefcounter<SDObject>::Dec(c->GetChild(i));
// we clear the array, because anything still left is C++ owned. We're just borrowing a
// reference to it, so C++ will control the lifetime.
c->data.children.clear();
StructuredObjectList discard;
c->TakeAllChildren(discard);
ActiveRefcounter<SDChunk>::DelPyObject(py, c);
}
@@ -154,13 +155,14 @@ struct ExtRefcount<SDObject *> : public ActiveRefcounter<SDObject>
{
// dec ref any python-owned objects in the children array, so the default destructor doesn't
// just delete them.
for(size_t i = 0; i < o->data.children.size(); i++)
if(ActiveRefcounter<SDObject>::HasPyObject(o->data.children[i]))
ActiveRefcounter<SDObject>::Dec(o->data.children[i]);
for(size_t i = 0; i < o->NumChildren(); i++)
if(ActiveRefcounter<SDObject>::HasPyObject(o->GetChild(i)))
ActiveRefcounter<SDObject>::Dec(o->GetChild(i));
// we clear the array, because anything still left is C++ owned. We're just borrowing a
// reference to it, so C++ will control the lifetime.
o->data.children.clear();
StructuredObjectList discard;
o->TakeAllChildren(discard);
ActiveRefcounter<SDObject>::DelPyObject(py, o);
}
+1 -1
View File
@@ -154,7 +154,7 @@ void APIInspector::fillAPIView()
root->setText(1, chunk->name);
addStructuredObjects(root, chunk->data.children, false);
addStructuredChildren(root, *chunk);
}
else
{
+14 -11
View File
@@ -65,7 +65,7 @@ static bool anyChildChanged(const SDObject *o)
if(val && def)
return !val->HasEqualValue(def);
for(const SDObject *c : o->data.children)
for(const SDObject *c : *o)
{
if(anyChildChanged(c))
return true;
@@ -95,7 +95,7 @@ public:
if(row < 0 || row > rowCount(parent))
return QModelIndex();
return createIndex(row, column, o->data.children[row]);
return createIndex(row, column, o->GetChild(row));
}
QModelIndex parent(const QModelIndex &index) const override
@@ -121,7 +121,7 @@ public:
if(o->FindChild("value"))
return 0;
return o->data.children.count();
return (int)o->NumChildren();
}
enum Columns
@@ -312,7 +312,7 @@ private:
return;
int i = 0;
for(SDObject *c : o->GetChildren())
for(SDObject *c : *o)
{
parents[c] = parent;
populateParents(c, index(i++, 0, parent));
@@ -343,11 +343,14 @@ protected:
SDObject *o = obj(source_parent);
return matchesAnyChild(o->data.children[source_row]);
return matchesAnyChild(o->GetChild(source_row));
}
bool matchesAnyChild(SDObject *o) const
{
if(!o)
return false;
if(QString(o->name).contains(m_Text, Qt::CaseInsensitive))
return true;
@@ -360,7 +363,7 @@ protected:
return false;
}
for(SDObject *c : o->GetChildren())
for(SDObject *c : *o)
if(matchesAnyChild(c))
return true;
@@ -459,8 +462,8 @@ bool SettingDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
val->DeleteChildren();
for(size_t c = 0; c < def->data.children.size(); c++)
val->data.children.push_back(def->data.children[c]->Duplicate());
for(size_t c = 0; c < def->NumChildren(); c++)
val->DuplicateAndAddChild(def->GetChild(c));
// call setData() to emit the dataChanged for this element and all parents
model->setData(index, QVariant(), Qt::UserRole);
@@ -585,7 +588,7 @@ QWidget *SettingDelegate::createEditor(QWidget *parent, const QStyleOptionViewIt
QStringList items;
for(SDObject *c : val->data.children)
for(SDObject *c : *val)
items << c->data.str;
list.setItems(items);
@@ -597,10 +600,10 @@ QWidget *SettingDelegate::createEditor(QWidget *parent, const QStyleOptionViewIt
items = list.getItems();
val->DeleteChildren();
val->data.children.resize(items.size());
val->ReserveChildren(items.size());
for(int i = 0; i < items.size(); i++)
val->data.children[i] = makeSDString("$el", items[i]);
val->AddAndOwnChild(makeSDString("$el", items[i]));
}
// we've handled the edit synchronously, don't create an edit widget
@@ -494,7 +494,7 @@ void SettingsDialog::on_chooseSearchPaths_clicked()
QStringList items;
for(SDObject *c : getPaths->data.children)
for(SDObject *c : *getPaths)
items << c->data.str;
list.setItems(items);
@@ -508,10 +508,10 @@ void SettingsDialog::on_chooseSearchPaths_clicked()
SDObject *setPaths = RENDERDOC_SetConfigSetting("DXBC.Debug.SearchDirPaths");
setPaths->DeleteChildren();
setPaths->data.children.resize(items.size());
setPaths->ReserveChildren(items.size());
for(int i = 0; i < items.size(); i++)
setPaths->data.children[i] = makeSDString("$el", items[i]);
setPaths->AddAndOwnChild(makeSDString("$el", items[i]));
RENDERDOC_SaveConfigSettings();
}
+1 -1
View File
@@ -315,7 +315,7 @@ void ResourceInspector::Inspect(ResourceId id)
root->setText(0, chunkObj->name);
addStructuredObjects(root, chunkObj->data.children, false);
addStructuredChildren(root, *chunkObj);
}
else
{
+99 -20
View File
@@ -351,13 +351,22 @@ struct SDObjectData
DOCUMENT("The string contents of the object.");
rdcstr str;
DOCUMENT("A list of :class:`SDObject` containing the children of this :class:`SDObject`.");
StructuredObjectList children;
SDObjectData(const SDObjectData &) = delete;
SDObjectData &operator=(const SDObjectData &other) = delete;
private:
friend struct SDObject;
friend struct SDChunk;
// allow serialisation functions access to the data
template <class SerialiserType>
friend void DoSerialise(SerialiserType &ser, SDObjectData &el);
template <class SerialiserType>
friend void DoSerialise(SerialiserType &ser, SDObject *el);
DOCUMENT("A list of :class:`SDObject` containing the children of this :class:`SDObject`.");
StructuredObjectList children;
void *operator new(size_t count) = delete;
void *operator new[](size_t count) = delete;
void operator delete(void *p) = delete;
@@ -366,7 +375,13 @@ private:
DECLARE_REFLECTION_STRUCT(SDObjectData);
DOCUMENT("Defines a single structured object.");
DOCUMENT(R"(Defines a single structured object. Structured objects are defined recursively and one
object can either be a basic type (integer, float, etc), an array, or a struct. Arrays and structs
are defined similarly.
Each object owns its children and they will be deleted when it is deleted. You can use
:meth:`Duplicate` to make a deep copy of an object.
)");
struct SDObject
{
/////////////////////////////////////////////////////////////////
@@ -400,7 +415,12 @@ struct SDObject
data.basic.u = 0;
}
~SDObject() { DeleteChildren(); }
~SDObject()
{
// we own our children, so delete them now.
DeleteChildren();
}
DOCUMENT("Create a deep copy of this object.");
SDObject *Duplicate() const
{
@@ -426,7 +446,13 @@ struct SDObject
DOCUMENT("The :class:`SDObjectData` with the contents of this object.");
SDObjectData data;
DOCUMENT("Checks if the given object has the same value as this one.");
DOCUMENT(R"(Checks if the given object has the same value as this one. This equality is defined
recursively through children.
:param SDObject obj: The object to compare against
:return: A boolean indicating if the object is equal to this one.
:rtype: ``bool``
)");
bool HasEqualValue(const SDObject *o) const
{
bool ret = true;
@@ -452,10 +478,21 @@ struct SDObject
return ret;
}
DOCUMENT("Add a new child object by duplicating it.");
inline void AddChild(SDObject *child) { data.children.push_back(child->Duplicate()); }
DOCUMENT("Find a child object by a given name.");
inline SDObject *FindChild(const char *childName) const
// this is renamed to just AddChild in the python interface file, since we always duplicate for
// python.
DOCUMENT(R"(Add a new child object.
:param SDObject obj: The new child to add
)");
inline void DuplicateAndAddChild(SDObject *child) { data.children.push_back(child->Duplicate()); }
DOCUMENT(R"(Find a child object by a given name. If no matching child is found, ``None`` is
returned.
:param str name: The name to search for.
:return: A reference to the child object if found, or ``None`` if not.
:rtype: SDObject
)");
inline SDObject *FindChild(const rdcstr &childName) const
{
for(size_t i = 0; i < data.children.size(); i++)
if(data.children[i]->name == childName)
@@ -463,7 +500,13 @@ struct SDObject
return NULL;
}
DOCUMENT("Get a child object at a given index.");
DOCUMENT(R"(Find a child object by a given index. If the index is out of bounds, ``None`` is
returned.
:param int index: The index to look up.
:return: A reference to the child object if valid, or ``None`` if not.
:rtype: SDObject
)");
inline SDObject *GetChild(size_t index) const
{
if(index < data.children.size())
@@ -471,6 +514,16 @@ struct SDObject
return NULL;
}
DOCUMENT(R"(Delete the child object at an index. If the index is out of bounds, nothing happens.
:param int index: The index to remove.
)");
inline void RemoveChild(size_t index)
{
if(index < data.children.size())
delete data.children.takeAt(index);
}
DOCUMENT("Delete all child objects.");
inline void DeleteChildren()
{
@@ -480,10 +533,12 @@ struct SDObject
data.children.clear();
}
DOCUMENT("Get the number of child objects.");
DOCUMENT(R"(Get the number of child objects.
:return: The number of children this object contains.
:rtype: ``int``
)");
inline size_t NumChildren() const { return data.children.size(); }
DOCUMENT("Get a ``list`` of :class:`SDObject` children.");
inline StructuredObjectList &GetChildren() { return data.children; }
#if !defined(SWIG)
// these are for C++ iteration so not defined when SWIG is generating interfaces
inline SDObject *const *begin() const { return data.children.begin(); }
@@ -492,6 +547,32 @@ struct SDObject
inline SDObject **end() { return data.children.end(); }
#endif
#if !defined(SWIG)
// this interface is 'more advanced' and is intended for C++ code manipulating structured data.
// reserve a number of children up front, useful when constructing an array to avoid repeated
// allocations.
void ReserveChildren(size_t num) { data.children.reserve(num); }
// add a new child without duplicating it, and take ownership of it. Returns the child back
// immediately for easy chaining.
SDObject *AddAndOwnChild(SDObject *child)
{
data.children.push_back(child);
return child;
}
// similar to AddAndOwnChild, but insert at a given offset
SDObject *InsertAndOwnChild(size_t offs, SDObject *child)
{
data.children.insert(offs, child);
return child;
}
// Take ownership of the whole children array from the object.
void TakeAllChildren(StructuredObjectList &objs)
{
objs.clear();
objs.swap(data.children);
}
#endif
// C++ gets more extensive typecasts. We'll add a couple for python in the interface file
#if !defined(SWIG)
// templated enum cast
@@ -577,8 +658,6 @@ struct SDObject
type.flags = SDTypeFlags::HasCustomString;
return this;
}
void AddAndOwnChild(SDObject *child) { data.children.push_back(child); }
#endif
// these are common to both python and C++
@@ -720,9 +799,9 @@ inline SDObject *makeSDObject(const char *name, QVariant val)
QVariantList list = val.toList();
ret->type.name = "array"_lit;
ret->type.basetype = SDBasic::Array;
ret->data.children.reserve(list.size());
ret->ReserveChildren(list.size());
for(int i = 0; i < list.size(); i++)
ret->data.children.push_back(makeSDObject("[]", list.at(i)));
ret->AddAndOwnChild(makeSDObject("[]", list.at(i)));
ret->type.byteSize = list.size();
break;
}
@@ -731,9 +810,9 @@ inline SDObject *makeSDObject(const char *name, QVariant val)
QVariantMap map = val.toMap();
ret->type.name = "struct"_lit;
ret->type.basetype = SDBasic::Struct;
ret->data.children.reserve(map.size());
ret->ReserveChildren(map.size());
for(const QString &str : map.keys())
ret->data.children.push_back(makeSDObject(str.toUtf8().data(), map[str]));
ret->AddAndOwnChild(makeSDObject(str.toUtf8().data(), map[str]));
ret->type.byteSize = map.size();
break;
}
+17 -17
View File
@@ -119,13 +119,13 @@ static void Config2XML(pugi::xml_node &parent, SDObject &child)
obj.append_attribute("type") = ToStr(value->type.basetype).c_str();
if(value->type.basetype == SDBasic::Array)
{
if(!value->data.children.empty())
obj.append_attribute("elemtype") = ToStr(value->data.children[0]->type.basetype).c_str();
if(value->NumChildren() > 0)
obj.append_attribute("elemtype") = ToStr(value->GetChild(0)->type.basetype).c_str();
else
obj.append_attribute("elemtype") = "";
for(size_t o = 0; o < value->data.children.size(); o++)
saveSDObject(*value->data.children[o], obj.append_child("item"));
for(size_t o = 0; o < value->NumChildren(); o++)
saveSDObject(*value->GetChild(o), obj.append_child("item"));
}
else
{
@@ -149,7 +149,7 @@ static SDObject *XML2Config(pugi::xml_node &obj)
SDObject *childObj = XML2Config(child);
if(childObj)
{
ret->data.children.push_back(childObj);
ret->AddAndOwnChild(childObj);
}
else
{
@@ -194,7 +194,7 @@ static SDObject *XML2Config(pugi::xml_node &obj)
if(childObj)
{
valueObj->data.children.push_back(childObj);
valueObj->AddAndOwnChild(childObj);
}
else
{
@@ -244,7 +244,7 @@ static SDObject *importXMLConfig(StreamReader &stream)
{
SDObject *childObj = XML2Config(child);
if(childObj)
ret->data.children.push_back(XML2Config(child));
ret->AddAndOwnChild(XML2Config(child));
}
}
@@ -258,8 +258,8 @@ static void exportXMLConfig(StreamWriter &stream, const SDObject *obj)
pugi::xml_node xRoot = doc.append_child("config");
xRoot.append_attribute("version") = (uint32_t)1;
for(size_t o = 0; o < obj->data.children.size(); o++)
Config2XML(xRoot, *obj->data.children[o]);
for(size_t o = 0; o < obj->NumChildren(); o++)
Config2XML(xRoot, *obj->GetChild(o));
xml_stream_writer writer(stream);
doc.save(writer, " ", pugi::format_default | pugi::format_no_empty_element_tags);
@@ -325,8 +325,8 @@ static bool MergeConfigValues(const rdcstr &prefix, SDObject *dstConfig, const S
dstVal->DeleteChildren();
for(size_t c = 0; c < srcVal->data.children.size(); c++)
dstVal->data.children.push_back(srcVal->data.children[c]->Duplicate());
for(size_t c = 0; c < srcVal->NumChildren(); c++)
dstVal->DuplicateAndAddChild(srcVal->GetChild(c));
}
// if the description has changed from the loaded, need to write the new one
@@ -344,7 +344,7 @@ static bool MergeConfigValues(const rdcstr &prefix, SDObject *dstConfig, const S
ret |= true;
// if we're copying nodes, do that now
dstConfig->AddChild(srcChild->Duplicate());
dstConfig->DuplicateAndAddChild(srcChild->Duplicate());
}
}
@@ -385,9 +385,9 @@ rdcstr DefValString(const T &el)
// this one needs a special implementation unfortunately to convert
const rdcarray<rdcstr> &ConfigVarRegistration<rdcarray<rdcstr>>::value()
{
tmp.resize(obj->data.children.size());
tmp.resize(obj->NumChildren());
for(size_t i = 0; i < tmp.size(); i++)
tmp[i] = obj->data.children[i]->data.str;
tmp[i] = obj->GetChild(i)->data.str;
return tmp;
}
@@ -410,7 +410,7 @@ inline SDObject *makeSDObject(const char *name, const rdcarray<rdcstr> &vals)
SDObject *ret = new SDObject(name, "array"_lit);
ret->type.basetype = SDBasic::Array;
for(const rdcstr &s : vals)
ret->data.children.push_back(makeSDObject("$el", s));
ret->AddAndOwnChild(makeSDObject("$el", s));
return ret;
}
@@ -581,9 +581,9 @@ void RenderDoc::RegisterSetting(const rdcstr &settingPath, SDObject *setting)
{
child = new SDObject(node, "category"_lit);
auto it =
std::lower_bound(cur->data.children.begin(), cur->data.children.end(), child,
std::lower_bound(cur->begin(), cur->end(), child,
[](const SDObject *a, const SDObject *b) { return a->name < b->name; });
cur->data.children.insert(it - cur->data.children.begin(), child);
cur->InsertAndOwnChild(it - cur->begin(), child);
}
cur = child;
+17 -17
View File
@@ -231,12 +231,12 @@ static void Obj2XML(pugi::xml_node &parent, SDObject &child)
}
else if(child.type.basetype == SDBasic::Struct || child.type.basetype == SDBasic::Array)
{
if(child.type.basetype == SDBasic::Array && !child.data.children.empty())
if(child.type.basetype == SDBasic::Array && child.NumChildren() > 0)
obj.remove_attribute("typename");
for(size_t o = 0; o < child.data.children.size(); o++)
for(size_t o = 0; o < child.NumChildren(); o++)
{
Obj2XML(obj, *child.data.children[o]);
Obj2XML(obj, *child.GetChild(o));
if(child.type.basetype == SDBasic::Array)
obj.last_child().remove_attribute("name");
@@ -444,15 +444,15 @@ static ReplayStatus Structured2XML(const char *filename, const RDCFile &file, ui
{
xChunk.append_attribute("opaque") = true;
RDCASSERT(!chunk->data.children.empty());
RDCASSERT(chunk->NumChildren() > 0);
pugi::xml_node opaque = xChunk.append_child("buffer");
opaque.append_attribute("byteLength") = chunk->data.children[0]->type.byteSize;
opaque.text() = chunk->data.children[0]->data.basic.u;
opaque.append_attribute("byteLength") = chunk->GetChild(0)->type.byteSize;
opaque.text() = chunk->GetChild(0)->data.basic.u;
}
else
{
for(size_t o = 0; o < chunk->data.children.size(); o++)
Obj2XML(xChunk, *chunk->data.children[o]);
for(size_t o = 0; o < chunk->NumChildren(); o++)
Obj2XML(xChunk, *chunk->GetChild(o));
}
if(progress)
@@ -516,14 +516,14 @@ static SDObject *XML2Obj(pugi::xml_node &obj)
{
for(pugi::xml_node child = obj.first_child(); child; child = child.next_sibling())
{
ret->data.children.push_back(XML2Obj(child));
SDObject *c = ret->AddAndOwnChild(XML2Obj(child));
if(ret->type.basetype == SDBasic::Array)
ret->data.children.back()->name = "$el";
c->name = "$el";
}
if(ret->type.basetype == SDBasic::Array && !ret->data.children.empty())
ret->type.name = ret->data.children.back()->type.name;
if(ret->type.basetype == SDBasic::Array && ret->NumChildren() > 0)
ret->type.name = ret->GetChild(0)->type.name;
}
else if(ret->type.basetype == SDBasic::Buffer)
{
@@ -813,15 +813,15 @@ static ReplayStatus XML2Structured(const char *xml, const ThumbTypeAndData &thum
chunk->metadata.flags |= SDChunkFlags::OpaqueChunk;
chunk->data.children.push_back(new SDObject("Opaque chunk"_lit, "Byte Buffer"_lit));
chunk->data.children[0]->type.basetype = SDBasic::Buffer;
chunk->data.children[0]->type.byteSize = opaque.attribute("byteLength").as_ullong();
chunk->data.children[0]->data.basic.u = opaque.text().as_ullong();
SDObject *buf = chunk->AddAndOwnChild(new SDObject("Opaque chunk"_lit, "Byte Buffer"_lit));
buf->type.basetype = SDBasic::Buffer;
buf->type.byteSize = opaque.attribute("byteLength").as_ullong();
buf->data.basic.u = opaque.text().as_ullong();
}
else
{
for(pugi::xml_node child = xChunk.first_child(); child; child = child.next_sibling())
chunk->data.children.push_back(XML2Obj(child));
chunk->AddAndOwnChild(XML2Obj(child));
}
chunks.push_back(chunk);
+8 -9
View File
@@ -210,9 +210,8 @@ void Serialiser<SerialiserMode::Reading>::SkipCurrentChunk()
SDObject &current = *m_StructureStack.back();
current.data.children.push_back(new SDObject("Opaque chunk"_lit, "Byte Buffer"_lit));
SDObject &obj = *current.AddAndOwnChild(new SDObject("Opaque chunk"_lit, "Byte Buffer"_lit));
SDObject &obj = *current.data.children.back();
obj.type.basetype = SDBasic::Buffer;
obj.type.byteSize = m_ChunkMetadata.length;
@@ -243,7 +242,7 @@ void Serialiser<SerialiserMode::Reading>::SkipCurrentChunk()
{
SDObject &current = *m_StructureStack.back();
SDObject &obj = *current.data.children.back();
SDObject &obj = *current.GetChild(current.NumChildren() - 1);
obj.data.basic.u = m_StructuredFile->buffers.size();
@@ -590,9 +589,9 @@ void Serialiser<SerialiserMode::Writing>::WriteStructuredFile(const SDFile &file
if(chunk.metadata.flags & SDChunkFlags::OpaqueChunk)
{
RDCASSERT(chunk.data.children.size() == 1);
RDCASSERT(chunk.NumChildren() == 1);
size_t bufID = (size_t)chunk.data.children[0]->data.basic.u;
size_t bufID = (size_t)chunk.GetChild(0)->data.basic.u;
byte *ptr = m_StructuredFile->buffers[bufID]->data();
size_t len = m_StructuredFile->buffers[bufID]->size();
@@ -600,10 +599,10 @@ void Serialiser<SerialiserMode::Writing>::WriteStructuredFile(const SDFile &file
}
else
{
for(size_t o = 0; o < chunk.data.children.size(); o++)
for(size_t o = 0; o < chunk.NumChildren(); o++)
{
// note, we don't need names because we aren't exporting structured data
ser->Serialise(""_lit, chunk.data.children[o]);
ser->Serialise(""_lit, chunk.GetChild(o));
}
}
@@ -753,8 +752,8 @@ void DoSerialise(SerialiserType &ser, SDObject *el)
{
case SDBasic::Chunk: RDCERR("Unexpected chunk inside object!"); break;
case SDBasic::Struct:
for(size_t o = 0; o < el->data.children.size(); o++)
ser.Serialise(""_lit, el->data.children[o]);
for(size_t o = 0; o < el->NumChildren(); o++)
ser.Serialise(""_lit, el->GetChild(o));
break;
case SDBasic::Array: ser.Serialise(""_lit, (rdcarray<SDObject *> &)el->data.children); break;
case SDBasic::Null:
+44 -58
View File
@@ -226,10 +226,9 @@ public:
SDObject &current = *m_StructureStack.back();
current.data.children.push_back(new SDObject(name, TypeName<T>()));
m_StructureStack.push_back(current.data.children.back());
SDObject &obj = *current.AddAndOwnChild(new SDObject(name, TypeName<T>()));
m_StructureStack.push_back(&obj);
SDObject &obj = *m_StructureStack.back();
obj.type.byteSize = sizeof(T);
if(std::is_union<T>::value)
obj.type.flags |= SDTypeFlags::Union;
@@ -272,10 +271,9 @@ public:
SDObject &current = *m_StructureStack.back();
current.data.children.push_back(new SDObject(name, "Byte Buffer"_lit));
m_StructureStack.push_back(current.data.children.back());
SDObject &obj = *current.AddAndOwnChild(new SDObject(name, "Byte Buffer"_lit));
m_StructureStack.push_back(&obj);
SDObject &obj = *m_StructureStack.back();
obj.type.basetype = SDBasic::Buffer;
obj.type.byteSize = byteSize;
}
@@ -382,10 +380,9 @@ public:
SDObject &current = *m_StructureStack.back();
current.data.children.push_back(new SDObject(name, "Byte Buffer"_lit));
m_StructureStack.push_back(current.data.children.back());
SDObject &obj = *current.AddAndOwnChild(new SDObject(name, "Byte Buffer"_lit));
m_StructureStack.push_back(&obj);
SDObject &obj = *m_StructureStack.back();
obj.type.basetype = SDBasic::Buffer;
obj.type.byteSize = count;
}
@@ -494,22 +491,20 @@ public:
}
SDObject &parent = *m_StructureStack.back();
parent.data.children.push_back(new SDObject(name, TypeName<T>()));
m_StructureStack.push_back(parent.data.children.back());
SDObject &arr = *m_StructureStack.back();
SDObject &arr = *parent.AddAndOwnChild(new SDObject(name, TypeName<T>()));
m_StructureStack.push_back(&arr);
arr.type.basetype = SDBasic::Array;
arr.type.byteSize = N;
arr.type.flags |= SDTypeFlags::FixedArray;
arr.data.children.resize(N);
arr.ReserveChildren(N);
for(size_t i = 0; i < N; i++)
{
arr.data.children[i] = new SDObject("$el"_lit, TypeName<T>());
m_StructureStack.push_back(arr.data.children[i]);
SDObject &obj = *m_StructureStack.back();
SDObject &obj = *arr.AddAndOwnChild(new SDObject("$el"_lit, TypeName<T>()));
m_StructureStack.push_back(&obj);
// default to struct. This will be overwritten if appropriate
obj.type.basetype = SDBasic::Struct;
@@ -613,14 +608,14 @@ public:
}
SDObject &parent = *m_StructureStack.back();
parent.data.children.push_back(new SDObject(name, TypeName<T>()));
m_StructureStack.push_back(parent.data.children.back());
SDObject &arr = *m_StructureStack.back();
SDObject &arr = *parent.AddAndOwnChild(new SDObject(name, TypeName<T>()));
m_StructureStack.push_back(&arr);
arr.type.basetype = SDBasic::Array;
arr.type.byteSize = arrayCount;
arr.data.children.resize((size_t)arrayCount);
arr.ReserveChildren((size_t)arrayCount);
// Coverity is unable to tie this allocation together with the automatic scoped deallocation in the
// ScopedDeseralise* classes. We can verify with e.g. valgrind that there are no leaks, so to keep
@@ -637,10 +632,8 @@ public:
for(uint64_t i = 0; el && i < arrayCount; i++)
{
arr.data.children[(size_t)i] = new SDObject("$el"_lit, TypeName<T>());
m_StructureStack.push_back(arr.data.children[(size_t)i]);
SDObject &obj = *m_StructureStack.back();
SDObject &obj = *arr.AddAndOwnChild(new SDObject("$el"_lit, TypeName<T>()));
m_StructureStack.push_back(&obj);
// default to struct. This will be overwritten if appropriate
obj.type.basetype = SDBasic::Struct;
@@ -704,24 +697,22 @@ public:
}
SDObject &parent = *m_StructureStack.back();
parent.data.children.push_back(new SDObject(name, TypeName<U>()));
m_StructureStack.push_back(parent.data.children.back());
SDObject &arr = *m_StructureStack.back();
SDObject &arr = *parent.AddAndOwnChild(new SDObject(name, TypeName<U>()));
m_StructureStack.push_back(&arr);
arr.type.basetype = SDBasic::Array;
arr.type.byteSize = size;
arr.data.children.resize((size_t)size);
arr.ReserveChildren((size_t)size);
if(IsReading())
el.resize((int)size);
for(size_t i = 0; i < (size_t)size; i++)
{
arr.data.children[i] = new SDObject("$el"_lit, TypeName<U>());
m_StructureStack.push_back(arr.data.children[i]);
SDObject &obj = *m_StructureStack.back();
SDObject &obj = *arr.AddAndOwnChild(new SDObject("$el"_lit, TypeName<U>()));
m_StructureStack.push_back(&obj);
// default to struct. This will be overwritten if appropriate
obj.type.basetype = SDBasic::Struct;
@@ -759,20 +750,18 @@ public:
}
SDObject &parent = *m_StructureStack.back();
parent.data.children.push_back(new SDObject(name, "pair"_lit));
m_StructureStack.push_back(parent.data.children.back());
SDObject &arr = *m_StructureStack.back();
SDObject &arr = *parent.AddAndOwnChild(new SDObject(name, "pair"_lit));
m_StructureStack.push_back(&arr);
arr.type.basetype = SDBasic::Struct;
arr.type.byteSize = 2;
arr.data.children.resize(2);
arr.ReserveChildren(2);
{
arr.data.children[0] = new SDObject("first"_lit, TypeName<U>());
m_StructureStack.push_back(arr.data.children[0]);
SDObject &obj = *m_StructureStack.back();
SDObject &obj = *arr.AddAndOwnChild(new SDObject("first"_lit, TypeName<U>()));
m_StructureStack.push_back(&obj);
// default to struct. This will be overwritten if appropriate
obj.type.basetype = SDBasic::Struct;
@@ -784,10 +773,8 @@ public:
}
{
arr.data.children[1] = new SDObject("second"_lit, TypeName<V>());
m_StructureStack.push_back(arr.data.children[1]);
SDObject &obj = *m_StructureStack.back();
SDObject &obj = *arr.AddAndOwnChild(new SDObject("second"_lit, TypeName<V>()));
m_StructureStack.push_back(&obj);
// default to struct. This will be overwritten if appropriate
obj.type.basetype = SDBasic::Struct;
@@ -866,7 +853,7 @@ public:
SDObject &parent = *m_StructureStack.back();
SDObject &nullable = *parent.data.children.back();
SDObject &nullable = *parent.GetChild(parent.NumChildren() - 1);
nullable.type.flags |= SDTypeFlags::Nullable;
if(std::is_union<T>::value)
@@ -875,9 +862,9 @@ public:
else
{
SDObject &parent = *m_StructureStack.back();
parent.data.children.push_back(new SDObject(name, TypeName<T>()));
SDObject &nullable = *parent.data.children.back();
SDObject &nullable = *parent.AddAndOwnChild(new SDObject(name, TypeName<T>()));
nullable.type.basetype = SDBasic::Null;
nullable.type.byteSize = 0;
nullable.type.flags |= SDTypeFlags::Nullable;
@@ -962,10 +949,9 @@ public:
SDObject &current = *m_StructureStack.back();
current.data.children.push_back(new SDObject(name.c_str(), "Byte Buffer"_lit));
m_StructureStack.push_back(current.data.children.back());
SDObject &obj = *current.AddAndOwnChild(new SDObject(name, "Byte Buffer"_lit));
m_StructureStack.push_back(&obj);
SDObject &obj = *m_StructureStack.back();
obj.type.basetype = SDBasic::Buffer;
obj.type.byteSize = totalSize;
@@ -1040,8 +1026,8 @@ public:
{
SDObject &current = *m_StructureStack.back();
if(!current.data.children.empty())
current.data.children.back()->type.flags |= SDTypeFlags::Hidden;
if(current.NumChildren() > 0)
current.GetChild(current.NumChildren() - 1)->type.flags |= SDTypeFlags::Hidden;
}
return *this;
@@ -1053,14 +1039,14 @@ public:
{
SDObject &current = *m_StructureStack.back();
if(!current.data.children.empty())
if(current.NumChildren() > 0)
{
SDObject *last = current.data.children.back();
SDObject *last = current.GetChild(current.NumChildren() - 1);
last->type.name = name;
if(last->type.basetype == SDBasic::Array)
{
for(SDObject *obj : last->data.children)
for(SDObject *obj : *last)
obj->type.name = name;
}
}
@@ -1075,8 +1061,8 @@ public:
{
SDObject &current = *m_StructureStack.back();
if(!current.data.children.empty())
current.data.children.back()->name = name;
if(current.NumChildren() > 0)
current.GetChild(current.NumChildren() - 1)->name = name;
}
return *this;
+91 -91
View File
@@ -253,15 +253,15 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
CHECK(chunk.metadata.length < ser.GetReader()->GetSize());
CHECK(chunk.type.basetype == SDBasic::Chunk);
CHECK(chunk.type.name == "Chunk");
CHECK(chunk.data.children.size() == 16);
CHECK(chunk.NumChildren() == 16);
for(SDObject *o : chunk.data.children)
for(SDObject *o : chunk)
REQUIRE(o);
int childIdx = 0;
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "a");
CHECK(o.type.name == "int64_t");
@@ -273,7 +273,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "b");
CHECK(o.type.name == "uint64_t");
@@ -285,7 +285,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "c");
CHECK(o.type.name == "int32_t");
@@ -297,7 +297,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "d");
CHECK(o.type.name == "uint32_t");
@@ -309,7 +309,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "e");
CHECK(o.type.name == "int16_t");
@@ -321,7 +321,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "f");
CHECK(o.type.name == "uint16_t");
@@ -333,7 +333,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "g");
CHECK(o.type.name == "int8_t");
@@ -345,7 +345,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "h");
CHECK(o.type.name == "uint8_t");
@@ -357,7 +357,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "i");
CHECK(o.type.name == "bool");
@@ -369,7 +369,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "j");
CHECK(o.type.name == "char");
@@ -381,7 +381,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "k");
CHECK(o.type.name == "double");
@@ -393,7 +393,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "l");
CHECK(o.type.name == "float");
@@ -405,7 +405,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "m");
CHECK(o.type.name == "string");
@@ -417,7 +417,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "n");
CHECK(o.type.name == "string");
@@ -429,7 +429,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "s");
CHECK(o.type.name == "string");
@@ -441,7 +441,7 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "t");
CHECK(o.type.name == "int32_t");
@@ -449,12 +449,12 @@ TEST_CASE("Read/write via structured of basic types", "[serialiser]")
CHECK(o.type.byteSize == 4);
CHECK(o.type.flags == SDTypeFlags::FixedArray);
CHECK(o.data.children.size() == 4);
CHECK(o.NumChildren() == 4);
CHECK(o.data.children[0]->data.basic.i == 20);
CHECK(o.data.children[1]->data.basic.c == 20);
CHECK(o.data.children[2]->data.basic.c == 20);
CHECK(o.data.children[3]->data.basic.c == 20);
CHECK(o.GetChild(0)->data.basic.i == 20);
CHECK(o.GetChild(1)->data.basic.c == 20);
CHECK(o.GetChild(2)->data.basic.c == 20);
CHECK(o.GetChild(3)->data.basic.c == 20);
}
StreamWriter *rewriteBuf = new StreamWriter(StreamWriter::DefaultScratchSize);
@@ -933,48 +933,48 @@ TEST_CASE("Read/write container types", "[serialiser][structured]")
const SDChunk &chunk = *structData.chunks[0];
CHECK(chunk.data.children.size() == 2);
CHECK(chunk.NumChildren() == 2);
for(SDObject *o : chunk.data.children)
for(SDObject *o : chunk)
REQUIRE(o);
int childIdx = 0;
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "v");
CHECK(o.type.basetype == SDBasic::Array);
CHECK(o.type.byteSize == 6);
CHECK(o.type.flags == SDTypeFlags::NoFlags);
CHECK(o.data.children.size() == 6);
CHECK(o.NumChildren() == 6);
for(SDObject *child : o.data.children)
for(SDObject *child : o)
{
CHECK(child->type.basetype == SDBasic::SignedInteger);
CHECK(child->type.byteSize == 4);
}
CHECK(o.data.children[0]->data.basic.i == 1);
CHECK(o.data.children[1]->data.basic.i == 1);
CHECK(o.data.children[2]->data.basic.i == 2);
CHECK(o.data.children[3]->data.basic.i == 3);
CHECK(o.data.children[4]->data.basic.i == 5);
CHECK(o.data.children[5]->data.basic.i == 8);
CHECK(o.GetChild(0)->data.basic.i == 1);
CHECK(o.GetChild(1)->data.basic.i == 1);
CHECK(o.GetChild(2)->data.basic.i == 2);
CHECK(o.GetChild(3)->data.basic.i == 3);
CHECK(o.GetChild(4)->data.basic.i == 5);
CHECK(o.GetChild(5)->data.basic.i == 8);
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "p");
CHECK(o.type.name == "pair");
CHECK(o.type.basetype == SDBasic::Struct);
CHECK(o.type.byteSize == 2);
CHECK(o.type.flags == SDTypeFlags::NoFlags);
CHECK(o.data.children.size() == 2);
CHECK(o.NumChildren() == 2);
{
SDObject &first = *o.data.children[0];
SDObject &first = *o.GetChild(0);
CHECK(first.name == "first");
CHECK(first.type.name == "float");
@@ -986,7 +986,7 @@ TEST_CASE("Read/write container types", "[serialiser][structured]")
}
{
SDObject &second = *o.data.children[1];
SDObject &second = *o.GetChild(1);
CHECK(second.name == "second");
CHECK(second.type.name == "string");
@@ -1225,15 +1225,15 @@ TEST_CASE("Read/write complex types", "[serialiser][structured]")
const SDChunk &chunk = *structData.chunks[0];
CHECK(chunk.data.children.size() == 5);
CHECK(chunk.NumChildren() == 5);
for(SDObject *o : chunk.data.children)
for(SDObject *o : chunk)
REQUIRE(o);
int childIdx = 0;
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "enumVal");
CHECK(o.type.basetype == SDBasic::Enum);
@@ -1244,62 +1244,62 @@ TEST_CASE("Read/write complex types", "[serialiser][structured]")
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "sparseStructArray");
CHECK(o.type.basetype == SDBasic::Array);
CHECK(o.type.byteSize == 10);
CHECK(o.type.flags == SDTypeFlags::NoFlags);
CHECK(o.data.children.size() == 10);
CHECK(o.NumChildren() == 10);
for(SDObject *child : o.data.children)
for(SDObject *child : o)
{
CHECK(child->type.basetype == SDBasic::Struct);
CHECK(child->type.name == "struct1");
CHECK(child->type.byteSize == sizeof(struct1));
CHECK(child->data.children.size() == 4);
CHECK(child->data.children[0]->type.basetype == SDBasic::Float);
CHECK(child->data.children[0]->type.byteSize == 4);
CHECK(child->data.children[0]->name == "x");
CHECK(child->data.children[1]->type.basetype == SDBasic::Float);
CHECK(child->data.children[1]->type.byteSize == 4);
CHECK(child->data.children[1]->name == "y");
CHECK(child->data.children[2]->type.basetype == SDBasic::Float);
CHECK(child->data.children[2]->type.byteSize == 4);
CHECK(child->data.children[2]->name == "width");
CHECK(child->data.children[3]->type.basetype == SDBasic::Float);
CHECK(child->data.children[3]->type.byteSize == 4);
CHECK(child->data.children[3]->name == "height");
CHECK(child->NumChildren() == 4);
CHECK(child->GetChild(0)->type.basetype == SDBasic::Float);
CHECK(child->GetChild(0)->type.byteSize == 4);
CHECK(child->GetChild(0)->name == "x");
CHECK(child->GetChild(1)->type.basetype == SDBasic::Float);
CHECK(child->GetChild(1)->type.byteSize == 4);
CHECK(child->GetChild(1)->name == "y");
CHECK(child->GetChild(2)->type.basetype == SDBasic::Float);
CHECK(child->GetChild(2)->type.byteSize == 4);
CHECK(child->GetChild(2)->name == "width");
CHECK(child->GetChild(3)->type.basetype == SDBasic::Float);
CHECK(child->GetChild(3)->type.byteSize == 4);
CHECK(child->GetChild(3)->name == "height");
}
CHECK(o.data.children[0]->data.children[0]->data.basic.d == 0.0f);
CHECK(o.data.children[0]->data.children[1]->data.basic.d == 0.0f);
CHECK(o.data.children[0]->data.children[2]->data.basic.d == 0.0f);
CHECK(o.data.children[0]->data.children[3]->data.basic.d == 0.0f);
CHECK(o.GetChild(0)->GetChild(0)->data.basic.d == 0.0f);
CHECK(o.GetChild(0)->GetChild(1)->data.basic.d == 0.0f);
CHECK(o.GetChild(0)->GetChild(2)->data.basic.d == 0.0f);
CHECK(o.GetChild(0)->GetChild(3)->data.basic.d == 0.0f);
CHECK(o.data.children[5]->data.children[0]->data.basic.d == 1.0f);
CHECK(o.data.children[5]->data.children[1]->data.basic.d == 2.0f);
CHECK(o.data.children[5]->data.children[2]->data.basic.d == 3.0f);
CHECK(o.data.children[5]->data.children[3]->data.basic.d == 4.0f);
CHECK(o.GetChild(5)->GetChild(0)->data.basic.d == 1.0f);
CHECK(o.GetChild(5)->GetChild(1)->data.basic.d == 2.0f);
CHECK(o.GetChild(5)->GetChild(2)->data.basic.d == 3.0f);
CHECK(o.GetChild(5)->GetChild(3)->data.basic.d == 4.0f);
CHECK(o.data.children[8]->data.children[0]->data.basic.d == 10.0f);
CHECK(o.data.children[8]->data.children[1]->data.basic.d == 20.0f);
CHECK(o.data.children[8]->data.children[2]->data.basic.d == 30.0f);
CHECK(o.data.children[8]->data.children[3]->data.basic.d == 40.0f);
CHECK(o.GetChild(8)->GetChild(0)->data.basic.d == 10.0f);
CHECK(o.GetChild(8)->GetChild(1)->data.basic.d == 20.0f);
CHECK(o.GetChild(8)->GetChild(2)->data.basic.d == 30.0f);
CHECK(o.GetChild(8)->GetChild(3)->data.basic.d == 40.0f);
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "complex");
CHECK(o.type.name == "struct2");
CHECK(o.type.basetype == SDBasic::Struct);
CHECK(o.type.byteSize == sizeof(struct2));
CHECK(o.type.flags == SDTypeFlags::NoFlags);
CHECK(o.data.children.size() == 3);
CHECK(o.NumChildren() == 3);
{
SDObject &c = *o.data.children[0];
SDObject &c = *o.GetChild(0);
CHECK(c.name == "name");
CHECK(c.type.name == "string");
@@ -1310,58 +1310,58 @@ TEST_CASE("Read/write complex types", "[serialiser][structured]")
}
{
SDObject &c = *o.data.children[1];
SDObject &c = *o.GetChild(1);
CHECK(c.name == "floats");
CHECK(c.type.basetype == SDBasic::Array);
CHECK(c.type.flags == SDTypeFlags::NoFlags);
CHECK(c.data.children.size() == 3);
for(SDObject *ch : c.data.children)
CHECK(c.NumChildren() == 3);
for(SDObject *ch : c)
{
CHECK(ch->type.basetype == SDBasic::Float);
CHECK(ch->type.byteSize == 4);
}
CHECK(c.data.children[0]->data.basic.d == 1.2f);
CHECK(c.data.children[1]->data.basic.d == 3.4f);
CHECK(c.data.children[2]->data.basic.d == 5.6f);
CHECK(c.GetChild(0)->data.basic.d == 1.2f);
CHECK(c.GetChild(1)->data.basic.d == 3.4f);
CHECK(c.GetChild(2)->data.basic.d == 5.6f);
}
{
SDObject &c = *o.data.children[2];
SDObject &c = *o.GetChild(2);
CHECK(c.name == "viewports");
CHECK(c.type.basetype == SDBasic::Array);
CHECK(c.type.flags == SDTypeFlags::NoFlags);
CHECK(c.data.children.size() == 4);
for(SDObject *ch : c.data.children)
CHECK(c.NumChildren() == 4);
for(SDObject *ch : c)
{
CHECK(ch->type.basetype == SDBasic::Struct);
CHECK(ch->type.name == "struct1");
}
CHECK(c.data.children[0]->data.children[0]->data.basic.d == 512.0f);
CHECK(c.data.children[0]->data.children[1]->data.basic.d == 0.0f);
CHECK(c.data.children[0]->data.children[2]->data.basic.d == 256.0f);
CHECK(c.data.children[0]->data.children[3]->data.basic.d == 256.0f);
CHECK(c.GetChild(0)->GetChild(0)->data.basic.d == 512.0f);
CHECK(c.GetChild(0)->GetChild(1)->data.basic.d == 0.0f);
CHECK(c.GetChild(0)->GetChild(2)->data.basic.d == 256.0f);
CHECK(c.GetChild(0)->GetChild(3)->data.basic.d == 256.0f);
}
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "inputParam1");
CHECK(o.type.basetype == SDBasic::Struct);
CHECK(o.type.flags == SDTypeFlags::Nullable);
CHECK(o.data.children[0]->data.basic.d == 9.0f);
CHECK(o.data.children[1]->data.basic.d == 9.9f);
CHECK(o.data.children[2]->data.basic.d == 9.99f);
CHECK(o.data.children[3]->data.basic.d == 9.999f);
CHECK(o.GetChild(0)->data.basic.d == 9.0f);
CHECK(o.GetChild(1)->data.basic.d == 9.9f);
CHECK(o.GetChild(2)->data.basic.d == 9.99f);
CHECK(o.GetChild(3)->data.basic.d == 9.999f);
}
{
SDObject &o = *chunk.data.children[childIdx++];
SDObject &o = *chunk.GetChild(childIdx++);
CHECK(o.name == "inputParam2");
CHECK(o.type.basetype == SDBasic::Null);