]> git.tdb.fi Git - libs/datafile.git/blobdiff - source/collection.h
Some more code reformatting
[libs/datafile.git] / source / collection.h
index 3a3b90e57398ec3ff99221b09f85143a37330f02..42dc2c90dd519c7f919742c42aaf1ff40eeee5f7 100644 (file)
@@ -1,13 +1,14 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2006  Mikko Rasa, Mikkosoft Productions
+Copyright © 2006-2008  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
 #ifndef MSP_DATAFILE_COLLECTION_H_
 #define MSP_DATAFILE_COLLECTION_H_
 
+#include <msp/core/meta.h>
 #include <msp/core/refptr.h>
 #include "loader.h"
 
@@ -64,6 +65,7 @@ private:
        */
        struct ItemKeywordBase
        {
+               virtual ~ItemKeywordBase() { }
                virtual void add_to_loader(Loader &) const { };
        };
 
@@ -97,19 +99,22 @@ private:
                virtual ~ItemCreatorBase() { }
 
                template<typename S>
-               S *create(Collection &coll, const std::string &name)
+               bool create(Collection &coll, const std::string &name, S *&ptr)
                {
                        ItemCreatorBridge<S> *creator=dynamic_cast<ItemCreatorBridge<S> *>(this);
                        if(creator)
-                               return creator->create(coll, name);
-                       return 0;
+                       {
+                               ptr=creator->create(coll, name);
+                               return true;
+                       }
+                       return false;
                }
        };
 
        template<typename S>
        struct ItemCreatorBridge: public ItemCreatorBase
        {
-               virtual S *create(Collection &, const std::string &) const =0;
+               virtual S *create(Collection &, const std::string &) const = 0;
        };
 
        template<typename T, typename S, typename C>
@@ -167,7 +172,10 @@ private:
        ItemKeywordSeq keywords;
        ItemCreatorSeq creators;
 
+       Collection(const Collection &);
+       Collection &operator=(const Collection &);
 public:
+       Collection() { }
        virtual ~Collection();
 
        /**
@@ -178,26 +186,28 @@ public:
        void add(const std::string &name, T *d)
        {
                if(items.count(name))
-                       throw KeyError("Duplicate key '"+name+"' in collection");
+                       throw KeyError("Duplicate key in collection", name);
 
-               items[name]=new Item<T>(d);
+               items[name]=new Item<typename RemoveConst<T>::Type>(d);
        }
 
        /**
        Gets an object of a specific type from the collection.
        */
        template<typename T>
-       T &get(const std::string &name) const
+       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");
+                       throw KeyError("Item not found in collection", name);
 
-               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");
+                       throw TypeError("Type mismatch on item '"+name+"'");
 
-               return *item->data;
+               return item->data;
        }
 
        /**
@@ -206,26 +216,31 @@ public:
        invoked.
        */
        template<typename T>
-       T &get(const std::string &name)
+       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))
+                       {
+                               NCT *d=0;
+                               if((*j)->create(*this, name, d))
                                {
                                        // We already know that the item didn't exist yet
-                                       items[name]=new Item<T>(d);
-                                       return *d;
+                                       items[name]=new Item<NCT>(d);
+                                       return d;
                                }
-                       throw KeyError("Item '"+name+"' not found in collection");
+                       }
+                       throw KeyError("Item not found in collection", name);
                }
 
-               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");
+                       throw TypeError("Type mismatch on item '"+name+"'");
 
-               return *item->data;
+               return item->data;
        }
 
        /**
@@ -236,17 +251,48 @@ 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.
        */
        bool contains(const std::string &n) const;
 
+       /**
+       Returns the name of an item in the collection.
+       */
+       template<typename T>
+       const std::string &get_name(T *d) const
+       {
+               typedef typename RemoveConst<T>::Type NCT;
+
+               for(ItemMap::const_iterator i=items.begin(); i!=items.end(); ++i)
+                       if(Item<NCT> *item=dynamic_cast<Item<NCT> *>(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.