]> git.tdb.fi Git - libs/datafile.git/commitdiff
Support const types with Collection properly
authorMikko Rasa <tdb@tdb.fi>
Tue, 16 Oct 2007 19:48:31 +0000 (19:48 +0000)
committerMikko Rasa <tdb@tdb.fi>
Tue, 16 Oct 2007 19:48:31 +0000 (19:48 +0000)
Delete old action in Loader if a new one replaces it
Add a namespace-scope load function taking an extra argument

source/collection.h
source/loader.cpp
source/loader.h

index 3a3b90e57398ec3ff99221b09f85143a37330f02..85ca843f5e1aba552ab2c2ed26a7241d30675d0b 100644 (file)
@@ -31,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.
@@ -167,7 +175,10 @@ private:
        ItemKeywordSeq keywords;
        ItemCreatorSeq creators;
 
+       Collection(const Collection &);
+       Collection &operator=(const Collection &);
 public:
+       Collection() { }
        virtual ~Collection();
 
        /**
@@ -180,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);
        }
 
        /**
@@ -189,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");
 
@@ -208,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");
 
index cf1a5acae89dc0e4abe7583358e3926ab629277c..0a9f68f249a8d56fe76ab5ba36f5c5bfe76a57e8 100644 (file)
@@ -34,6 +34,18 @@ Loader::~Loader()
                delete i->second;
 }
 
+void Loader::add(const string &k, LoaderAction *a)
+{
+       ActionMap::iterator i=actions.find(k);
+       if(i!=actions.end())
+       {
+               delete i->second;
+               i->second=a;
+       }
+       else
+               actions[k]=a;
+}
+
 void Loader::load_statement(const Statement &st)
 {
        cur_st=&st;
index da1da3a23f462f4ed4ec77efd4b8e4c7977336e2..8d26a418a0f5d9cdec52a6ecc85160ff4ee1c4e4 100644 (file)
@@ -239,40 +239,40 @@ protected:
        */
        template<typename L>
        void add(const std::string &k, void (L::*func)())
-       { actions.insert(typename ActionMap::value_type(k, new LoaderFunc0<L>(func))); }
+       { add(k, new LoaderFunc0<L>(func)); }
 
        template<typename L, typename A0>
        void add(const std::string &k, void (L::*func)(A0))
-       { actions.insert(typename ActionMap::value_type(k, new LoaderFunc1<L, A0>(func))); }
+       { add(k, new LoaderFunc1<L, A0>(func)); }
 
        template<typename L, typename A0, typename A1>
        void add(const std::string &k, void (L::*func)(A0, A1))
-       { actions.insert(typename ActionMap::value_type(k, new LoaderFunc2<L, A0, A1>(func))); }
+       { add(k, new LoaderFunc2<L, A0, A1>(func)); }
 
        template<typename L, typename A0, typename A1, typename A2>
        void add(const std::string &k, void (L::*func)(A0, A1, A2))
-       { actions.insert(typename ActionMap::value_type(k, new LoaderFunc3<L, A0, A1, A2>(func))); }
+       { add(k, new LoaderFunc3<L, A0, A1, A2>(func)); }
 
        template<typename L, typename A0, typename A1, typename A2, typename A3>
        void add(const std::string &k, void (L::*func)(A0, A1, A2, A3))
-       { actions.insert(typename ActionMap::value_type(k, new LoaderFunc4<L, A0, A1, A2, A3>(func))); }
+       { add(k, new LoaderFunc4<L, A0, A1, A2, A3>(func)); }
 
        /**
        Adds a keyword that is loaded into a variable of the loaded object.
        */
        template<typename L, typename T0>
        void add(const std::string &k, T0 L::*p0)
-       { actions.insert(typename ActionMap::value_type(k, new LoadValue1<L, T0>(p0))); }
+       { add(k, new LoadValue1<L, T0>(p0)); }
 
        template<typename L, typename T0, typename T1>
        void add(const std::string &k, T0 L::*p0, T1 L::*p1)
-       { actions.insert(typename ActionMap::value_type(k, new LoadValue2<L, T0, T1>(p0, p1))); }
+       { add(k, new LoadValue2<L, T0, T1>(p0, p1)); }
 
        /**
        Adds a keyword that is recognized but ignored.
        */
        void add(const std::string &k)
-       { actions.insert(ActionMap::value_type(k, 0)); }
+       { add(k, 0); }
 
        /**
        Loads a sub-object from the statement being processed.  The Loader class of
@@ -328,6 +328,7 @@ private:
        ActionMap       actions;
        const Statement *cur_st;
 
+       void add(const std::string &, LoaderAction *);
        void load_statement(const Statement &st);
 };
 
@@ -346,6 +347,18 @@ void load(T &obj, const std::string &fn)
        loader.load(parser);
 }
 
+template<typename T, typename U>
+void load(T &obj, const std::string &fn, U arg)
+{
+       std::ifstream in(fn.c_str());
+       if(!in)
+               throw Exception("Couldn't open "+fn);
+
+       Parser parser(in, fn);
+       typename T::Loader loader(obj, arg);
+       loader.load(parser);
+}
+
 } // namespace DataFile
 } // namespace Msp