Make opus_packet_tick_count a common function
[lsnes.git] / src / library / settings.cpp
blobb16cbcceaf646a5724b2a21e260752dcbdd25b2c
1 #include "globalwrap.hpp"
2 #include "register-queue.hpp"
3 #include "settings.hpp"
4 #include "string.hpp"
6 #include <set>
7 #include <map>
8 #include <sstream>
9 #include <iostream>
11 namespace
13 struct pending_registration
15 setting_group* group;
16 std::string name;
17 setting* toreg;
20 typedef register_queue<setting_group, setting> regqueue_t;
23 setting_listener::~setting_listener() throw()
27 setting_group::setting_group() throw(std::bad_alloc)
29 regqueue_t::do_ready(*this, true);
32 setting_group::~setting_group() throw()
34 regqueue_t::do_ready(*this, false);
37 setting* setting_group::get_by_name(const std::string& name)
39 umutex_class h(lock);
40 if(!settings.count(name))
41 throw std::runtime_error("No such setting '" + name + "'");
42 return settings[name];
45 void setting_group::set(const std::string& _setting, const std::string& value) throw(std::bad_alloc,
46 std::runtime_error)
48 setting* tochange;
49 try {
50 tochange = get_by_name(_setting);
51 } catch(...) {
52 if(storage_mode)
53 invalid_values[_setting] = value;
54 throw;
56 try {
58 setting::lock_holder lck(tochange);
59 tochange->set(value);
60 invalid_values.erase(_setting);
62 std::set<setting_listener*> l;
64 umutex_class h(lock);
65 for(auto i : listeners)
66 l.insert(i);
68 for(auto i : l)
69 i->changed(*this, _setting, value);
70 } catch(std::bad_alloc& e) {
71 throw;
72 } catch(std::exception& e) {
73 if(storage_mode)
74 invalid_values[_setting] = value;
75 throw std::runtime_error("Can't set setting '" + _setting + "': " + e.what());
79 bool setting_group::blankable(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
81 setting* tochange = get_by_name(_setting);
82 try {
84 setting::lock_holder lck(tochange);
85 return tochange->blank(false);
87 } catch(...) {
88 return false;
92 void setting_group::blank(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
94 setting* tochange = get_by_name(_setting);
95 try {
97 setting::lock_holder lck(tochange);
98 if(!tochange->blank(true))
99 throw std::runtime_error("This setting can't be cleared");
100 invalid_values.erase(_setting);
102 std::set<setting_listener*> l;
104 umutex_class h(lock);
105 for(auto i : listeners)
106 l.insert(i);
108 for(auto i : l)
109 i->blanked(*this, _setting);
110 } catch(std::bad_alloc& e) {
111 throw;
112 } catch(std::exception& e) {
113 throw std::runtime_error("Can't clear setting '" + _setting + "': " + e.what());
117 std::string setting_group::get(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
119 setting* tochange = get_by_name(_setting);
121 setting::lock_holder lck(tochange);
122 return tochange->get();
126 bool setting_group::is_set(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
128 setting* tochange = get_by_name(_setting);
130 setting::lock_holder lck(tochange);
131 return tochange->is_set();
135 std::set<std::string> setting_group::get_settings_set() throw(std::bad_alloc)
137 umutex_class(lock);
138 std::set<std::string> r;
139 for(auto i : settings)
140 r.insert(i.first);
141 return r;
144 void setting_group::set_storage_mode(bool enable) throw()
146 storage_mode = enable;
149 std::map<std::string, std::string> setting_group::get_invalid_values() throw(std::bad_alloc)
151 umutex_class(lock);
152 return invalid_values;
155 void setting_group::add_listener(struct setting_listener& listener) throw(std::bad_alloc)
157 umutex_class(lock);
158 listeners.insert(&listener);
161 void setting_group::remove_listener(struct setting_listener& listener) throw(std::bad_alloc)
163 umutex_class(lock);
164 listeners.erase(&listener);
167 void setting_group::do_register(const std::string& name, setting& _setting) throw(std::bad_alloc)
169 umutex_class(lock);
170 settings[name] = &_setting;
173 void setting_group::do_unregister(const std::string& name) throw(std::bad_alloc)
175 umutex_class(lock);
176 settings.erase(name);
179 setting::setting(setting_group& group, const std::string& name) throw(std::bad_alloc)
180 : in_group(group)
182 regqueue_t::do_register(group, settingname = name, *this);
185 setting::~setting() throw()
187 regqueue_t::do_unregister(in_group, settingname);
190 bool setting::blank(bool really) throw(std::bad_alloc, std::runtime_error)
192 return false;
195 numeric_setting::numeric_setting(setting_group& group, const std::string& sname, int32_t minv, int32_t maxv,
196 int32_t dflt) throw(std::bad_alloc)
197 : setting(group, sname)
199 minimum = minv;
200 maximum = maxv;
201 value = dflt;
204 bool numeric_setting::is_set() throw()
206 return true;
209 void numeric_setting::set(const std::string& _value) throw(std::bad_alloc, std::runtime_error)
211 int32_t v = parse_value<int32_t>(_value);
212 if(v < minimum || v > maximum) {
213 std::ostringstream x;
214 x << "Value out of range (" << minimum << " - " << maximum << ")";
215 throw std::runtime_error(x.str());
217 value = v;
220 std::string numeric_setting::get() throw(std::bad_alloc)
222 std::ostringstream x;
223 x << value;
224 return x.str();
227 numeric_setting::operator int32_t() throw()
229 lock_holder lck(this);
230 return value;
233 boolean_setting::boolean_setting(setting_group& group, const std::string& sname, bool dflt) throw(std::bad_alloc)
234 : setting(group, sname)
236 value = dflt;
239 bool boolean_setting::is_set() throw()
241 return true;
244 void boolean_setting::set(const std::string& v) throw(std::bad_alloc, std::runtime_error)
246 switch(string_to_bool(v)) {
247 case 1:
248 value = true;
249 break;
250 case 0:
251 value = false;
252 break;
253 default:
254 throw std::runtime_error("Invalid value for boolean setting");
258 std::string boolean_setting::get() throw(std::bad_alloc)
260 if(value)
261 return "true";
262 else
263 return "false";
266 boolean_setting::operator bool() throw()
268 lock_holder lck(this);
269 return value;
272 path_setting::path_setting(setting_group& group, const std::string& sname) throw(std::bad_alloc)
273 : setting(group, sname)
275 path = ".";
276 _default = true;
279 bool path_setting::blank(bool really) throw(std::bad_alloc, std::runtime_error)
281 if(!really)
282 return true;
283 path = ".";
284 _default = true;
285 return true;
288 bool path_setting::is_set() throw()
290 return !_default;
293 void path_setting::set(const std::string& value) throw(std::bad_alloc, std::runtime_error)
295 if(value == "") {
296 path = ".";
297 _default = true;
298 } else {
299 path = value;
300 _default = false;
304 std::string path_setting::get() throw(std::bad_alloc)
306 return path;
309 path_setting::operator std::string()
311 lock_holder lck(this);
312 return path;