X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fcollection.h;h=2d346d9a4557a72325a18ae6f89c232e5f629681;hb=35d0da96bad97214376f18d15078e6d731e6f219;hp=e7d173d061ed7947750702d8fe1681cd2e44bcb5;hpb=1d9c21a8a301007fb242e05b69cc6390ec566273;p=libs%2Fdatafile.git diff --git a/source/collection.h b/source/collection.h index e7d173d..2d346d9 100644 --- a/source/collection.h +++ b/source/collection.h @@ -1,15 +1,9 @@ -/* $Id$ - -This file is part of libmspdatafile -Copyright © 2006 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - #ifndef MSP_DATAFILE_COLLECTION_H_ #define MSP_DATAFILE_COLLECTION_H_ +#include +#include #include -#include "item.h" #include "loader.h" namespace Msp { @@ -65,6 +59,7 @@ private: */ struct ItemKeywordBase { + virtual ~ItemKeywordBase() { } virtual void add_to_loader(Loader &) const { }; }; @@ -98,19 +93,22 @@ private: virtual ~ItemCreatorBase() { } template - S *create(Collection &coll, const std::string &name) + bool create(Collection &coll, const std::string &name, S *&ptr) { ItemCreatorBridge *creator=dynamic_cast *>(this); if(creator) - return creator->create(coll, name); - return 0; + { + ptr=creator->create(coll, name); + return true; + } + return false; } }; template struct ItemCreatorBridge: public ItemCreatorBase { - virtual S *create(Collection &, const std::string &) const =0; + virtual S *create(Collection &, const std::string &) const = 0; }; template @@ -168,7 +166,10 @@ private: ItemKeywordSeq keywords; ItemCreatorSeq creators; + Collection(const Collection &); + Collection &operator=(const Collection &); public: + Collection() { } virtual ~Collection(); /** @@ -178,27 +179,28 @@ public: template void add(const std::string &name, T *d) { - if(items.count(name)) - throw KeyError("Duplicate key '"+name+"' in collection"); + typedef typename RemoveConst::Type NCT; - items[name]=new Item(d); + RefPtr > i=new Item(d); + insert_unique(items, i.get()); + i.release(); } /** Gets an object of a specific type from the collection. */ template - T &get(const std::string &name) const + T *get(const std::string &name) const { - ItemMap::const_iterator i=items.find(name); - if(i==items.end()) - throw KeyError("Item '"+name+"' not found in collection"); + typedef typename RemoveConst::Type NCT; - const Item *item=dynamic_cast *>(i->second); + ItemBase *i=get_item(items, name); + + const Item *item=dynamic_cast *>(i); if(!item) - throw TypeError("Item '"+name+"' is not of correct type"); + throw TypeError("Type mismatch on item '"+name+"'"); - return *item->data; + return item->data; } /** @@ -207,26 +209,31 @@ public: invoked. */ template - T &get(const std::string &name) + T *get(const std::string &name) { - ItemMap::const_iterator i=items.find(name); - if(i==items.end()) + typedef typename RemoveConst::Type NCT; + + if(!items.count(name)) { for(ItemCreatorSeq::iterator j=creators.begin(); j!=creators.end(); ++j) - if(T *d=(*j)->create(*this, name)) + { + NCT *d=0; + if((*j)->create(*this, name, d)) { // We already know that the item didn't exist yet - items[name]=new Item(d); - return *d; + items[name]=new Item(d); + return d; } - throw KeyError("Item '"+name+"' not found in collection"); + } } - const Item *item=dynamic_cast *>(i->second); + ItemBase *i=get_item(items, name); + + const Item *item=dynamic_cast *>(i); if(!item) - throw TypeError("Item '"+name+"' is not of correct type"); + throw TypeError("Type mismatch on item '"+name+"'"); - return *item->data; + return item->data; } /** @@ -237,17 +244,48 @@ public: { std::list result; for(ItemMap::const_iterator i=items.begin(); i!=items.end(); ++i) - if(dynamic_cast *>(i->second)) + if(dynamic_cast::Type> *>(i->second)) result.push_back(i->first); return result; } + /** + Returns a list of objects of a specific type in the collection. + */ + template + std::list get_list() const + { + typedef typename RemoveConst::Type NCT; + + std::list result; + for(ItemMap::const_iterator i=items.begin(); i!=items.end(); ++i) + if(Item *item=dynamic_cast *>(i->second)) + result.push_back(item->data); + return result; + } + /** Checks whether a name exists in the collection. Does not care about the type of the object. */ bool contains(const std::string &n) const; + /** + Returns the name of an item in the collection. + */ + template + const std::string &get_name(T *d) const + { + typedef typename RemoveConst::Type NCT; + + for(ItemMap::const_iterator i=items.begin(); i!=items.end(); ++i) + if(Item *item=dynamic_cast *>(i->second)) + if(item->data==d) + return i->first; + + throw KeyError("Item not found in collection"); + } + protected: /** Adds a type that can be loaded from datafiles.