From: Mikko Rasa Date: Wed, 26 Sep 2012 19:18:24 +0000 (+0300) Subject: Give DirectoryCollection the ability to add files as future objects X-Git-Url: http://git.tdb.fi/?p=libs%2Fdatafile.git;a=commitdiff_plain;h=495920e971324d29bd4933b8a319fb5668ca5562 Give DirectoryCollection the ability to add files as future objects --- diff --git a/source/collection.cpp b/source/collection.cpp index d52ee22..a16ae5a 100644 --- a/source/collection.cpp +++ b/source/collection.cpp @@ -1,5 +1,7 @@ #include "collection.h" +using namespace std; + namespace Msp { namespace DataFile { @@ -9,6 +11,22 @@ Collection::~Collection() delete *i; } +void Collection::add_future(const std::string &name) +{ + if(items.count(name)) + throw key_error(typeid(ItemMap)); + + for(TypeList::const_iterator i=types.begin(); i!=types.end(); ++i) + if((*i)->match_name(name)) + { + items.insert(ItemMap::value_type(name, (*i)->create_future())); + return; + } + + /* XXX throw something? If we do, DirectoryCollection needs some way to + check if a name matches any item type. */ +} + Collection::Loader::Loader(Collection &c): coll(c) @@ -27,5 +45,25 @@ CollectionItemTypeBase::~CollectionItemTypeBase() delete tag; } +void CollectionItemTypeBase::set_keyword(const string &k) +{ + kwd = k; + if(suffixes.empty()) + add_suffix("."+kwd); +} + +void CollectionItemTypeBase::add_suffix(const string &s) +{ + suffixes.push_back(s); +} + +bool CollectionItemTypeBase::match_name(const string &name) const +{ + for(vector::const_iterator i=suffixes.begin(); i!=suffixes.end(); ++i) + if(name.size()>i->size() && !name.compare(name.size()-i->size(), string::npos, *i)) + return true; + return false; +} + } // namespace DataFile } // namespace Msp diff --git a/source/collection.h b/source/collection.h index 0595aac..66c50fe 100644 --- a/source/collection.h +++ b/source/collection.h @@ -137,6 +137,8 @@ protected: insert_unique(items, name, ptr); } + void add_future(const std::string &name); + public: /// Gets a typed object from the collection. template @@ -302,15 +304,20 @@ protected: { }; std::string kwd; + std::vector suffixes; TagBase *tag; CollectionItemTypeBase(); public: virtual ~CollectionItemTypeBase(); + void set_keyword(const std::string &); + void add_suffix(const std::string &); virtual void add_to_loader(Collection::Loader &) const = 0; virtual bool can_create() const = 0; virtual void create_item(Collection &, const std::string &) const = 0; + bool match_name(const std::string &) const; + virtual Variant create_future() const = 0; template bool check_type() const @@ -360,6 +367,7 @@ private: virtual ~StoreBase() { } virtual void store(Collection &, const std::string &, T *) = 0; + virtual Variant create_future() const = 0; virtual void add_to_loader(Collection::Loader &, const std::string &) = 0; }; @@ -371,6 +379,9 @@ private: virtual void store(Collection &coll, const std::string &name, T *obj) { coll.add(name, static_cast(obj)); } + virtual Variant create_future() const + { return RefPtr(0); } + virtual void add_to_loader(Collection::Loader &loader, const std::string &kwd) { Collection::Loader::Add::add(loader, kwd); } }; @@ -394,7 +405,17 @@ public: item's name. */ CollectionItemType &keyword(const std::string &k) { - kwd = k; + set_keyword(k); + return *this; + } + + /** Adds a suffix that is used to match names when looking for future + objects. There is no implied separator; a name matches if it ends with the + suffix. If a keyword is defined before any suffixes, then "."+keyword is + added as a suffix. */ + CollectionItemType &suffix(const std::string &s) + { + add_suffix(s); return *this; } @@ -438,6 +459,9 @@ public: if(obj) store->store(coll, name, obj); } + + virtual Variant create_future() const + { return store->create_future(); } }; diff --git a/source/directorycollection.cpp b/source/directorycollection.cpp index 25808d6..4413ca5 100644 --- a/source/directorycollection.cpp +++ b/source/directorycollection.cpp @@ -1,3 +1,4 @@ +#include #include #include "directorycollection.h" @@ -22,6 +23,16 @@ void DirectoryCollection::add_directory(const FS::Path &d) dirs.push_back(d); } +void DirectoryCollection::load_names() +{ + for(list::const_iterator i=dirs.begin(); i!=dirs.end(); ++i) + { + list names = FS::list_files(*i); + for(list::const_iterator j=names.begin(); j!=names.end(); ++j) + add_future(*j); + } +} + bool DirectoryCollection::lookup_file(const string &name, FS::Path &result) const { for(list::const_iterator i=dirs.begin(); i!=dirs.end(); ++i) diff --git a/source/directorycollection.h b/source/directorycollection.h index e9a9463..cbaffd6 100644 --- a/source/directorycollection.h +++ b/source/directorycollection.h @@ -25,6 +25,10 @@ protected: void set_directory(const FS::Path &); void add_directory(const FS::Path &); + /** Examines the names of files in the designated directories and adds any + applicable ones as future objects. */ + void load_names(); + template CollectionItemType &add_type() {