X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fpackcollection.h;fp=source%2Fpackcollection.h;h=946271a012a308cdbe06310156d062ee81e0db68;hb=57d8b8c6f07808efdd1b9647d12447c177ce1e7d;hp=0000000000000000000000000000000000000000;hpb=348a6d9ca1a9b3838ff8c6da5050f61b2c74d010;p=libs%2Fdatafile.git diff --git a/source/packcollection.h b/source/packcollection.h new file mode 100644 index 0000000..946271a --- /dev/null +++ b/source/packcollection.h @@ -0,0 +1,153 @@ +#ifndef MSP_DATAFILE_PACKCOLLECTION_H_ +#define MSP_DATAFILE_PACKCOLLECTION_H_ + +#include "collection.h" +#include "objectloader.h" + +namespace Msp { +namespace DataFile { + +/** +A collection class that loads data from pack files. As opposed to plain +collection files, pack files are composed from a number of logical files. They +also contain a directory with a list of objects contained in the pack and which +logical files they are in. This allows the pack to be loaded in a piecewise +manner instead of all at once. + +It's possible for a pack file to contain plain collection files as well. When +an object from such a file is requested, the entire sub-collection it is stored +in is loaded. +*/ +class PackCollection: public Collection +{ +private: + class File; + struct Object; + + typedef std::map ObjectMap; + + class Pack + { + public: + class Loader: public ObjectLoader + { + public: + Loader(Pack &); + private: + void file(const std::string &); + }; + + private: + std::string filename; + unsigned base_offset; + std::list files; + + public: + Pack(const std::string &); + + const std::string &get_filename() const { return filename; } + unsigned get_base_offset() const { return base_offset; } + + void collect_objects(ObjectMap &) const; + }; + + class File + { + public: + class Loader: public ObjectLoader + { + public: + Loader(File &); + private: + virtual void finish(); + void object(const std::string &, const std::string &); + }; + + private: + const Pack &pack; + std::string filename; + unsigned offset; + unsigned length; + bool collection; + std::list objects; + bool loaded; + + public: + File(const Pack &, const std::string &); + + RefPtr open() const; + const std::string &get_filename() const { return filename; } + std::string get_full_name() const; + bool is_collection() const { return collection; } + + void set_loaded(); + bool is_loaded() const { return loaded; } + + void collect_objects(ObjectMap &) const; + }; + + class Object + { + private: + File &file; + std::string name; + std::string keyword; + + public: + Object(File &, const std::string &, const std::string &); + + File &get_file() const { return file; } + const std::string &get_name() const { return name; } + const std::string &get_keyword() const { return keyword; } + }; + + std::list packs; + ObjectMap objects; + +public: + /** Adds a pack file to the collection. The directory is read immediately, + and packed objects are loaded as they are needed. */ + void add_pack_file(const std::string &); + +protected: + template + CollectionItemType &add_type() + { + return Collection::add_type().creator(&PackCollection::create); + } + +private: + template + T *create(const std::string &name) + { + ObjectMap::iterator i = objects.find(name); + if(i==objects.end()) + return 0; + + File &file = i->second->get_file(); + if(file.is_loaded()) + return 0; + file.set_loaded(); + + RefPtr in = file.open(); + Parser parser(*in, file.get_full_name()); + if(file.is_collection()) + { + Loader ldr(*this); + ldr.load(parser); + return 0; + } + else + { + RefPtr item = new T; + ItemLoader ldr(*item, *this); + ldr.load(parser); + return item.release(); + } + } +}; + +} // namespace DataFile +} // namespace Msp + +#endif