X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fcollection.cpp;h=f86adf65c71ace3370e7a57537eaa4fe6cd8243a;hb=fbf76ed98dbd2cca6785efe2dd489d717fa5dce6;hp=bf1c5edc211e93b33f1dacc833e0ac1a38657a5e;hpb=b1bc25649c1f22abf940a807d934f1e9bb780c28;p=libs%2Fdatafile.git diff --git a/source/collection.cpp b/source/collection.cpp index bf1c5ed..f86adf6 100644 --- a/source/collection.cpp +++ b/source/collection.cpp @@ -1,3 +1,4 @@ +#include #include "collection.h" using namespace std; @@ -5,17 +6,161 @@ using namespace std; namespace Msp { namespace DataFile { +Collection::Collection(): + fallback(0) +{ } + Collection::~Collection() { for(TypeList::iterator i = types.begin(); i!=types.end(); ++i) delete *i; } -void Collection::add_source(CollectionSource &s) +void Collection::add_var(const string &name, const CollectionItemTypeBase *type, const Variant &var) +{ + insert_unique(items, name, var); + if(type) + type->notify_item(*this, name, var); +} + +const Variant &Collection::get_var(const string &name, const CollectionItemTypeBase *type) +{ + const Variant *var = find_var(name, type); + if(var) + return *var; + + throw key_error(name); +} + +const Variant *Collection::find_var(const string &name, const CollectionItemTypeBase *type) +{ + ItemMap::iterator i = items.find(name); + if(i!=items.end()) + return &i->second; + + if(type) + { + bool loaded = false; + if(type->can_create()) + { + type->create_item(*this, name); + loaded = items.count(name); + } + for(SourceList::iterator j=sources.begin(); (!loaded && j!=sources.end()); ++j) + { + (*j)->load(*this, *type, name); + loaded = items.count(name); + } + if(!loaded && fallback) + if(CollectionItemTypeBase *fb_type = fallback->get_type(*type)) + if(fallback->get_status(name, *fb_type)) + return fallback->find_var(name, fb_type); + } + + i = items.find(name); + return (i!=items.end() ? &i->second : 0); +} + +void Collection::gather_items(vector *vars, list *names, const CollectionItemTypeBase &type, bool include_sources) const +{ + for(ItemMap::const_iterator i=items.begin(); i!=items.end(); ++i) + if(type.check_item_type(i->second)) + { + if(vars) + vars->push_back(&i->second); + if(names) + names->push_back(i->first); + } + + if(include_sources && names) + gather_names_from_sources(*names, type); +} + +unsigned Collection::get_status(const string &name, const CollectionItemTypeBase &type) const +{ + ItemMap::const_iterator i = items.find(name); + if(i==items.end()) + { + for(SourceList::const_iterator j=sources.begin(); j!=sources.end(); ++j) + if((*j)->is_loadable(type, name)) + return 2; + if(fallback) + if(CollectionItemTypeBase *fb_type = fallback->get_type(type)) + return fallback->get_status(name, *fb_type); + return 0; + } + + return type.check_item_type(i->second); +} + +CollectionItemTypeBase *Collection::get_type(const CollectionItemTypeBase &type) const +{ + for(TypeList::const_iterator j=types.begin(); j!=types.end(); ++j) + if((*j)->is_same_type(type)) + return *j; + return 0; +} + +CollectionItemTypeBase *Collection::get_type_for_item(const Variant &var) const +{ + for(TypeList::const_iterator i=types.begin(); i!=types.end(); ++i) + if((*i)->check_item_type(var)) + return *i; + return 0; +} + +void Collection::add_source(const CollectionSource &s) { sources.push_back(&s); } +IO::Seekable *Collection::open_raw(const string &name) const +{ + for(SourceList::const_iterator i=sources.begin(); i!=sources.end(); ++i) + if(IO::Seekable *io = (*i)->open(name)) + return io; + + return 0; +} + +void Collection::gather_names_from_sources(list &names, const CollectionItemTypeBase &type) const +{ + set new_names; + for(SourceList::const_iterator i=sources.begin(); i!=sources.end(); ++i) + { + std::list available_names = (*i)->get_names(type); + for(std::list::iterator j=available_names.begin(); j!=available_names.end(); ++j) + if(!items.count(*j)) + new_names.insert(*j); + } + names.insert(names.end(), new_names.begin(), new_names.end()); +} + +void Collection::load_items_from_sources(const CollectionItemTypeBase &type) +{ + for(SourceList::const_iterator i=sources.begin(); i!=sources.end(); ++i) + { + std::list available_names = (*i)->get_names(type); + for(std::list::iterator j=available_names.begin(); j!=available_names.end(); ++j) + if(!items.count(*j)) + { + bool loaded = false; + if(type.can_create()) + { + type.create_item(*this, *j); + loaded = items.count(*j); + } + if(!loaded) + (*i)->load(*this, type, *j); + } + } +} + +void Collection::set_fallback(Collection *f) +{ + fallback = f; +} + Collection::Loader::Loader(Collection &c): coll(c) @@ -25,13 +170,10 @@ Collection::Loader::Loader(Collection &c): } -CollectionItemTypeBase::CollectionItemTypeBase(): - tag(0) -{ } - CollectionItemTypeBase::~CollectionItemTypeBase() { - delete tag; + for(vector::iterator i=extractors.begin(); i!=extractors.end(); ++i) + delete *i; } void CollectionItemTypeBase::set_keyword(const string &k)