]> git.tdb.fi Git - libs/datafile.git/blob - source/collection.cpp
Use C++11 features to manipulate containers
[libs/datafile.git] / source / collection.cpp
1 #include <set>
2 #include <msp/core/algorithm.h>
3 #include "collection.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace DataFile {
9
10 Collection::Collection():
11         fallback(0)
12 { }
13
14 Collection::~Collection()
15 {
16         for(CollectionItemTypeBase *t: types)
17                 delete t;
18 }
19
20 void Collection::add_var(const string &name, const CollectionItemTypeBase *type, const Variant &var)
21 {
22         insert_unique(items, name, var);
23         if(type)
24                 type->notify_item(*this, name, var);
25 }
26
27 const Variant &Collection::get_var(const string &name, const CollectionItemTypeBase *type)
28 {
29         const Variant *var = find_var(name, type);
30         if(var)
31                 return *var;
32
33         throw key_error(name);
34 }
35
36 const Variant *Collection::find_var(const string &name, const CollectionItemTypeBase *type)
37 {
38         ItemMap::iterator i = items.find(name);
39         if(i!=items.end())
40                 return &i->second;
41
42         if(type)
43         {
44                 bool loaded = false;
45                 if(type->can_create())
46                 {
47                         type->create_item(*this, name);
48                         loaded = items.count(name);
49                 }
50                 for(auto j=sources.begin(); (!loaded && j!=sources.end()); ++j)
51                 {
52                         (*j)->load(*this, *type, name);
53                         loaded = items.count(name);
54                 }
55                 if(!loaded && fallback)
56                         if(CollectionItemTypeBase *fb_type = fallback->get_type(*type))
57                                 if(fallback->get_status(name, *fb_type))
58                                         return fallback->find_var(name, fb_type);
59         }
60
61         i = items.find(name);
62         return (i!=items.end() ? &i->second : 0);
63 }
64
65 void Collection::gather_items(vector<const Variant *> *vars, list<string> *names, const CollectionItemTypeBase &type, bool include_sources) const
66 {
67         for(const auto &kvp: items)
68                 if(type.check_item_type(kvp.second))
69                 {
70                         if(vars)
71                                 vars->push_back(&kvp.second);
72                         if(names)
73                                 names->push_back(kvp.first);
74                 }
75
76         if(include_sources && names)
77                 gather_names_from_sources(*names, type);
78 }
79
80 unsigned Collection::get_status(const string &name, const CollectionItemTypeBase &type) const
81 {
82         ItemMap::const_iterator i = items.find(name);
83         if(i==items.end())
84         {
85                 auto j = find_if(sources, [&name, &type](const CollectionSource *s){ return s->is_loadable(type, name); });
86                 if(j!=sources.end())
87                         return 2;
88                 if(fallback)
89                         if(CollectionItemTypeBase *fb_type = fallback->get_type(type))
90                                 return fallback->get_status(name, *fb_type);
91                 return 0;
92         }
93
94         return type.check_item_type(i->second);
95 }
96
97 CollectionItemTypeBase *Collection::get_type(const CollectionItemTypeBase &type) const
98 {
99         for(CollectionItemTypeBase *t: types)
100                 if(t->is_same_type(type))
101                         return t;
102         return 0;
103 }
104
105 CollectionItemTypeBase *Collection::get_type_for_item(const Variant &var) const
106 {
107         for(CollectionItemTypeBase *t: types)
108                 if(t->check_item_type(var))
109                         return t;
110         return 0;
111 }
112
113 void Collection::add_source(const CollectionSource &s)
114 {
115         sources.push_back(&s);
116 }
117
118 IO::Seekable *Collection::open_raw(const string &name) const
119 {
120         for(const CollectionSource *s: sources)
121                 if(IO::Seekable *io = s->open(name))
122                         return io;
123
124         return 0;
125 }
126
127 void Collection::gather_names_from_sources(list<string> &names, const CollectionItemTypeBase &type) const
128 {
129         set<string> new_names;
130         for(const CollectionSource *s: sources)
131                 for(const string &n: s->get_names(type))
132                         if(!items.count(n))
133                                 new_names.insert(n);
134         names.insert(names.end(), new_names.begin(), new_names.end());
135 }
136
137 void Collection::load_items_from_sources(const CollectionItemTypeBase &type)
138 {
139         for(const CollectionSource *s: sources)
140                 for(const string &n: s->get_names(type))
141                         if(!items.count(n))
142                         {
143                                 bool loaded = false;
144                                 if(type.can_create())
145                                 {
146                                         type.create_item(*this, n);
147                                         loaded = items.count(n);
148                                 }
149                                 if(!loaded)
150                                         s->load(*this, type, n);
151                         }
152 }
153
154 void Collection::set_fallback(Collection *f)
155 {
156         fallback = f;
157 }
158
159
160 Collection::Loader::Loader(Collection &c):
161         coll(c)
162 {       
163         for(const CollectionItemTypeBase *t: coll.types)
164                 t->add_to_loader(*this);
165 }
166
167
168 CollectionItemTypeBase::~CollectionItemTypeBase()
169 {
170         for(ExtractorBase *e: extractors)
171                 delete e;
172 }
173
174 void CollectionItemTypeBase::set_keyword(const string &k)
175 {
176         kwd = k;
177         if(suffixes.empty())
178                 add_suffix("."+kwd);
179 }
180
181 void CollectionItemTypeBase::add_suffix(const string &s)
182 {
183         suffixes.push_back(s);
184 }
185
186 bool CollectionItemTypeBase::match_name(const string &name) const
187 {
188         for(const string &s: suffixes)
189                 if(name.size()>s.size() && !name.compare(name.size()-s.size(), string::npos, s))
190                         return true;
191         return false;
192 }
193
194 } // namespace DataFile
195 } // namespace Msp