]> git.tdb.fi Git - libs/datafile.git/blob - source/packsource.cpp
Redesign automatic object loading
[libs/datafile.git] / source / packsource.cpp
1 #include <msp/strings/format.h>
2 #include "collection.h"
3 #include "packsource.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace DataFile {
9
10 void PackSource::add_pack_file(const string &fn)
11 {
12         packs.push_back(Pack(fn));
13         Pack &pack = packs.back();
14         DataFile::load(pack, fn);
15
16         pack.collect_objects(objects);
17 }
18
19 bool PackSource::is_loadable(const CollectionItemTypeBase &type, const string &name) const
20 {
21         ObjectMap::const_iterator i = objects.find(name);
22         if(i==objects.end())
23                 return false;
24
25         // If the object has a keyword, it must match that of the type
26         if(!i->second->get_keyword().empty() && i->second->get_keyword()!=type.get_keyword())
27                 return false;
28
29         return true;
30 }
31
32 CollectionSource::NameList PackSource::get_names(const CollectionItemTypeBase &type) const
33 {
34         NameList names;
35         for(ObjectMap::const_iterator i=objects.begin(); i!=objects.end(); ++i)
36         {
37                 if(!i->second->get_keyword().empty())
38                 {
39                         if(i->second->get_keyword()!=type.get_keyword())
40                                 continue;
41                 }
42                 else if(!type.match_name(i->first))
43                         continue;
44
45                 names.push_back(i->first);
46         }
47
48         return names;
49 }
50
51 void PackSource::load(Collection &coll, const CollectionItemTypeBase &type, const string &name) const
52 {
53         ObjectMap::const_iterator i = objects.find(name);
54         if(i==objects.end())
55                 return;
56
57         File &file = i->second->get_file();
58         if(file.is_loaded())
59                 return;
60         file.set_loaded();
61
62         RefPtr<IO::Base> in = file.open();
63         Parser parser(*in, file.get_full_name());
64         if(file.is_collection())
65         {
66                 Collection::Loader ldr(coll);
67                 ldr.load(parser);
68         }
69         else
70                 type.load_item(coll, parser, name);
71 }
72
73
74 PackSource::Pack::Pack(const string &fn):
75         filename(fn),
76         base_offset(0)
77 { }
78
79 void PackSource::Pack::collect_objects(ObjectMap &objs) const
80 {
81         for(list<File>::const_iterator i=files.begin(); i!=files.end(); ++i)
82                 i->collect_objects(objs);
83 }
84
85
86 PackSource::File::File(const Pack &p, const string &fn):
87         pack(p),
88         filename(fn),
89         offset(0),
90         length(0),
91         collection(false),
92         loaded(false)
93 { }
94
95 RefPtr<IO::Base> PackSource::File::open() const
96 {
97         RefPtr<IO::BufferedFile> io_file = new IO::BufferedFile(pack.get_filename());
98         io_file->seek(pack.get_base_offset()+offset, IO::S_BEG);
99         return io_file;
100 }
101
102 string PackSource::File::get_full_name() const
103 {
104         return format("%s/%s", pack.get_filename(), filename);
105 }
106
107 void PackSource::File::set_loaded()
108 {
109         loaded = true;
110 }
111
112 void PackSource::File::collect_objects(ObjectMap &objs) const
113 {
114         for(list<Object>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
115                 objs[i->get_name()] = &*i;
116 }
117
118
119 PackSource::Object::Object(File &f, const string &n, const string &k):
120         file(f),
121         name(n),
122         keyword(k)
123 { }
124
125
126 PackSource::Pack::Loader::Loader(Pack &p):
127         ObjectLoader<Pack>(p)
128 {
129         add("file",        &Loader::file);
130         add("base_offset", &Pack::base_offset);
131 }
132
133 void PackSource::Pack::Loader::file(const string &fn)
134 {
135         obj.files.push_back(File(obj, fn));
136         load_sub(obj.files.back());
137 }
138
139
140 PackSource::File::Loader::Loader(File &f):
141         ObjectLoader<File>(f)
142 {
143         add("object", &Loader::object);
144         add("slice",  &File::offset, &File::length);
145 }
146
147 void PackSource::File::Loader::finish()
148 {
149         if(!obj.collection)
150         {
151                 PackSource::Object ob(obj, obj.filename, string());
152                 obj.objects.push_back(ob);
153         }
154 }
155
156 void PackSource::File::Loader::object(const string &name, const string &kwd)
157 {
158         obj.objects.push_back(PackSource::Object(obj, name, kwd));
159         obj.collection = true;
160 }
161
162 } // namespace DataFile
163 } // namespace Msp