]> git.tdb.fi Git - libs/datafile.git/blobdiff - source/packsource.cpp
Redesign automatic object loading
[libs/datafile.git] / source / packsource.cpp
diff --git a/source/packsource.cpp b/source/packsource.cpp
new file mode 100644 (file)
index 0000000..c06b270
--- /dev/null
@@ -0,0 +1,163 @@
+#include <msp/strings/format.h>
+#include "collection.h"
+#include "packsource.h"
+
+using namespace std;
+
+namespace Msp {
+namespace DataFile {
+
+void PackSource::add_pack_file(const string &fn)
+{
+       packs.push_back(Pack(fn));
+       Pack &pack = packs.back();
+       DataFile::load(pack, fn);
+
+       pack.collect_objects(objects);
+}
+
+bool PackSource::is_loadable(const CollectionItemTypeBase &type, const string &name) const
+{
+       ObjectMap::const_iterator i = objects.find(name);
+       if(i==objects.end())
+               return false;
+
+       // If the object has a keyword, it must match that of the type
+       if(!i->second->get_keyword().empty() && i->second->get_keyword()!=type.get_keyword())
+               return false;
+
+       return true;
+}
+
+CollectionSource::NameList PackSource::get_names(const CollectionItemTypeBase &type) const
+{
+       NameList names;
+       for(ObjectMap::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+       {
+               if(!i->second->get_keyword().empty())
+               {
+                       if(i->second->get_keyword()!=type.get_keyword())
+                               continue;
+               }
+               else if(!type.match_name(i->first))
+                       continue;
+
+               names.push_back(i->first);
+       }
+
+       return names;
+}
+
+void PackSource::load(Collection &coll, const CollectionItemTypeBase &type, const string &name) const
+{
+       ObjectMap::const_iterator i = objects.find(name);
+       if(i==objects.end())
+               return;
+
+       File &file = i->second->get_file();
+       if(file.is_loaded())
+               return;
+       file.set_loaded();
+
+       RefPtr<IO::Base> in = file.open();
+       Parser parser(*in, file.get_full_name());
+       if(file.is_collection())
+       {
+               Collection::Loader ldr(coll);
+               ldr.load(parser);
+       }
+       else
+               type.load_item(coll, parser, name);
+}
+
+
+PackSource::Pack::Pack(const string &fn):
+       filename(fn),
+       base_offset(0)
+{ }
+
+void PackSource::Pack::collect_objects(ObjectMap &objs) const
+{
+       for(list<File>::const_iterator i=files.begin(); i!=files.end(); ++i)
+               i->collect_objects(objs);
+}
+
+
+PackSource::File::File(const Pack &p, const string &fn):
+       pack(p),
+       filename(fn),
+       offset(0),
+       length(0),
+       collection(false),
+       loaded(false)
+{ }
+
+RefPtr<IO::Base> PackSource::File::open() const
+{
+       RefPtr<IO::BufferedFile> io_file = new IO::BufferedFile(pack.get_filename());
+       io_file->seek(pack.get_base_offset()+offset, IO::S_BEG);
+       return io_file;
+}
+
+string PackSource::File::get_full_name() const
+{
+       return format("%s/%s", pack.get_filename(), filename);
+}
+
+void PackSource::File::set_loaded()
+{
+       loaded = true;
+}
+
+void PackSource::File::collect_objects(ObjectMap &objs) const
+{
+       for(list<Object>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+               objs[i->get_name()] = &*i;
+}
+
+
+PackSource::Object::Object(File &f, const string &n, const string &k):
+       file(f),
+       name(n),
+       keyword(k)
+{ }
+
+
+PackSource::Pack::Loader::Loader(Pack &p):
+       ObjectLoader<Pack>(p)
+{
+       add("file",        &Loader::file);
+       add("base_offset", &Pack::base_offset);
+}
+
+void PackSource::Pack::Loader::file(const string &fn)
+{
+       obj.files.push_back(File(obj, fn));
+       load_sub(obj.files.back());
+}
+
+
+PackSource::File::Loader::Loader(File &f):
+       ObjectLoader<File>(f)
+{
+       add("object", &Loader::object);
+       add("slice",  &File::offset, &File::length);
+}
+
+void PackSource::File::Loader::finish()
+{
+       if(!obj.collection)
+       {
+               PackSource::Object ob(obj, obj.filename, string());
+               obj.objects.push_back(ob);
+       }
+}
+
+void PackSource::File::Loader::object(const string &name, const string &kwd)
+{
+       obj.objects.push_back(PackSource::Object(obj, name, kwd));
+       obj.collection = true;
+}
+
+} // namespace DataFile
+} // namespace Msp