]> git.tdb.fi Git - libs/datafile.git/blobdiff - source/collection.h
Use the functions from maputils.h in various places
[libs/datafile.git] / source / collection.h
index 24be69dd2f70cd07d425453b3121788b2ff60086..2d346d9a4557a72325a18ae6f89c232e5f629681 100644 (file)
@@ -1,13 +1,8 @@
-/* $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 <msp/core/meta.h>
+#include <msp/core/maputils.h>
 #include <msp/core/refptr.h>
 #include "loader.h"
 
@@ -31,14 +26,6 @@ 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.
@@ -72,6 +59,7 @@ private:
        */
        struct ItemKeywordBase
        {
+               virtual ~ItemKeywordBase() { }
                virtual void add_to_loader(Loader &) const { };
        };
 
@@ -110,7 +98,7 @@ private:
                        ItemCreatorBridge<S> *creator=dynamic_cast<ItemCreatorBridge<S> *>(this);
                        if(creator)
                        {
-                               creator->create(coll, name, ptr);
+                               ptr=creator->create(coll, name);
                                return true;
                        }
                        return false;
@@ -120,7 +108,7 @@ private:
        template<typename S>
        struct ItemCreatorBridge: public ItemCreatorBase
        {
-               virtual bool create(Collection &, const std::string &, S *&) const =0;
+               virtual S *create(Collection &, const std::string &) const = 0;
        };
 
        template<typename T, typename S, typename C>
@@ -191,10 +179,11 @@ public:
        template<typename T>
        void add(const std::string &name, T *d)
        {
-               if(items.count(name))
-                       throw KeyError("Duplicate key '"+name+"' in collection");
+               typedef typename RemoveConst<T>::Type NCT;
 
-               items[name]=new Item<typename RemoveConst<T>::Type>(d);
+               RefPtr<Item<NCT> > i=new Item<NCT>(d);
+               insert_unique(items, i.get());
+               i.release();
        }
 
        /**
@@ -205,15 +194,13 @@ public:
        {
                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");
+               ItemBase *i=get_item(items, name);
 
-               const Item<NCT> *item=dynamic_cast<const Item<NCT> *>(i->second);
+               const Item<NCT> *item=dynamic_cast<const Item<NCT> *>(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;
        }
 
        /**
@@ -226,8 +213,7 @@ public:
        {
                typedef typename RemoveConst<T>::Type NCT;
 
-               ItemMap::const_iterator i=items.find(name);
-               if(i==items.end())
+               if(!items.count(name))
                {
                        for(ItemCreatorSeq::iterator j=creators.begin(); j!=creators.end(); ++j)
                        {
@@ -236,17 +222,18 @@ public:
                                {
                                        // We already know that the item didn't exist yet
                                        items[name]=new Item<NCT>(d);
-                                       return *d;
+                                       return d;
                                }
                        }
-                       throw KeyError("Item '"+name+"' not found in collection");
                }
 
-               const Item<NCT> *item=dynamic_cast<const Item<NCT> *>(i->second);
+               ItemBase *i=get_item(items, name);
+
+               const Item<NCT> *item=dynamic_cast<const Item<NCT> *>(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;
        }
 
        /**
@@ -283,6 +270,22 @@ public:
        */
        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.