[The Juce Archive Format Blog]

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).

While I’m being sure to make the Archive class perfectly usable as a single object (which doesn’t require subclassing), one of my goals is to make it so that you CAN subclass it to operate with a particular structure.

I want to get it working as a class in its own right first, and then develop a number of variant subclasses which can be adopted instead. For example, the document format for most applications (thanks to just how easy and intuitive it is with juce) tends to be an XML file. I plan on creating an Archive subclass that assumes this (say, UserDocumentArchive) - there will be a fixed ‘usedocument’ XML file, and helper functions to make adding/removing extra content easy; you could define folders within the archive for storing different types of content (e.g. Images, Audio, etc…), and have functions to ‘getImage(name)’ etc… it will also help when creating the document XML itself, having functions to generate tags which refer to specific items within the archive [i.e. there could be a ‘createXmlReference (Archivable*)’, which you can use in the document to link directly to an item.

I basically want to make it as easy as possible to [a] be able to create/read archives directly, and [b] define a format for a document with mixed content that can be used for a specific application.

I think the decision to make Archive a FileBasedDocument was probably an error, in terms of logical layout; I’m going to take out that part of it and just give it save/load functions, and then it can be used as a member of a FileBasedDocument (it makes a lot more sense when considering how the main document class will be used within an app!).

Anyway, enough rambling from me :slight_smile:

Being new here, I tried to download the class but the link is broken. What’s the status of this project?

/Michael