/* $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 "item.h"
#include "loader.h"
namespace Msp {
*/
struct ItemKeywordBase
{
+ virtual ~ItemKeywordBase() { }
virtual void add_to_loader(Loader &) const { };
};
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>
ItemKeywordSeq keywords;
ItemCreatorSeq creators;
+ Collection(const Collection &);
+ Collection &operator=(const Collection &);
public:
+ Collection() { }
virtual ~Collection();
/**
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;
}
/**
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;
}
/**
{
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.