X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fcollection.h;h=aa3c18a0fcc1a5e27f5d4ddc1278b58e65904877;hb=fbf76ed98dbd2cca6785efe2dd489d717fa5dce6;hp=d0e8a1a8bb9b25c636ab23a8c1e4bbdcfa5c04a7;hpb=465ac6c7ceda80ce7e2f6e3f7b6901ce0921406e;p=libs%2Fdatafile.git diff --git a/source/collection.h b/source/collection.h index d0e8a1a..aa3c18a 100644 --- a/source/collection.h +++ b/source/collection.h @@ -3,6 +3,7 @@ #include #include +#include #include #include "collectionsource.h" #include "loader.h" @@ -49,7 +50,7 @@ that are not present. Items retrieted from the fallback collection are shared between the collections, and are only deleted when all collections in the chain have been destroyed. */ -class Collection +class Collection: private NonCopyable { public: /** @@ -91,8 +92,6 @@ private: SourceList sources; Collection *fallback; - Collection(const Collection &); - Collection &operator=(const Collection &); public: Collection(); virtual ~Collection(); @@ -105,10 +104,11 @@ public: if(!item) throw std::invalid_argument("Collection::add(item)"); - RefPtr::Type> ptr(item); + typedef typename RemoveConst::Type NCT; + RefPtr ptr(item); try { - insert_unique(items, name, ptr); + add_var(name, get_type(name), ptr); } catch(...) { @@ -135,8 +135,28 @@ public: return extract(get_var(name, get_type(name))); } + /** Finds a typed object in the collection. Returns null if the name does + not exist. Throws if the name exists but the object is of an incorrect + type. */ + template + T *find(const std::string &name) const + { + ItemMap::const_iterator i = items.find(name); + return (i!=items.end() ? extract::Type>(i->second) : 0); + } + + template + T *find(const std::string &name) + { + typedef typename RemoveConst::Type NCT; + const Variant *var = find_var(name, get_type(name)); + return (var ? &extract(*var) : 0); + } + private: + void add_var(const std::string &, const CollectionItemTypeBase *, const Variant &); const Variant &get_var(const std::string &, const CollectionItemTypeBase *); + const Variant *find_var(const std::string &, const CollectionItemTypeBase *); template T &extract(const Variant &var) const; @@ -279,10 +299,6 @@ public: object when done with it. */ IO::Seekable *open_raw(const std::string &) const; -protected: - // Deprecated. Use open_raw instead. - DEPRECATED IO::Seekable *open_from_sources(const std::string &n) { return open_raw(n); } - private: void gather_names_from_sources(std::list &, const CollectionItemTypeBase &) const; @@ -349,6 +365,7 @@ public: virtual bool can_create() const = 0; virtual void create_item(Collection &, const std::string &) const = 0; virtual void load_item(Collection &, Parser &, const std::string &) const = 0; + virtual void notify_item(Collection &, const std::string &, const Variant &) const = 0; template bool can_extract() const @@ -398,6 +415,26 @@ private: { return (dynamic_cast(coll).*func)(name); } }; + struct NotifyeeBase + { + virtual ~NotifyeeBase() { } + + virtual void notify(Collection &, const std::string &, T &) const = 0; + }; + + template + struct Notifyee: NotifyeeBase + { + typedef void (C::*FuncPtr)(const std::string &, T &); + + FuncPtr func; + + Notifyee(FuncPtr f): func(f) { } + + virtual void notify(Collection &coll, const std::string &name, T &item) const + { (dynamic_cast(coll).*func)(name, item); } + }; + template struct Extractor: CollectionItemTypeBase::Extractor { @@ -406,6 +443,7 @@ private: }; CreatorBase *creat; + std::vector notif; public: CollectionItemType(): @@ -415,6 +453,8 @@ public: ~CollectionItemType() { delete creat; + for(typename std::vector::const_iterator i=notif.begin(); i!=notif.end(); ++i) + delete *i; } /** Sets a datafile keyword for this item type. The Collection's loader @@ -458,6 +498,13 @@ public: return *this; } + template + CollectionItemType ¬ify(void (C::*func)(const std::string &, T &)) + { + notif.push_back(new Notifyee(func)); + return *this; + } + virtual bool is_same_type(const CollectionItemTypeBase &other) const { return dynamic_cast *>(&other); } @@ -483,6 +530,13 @@ public: { throw std::runtime_error("this type cannot be loaded"); } + + virtual void notify_item(Collection &coll, const std::string &name, const Variant &var) const + { + RefPtr obj = var.value >(); + for(typename std::vector::const_iterator i=notif.begin(); i!=notif.end(); ++i) + (*i)->notify(coll, name, *obj); + } };