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