What would be nice, it’s a way to describe the archive “format” programatically, and let the framework extract all data when required.
Something like:
struct MyArchiveFormat : public Archive::Defined<MyArchiveFormat>
{
BeginArchiveDesc
DeclareFile(MyFile, "something.xml");
DeclareText(MyText, "to.txt")
DeclareImage(MyPicture, "myPic.jpg");
EndArchiveDesc
};
MyArchiveFormat format;
format.read("archive.zip");
String xmlContent = format["MyFile"].loadFileAsString();
// And so on
The macros are defined as:
#define BeginArchiveDesc Archivable & enumerate(Visitor & vis) { int i = 0;
#define DeclareFile(X, Y) static ArchivableFile X(#X, Y, i); i++; if (vis.accept(X, i)) return X
... and so on for others
#define EndArchiveDesc }
Archive::Described<T> : public T
{
struct NameVisitor
{
bool accept(Archivable & archive, const int position)
{ return (archive.getName() == name); }
NameVisitor(const String & _name) : name(_name) {}
};
struct CountVisitor
{
int count = 0;
bool accept(Archivable & archive, const int position)
{ count = max(count, position); }
};
struct NameAt
{
int pos;
bool accept(Archivable & archive, const int position)
{ return (pos == position); }
}
};
Archive::Defined<T> : public Described<T>
{
struct Map { String Name; Archivable & archive; };
OwnedArray<Map> map;
Archive::Defined<T>()
{
CountVisitor count;
enumerate(count);
for (int i = 0; i < count.count; i++)
{
const String & name = enumerate(NameAt(i)).getName();
map.add(new Map(name, enumerate(NameVisitor(name))));
}
}
Archivable & operator[] (const String & name) { return map[enumerate(NameVisitor(name)).getPosition()]->archive; }
};
So the using the archive is not error prone (it’s declared once, and only once) and it’s safe. (You don’t have to write a serializing code, it’s done automatically with the mixins).