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