7d616614cff490690d73699f4a5b4f6a76a545f1
[libs/datafile.git] / source / packsource.h
1 #ifndef MSP_DATAFILE_PACKSOURCE_H_
2 #define MSP_DATAFILE_PACKSOURCE_H_
3
4 #include <msp/core/refptr.h>
5 #include "collectionsource.h"
6 #include "objectloader.h"
7
8 namespace Msp {
9 namespace DataFile {
10
11 /**
12 A source that loads data from pack files.  As opposed to plain collection
13 files, pack files are composed from a number of logical files.  They also
14 contain an index of objects contained in the pack and which logical files they
15 are in.  This allows the pack to be loaded in a piecewise manner instead of all
16 at once.
17
18 It's possible for a pack file to contain plain collection files as well.  When
19 an object from such a file is requested, the entire sub-collection it is stored
20 in is loaded.
21 */
22 class PackSource: public CollectionSource
23 {
24 public:
25         struct FileInfo
26         {
27                 std::string name;
28                 unsigned size;
29         };
30
31 private:
32         class File;
33         class Object;
34
35         typedef std::map<std::string, const File *> FileMap;
36         typedef std::map<std::string, const Object *> ObjectMap;
37
38         class Pack
39         {
40         public:
41                 class Loader: public ObjectLoader<Pack>
42                 {
43                 public:
44                         Loader(Pack &);
45                 private:
46                         void file(const std::string &);
47                 };
48
49         private:
50                 std::string filename;
51                 IO::Seekable *io;
52                 unsigned base_offset;
53                 std::list<File> files;
54
55         public:
56                 Pack(IO::Seekable *, const std::string &);
57
58                 const std::string &get_filename() const { return filename; }
59                 IO::Seekable *get_io() const { return io; }
60                 unsigned get_base_offset() const { return base_offset; }
61
62                 void collect_files(FileMap &, const std::string &) const;
63         };
64
65         class File
66         {
67         public:
68                 class Loader: public ObjectLoader<File>
69                 {
70                 public:
71                         Loader(File &);
72                 private:
73                         virtual void finish();
74                         void object(const std::string &, const std::string &);
75                 };
76
77         private:
78                 const Pack &pack;
79                 std::string filename;
80                 unsigned offset;
81                 unsigned length;
82                 bool collection;
83                 std::list<Object> objects;
84                 bool loaded;
85
86         public:
87                 File(const Pack &, const std::string &);
88
89                 RefPtr<IO::Seekable> open() const;
90                 const std::string &get_filename() const { return filename; }
91                 FileInfo get_info() const;
92                 std::string get_full_name() const;
93                 bool is_collection() const { return collection; }
94
95                 void set_loaded();
96                 bool is_loaded() const { return loaded; }
97
98                 void collect_objects(ObjectMap &) const;
99         };
100
101         class Object
102         {
103         private:
104                 File &file;
105                 std::string name;
106                 std::string keyword;
107
108         public:
109                 Object(File &, const std::string &, const std::string &);
110
111                 File &get_file() const { return file; }
112                 const std::string &get_name() const { return name; }
113                 const std::string &get_keyword() const { return keyword; }
114         };
115
116         std::list<Pack> packs;
117         FileMap files;
118         ObjectMap objects;
119
120 public:
121         /// Adds a pack file to load objects from.  The index is read immediately.
122         void add_pack_file(const std::string &);
123
124         /** Adds a pack file with a regex to filter logical files.  The index is
125         read on the first call; subsequent calls will use cached data. */
126         void add_pack_file(const std::string &, const std::string &);
127
128         /** Adds a pack from an existing seekable I/O object.  The same object is
129         used for all accesses to the pack, so it must not be deleted before the
130         PackSource. */
131         void add_pack_io(IO::Seekable &, const std::string & = std::string());
132
133         /** Adds a pack from an I/O object with a regex to filter logical files.
134         Multiple filters for the same I/O object can be added with repeated calls. */
135         void add_pack_io(IO::Seekable &, const std::string &, const std::string &);
136
137 private:
138         void add_pack(IO::Seekable *, const std::string &, const std::string &);
139
140 public:
141         /// Returns information about the files in the pack.
142         std::list<FileInfo> list_files() const;
143
144         virtual bool is_loadable(const CollectionItemTypeBase &, const std::string &) const;
145         virtual NameList get_names(const CollectionItemTypeBase &) const;
146         virtual void load(Collection &, const CollectionItemTypeBase &, const std::string &) const;
147         virtual IO::Seekable *open(const std::string &) const;
148 };
149
150 } // namespace DataFile
151 } // namespace Msp
152
153 #endif