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