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