]> git.tdb.fi Git - libs/datafile.git/blobdiff - source/collection.h
Add Collection::get_list
[libs/datafile.git] / source / collection.h
index e7d173d061ed7947750702d8fe1681cd2e44bcb5..6ddbe6ed65c980d035b30160ad1eca18c0390f1f 100644 (file)
@@ -9,7 +9,6 @@ Distributed under the LGPL
 #define MSP_DATAFILE_COLLECTION_H_
 
 #include <msp/core/refptr.h>
-#include "item.h"
 #include "loader.h"
 
 namespace Msp {
@@ -32,6 +31,14 @@ struct NeedsCollection
        enum { result=(sizeof(f<T>(0))==sizeof(Yes)) };
 };
 
+template<typename T>
+struct RemoveConst
+{ typedef T Type; };
+
+template<typename T>
+struct RemoveConst<const T>
+{ typedef T Type; };
+
 /**
 A collection of objects that can be loaded from a datafile.  Each object is
 identified by a name, which must be unique across the entire collection.
@@ -168,7 +175,10 @@ private:
        ItemKeywordSeq keywords;
        ItemCreatorSeq creators;
 
+       Collection(const Collection &);
+       Collection &operator=(const Collection &);
 public:
+       Collection() { }
        virtual ~Collection();
 
        /**
@@ -181,7 +191,7 @@ public:
                if(items.count(name))
                        throw KeyError("Duplicate key '"+name+"' in collection");
 
-               items[name]=new Item<T>(d);
+               items[name]=new Item<typename RemoveConst<T>::Type>(d);
        }
 
        /**
@@ -190,11 +200,13 @@ public:
        template<typename T>
        T &get(const std::string &name) const
        {
+               typedef typename RemoveConst<T>::Type NCT;
+
                ItemMap::const_iterator i=items.find(name);
                if(i==items.end())
                        throw KeyError("Item '"+name+"' not found in collection");
 
-               const Item<T> *item=dynamic_cast<const Item<T> *>(i->second);
+               const Item<NCT> *item=dynamic_cast<const Item<NCT> *>(i->second);
                if(!item)
                        throw TypeError("Item '"+name+"' is not of correct type");
 
@@ -209,20 +221,22 @@ public:
        template<typename T>
        T &get(const std::string &name)
        {
+               typedef typename RemoveConst<T>::Type NCT;
+
                ItemMap::const_iterator i=items.find(name);
                if(i==items.end())
                {
                        for(ItemCreatorSeq::iterator j=creators.begin(); j!=creators.end(); ++j)
-                               if(T *d=(*j)->create<T>(*this, name))
+                               if(NCT *d=(*j)->create<NCT>(*this, name))
                                {
                                        // We already know that the item didn't exist yet
-                                       items[name]=new Item<T>(d);
+                                       items[name]=new Item<NCT>(d);
                                        return *d;
                                }
                        throw KeyError("Item '"+name+"' not found in collection");
                }
 
-               const Item<T> *item=dynamic_cast<const Item<T> *>(i->second);
+               const Item<NCT> *item=dynamic_cast<const Item<NCT> *>(i->second);
                if(!item)
                        throw TypeError("Item '"+name+"' is not of correct type");
 
@@ -237,11 +251,26 @@ public:
        {
                std::list<std::string> result;
                for(ItemMap::const_iterator i=items.begin(); i!=items.end(); ++i)
-                       if(dynamic_cast<const Item<T> *>(i->second))
+                       if(dynamic_cast<const Item<typename RemoveConst<T>::Type> *>(i->second))
                                result.push_back(i->first);
                return result;
        }
 
+       /**
+       Returns a list of objects of a specific type in the collection.
+       */
+       template<typename T>
+       std::list<T *> get_list() const
+       {
+               typedef typename RemoveConst<T>::Type NCT;
+
+               std::list<T *> result;
+               for(ItemMap::const_iterator i=items.begin(); i!=items.end(); ++i)
+                       if(Item<NCT> *item=dynamic_cast<Item<NCT> *>(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.