--- /dev/null
+#ifndef MSP_DATAFILE_PACKSOURCE_H_
+#define MSP_DATAFILE_PACKSOURCE_H_
+
+#include <msp/core/refptr.h>
+#include "collectionsource.h"
+#include "objectloader.h"
+
+namespace Msp {
+namespace DataFile {
+
+/**
+A source that loads data from pack files. As opposed to plain collection
+files, pack files are composed from a number of logical files. They also
+contain an index of objects contained in the pack and which logical files they
+are in. This allows the pack to be loaded in a piecewise manner instead of all
+at once.
+
+It's possible for a pack file to contain plain collection files as well. When
+an object from such a file is requested, the entire sub-collection it is stored
+in is loaded.
+*/
+class PackSource: public CollectionSource
+{
+private:
+ class File;
+ struct Object;
+
+ typedef std::map<std::string, const Object *> ObjectMap;
+
+ class Pack
+ {
+ public:
+ class Loader: public ObjectLoader<Pack>
+ {
+ public:
+ Loader(Pack &);
+ private:
+ void file(const std::string &);
+ };
+
+ private:
+ std::string filename;
+ unsigned base_offset;
+ std::list<File> files;
+
+ public:
+ Pack(const std::string &);
+
+ const std::string &get_filename() const { return filename; }
+ unsigned get_base_offset() const { return base_offset; }
+
+ void collect_objects(ObjectMap &) const;
+ };
+
+ class File
+ {
+ public:
+ class Loader: public ObjectLoader<File>
+ {
+ public:
+ Loader(File &);
+ private:
+ virtual void finish();
+ void object(const std::string &, const std::string &);
+ };
+
+ private:
+ const Pack &pack;
+ std::string filename;
+ unsigned offset;
+ unsigned length;
+ bool collection;
+ std::list<Object> objects;
+ bool loaded;
+
+ public:
+ File(const Pack &, const std::string &);
+
+ RefPtr<IO::Base> open() const;
+ const std::string &get_filename() const { return filename; }
+ std::string get_full_name() const;
+ bool is_collection() const { return collection; }
+
+ void set_loaded();
+ bool is_loaded() const { return loaded; }
+
+ void collect_objects(ObjectMap &) const;
+ };
+
+ class Object
+ {
+ private:
+ File &file;
+ std::string name;
+ std::string keyword;
+
+ public:
+ Object(File &, const std::string &, const std::string &);
+
+ File &get_file() const { return file; }
+ const std::string &get_name() const { return name; }
+ const std::string &get_keyword() const { return keyword; }
+ };
+
+ std::list<Pack> packs;
+ ObjectMap objects;
+
+public:
+ /// Adds a pack file to load objects from. The index is read immediately.
+ void add_pack_file(const std::string &);
+
+
+ virtual bool is_loadable(const CollectionItemTypeBase &, const std::string &) const;
+ virtual NameList get_names(const CollectionItemTypeBase &) const;
+ virtual void load(Collection &, const CollectionItemTypeBase &, const std::string &) const;
+};
+
+} // namespace DataFile
+} // namespace Msp
+
+#endif