Reorganize the window code a bit
[lsnes.git] / generic / settings.cpp
blob8f5865755389335d29805156f7cdde0b9dea9490
1 #include "settings.hpp"
2 #include "misc.hpp"
3 #include <map>
4 #include <sstream>
5 #include "misc.hpp"
6 #include "command.hpp"
7 #include "globalwrap.hpp"
8 #include <iostream>
10 namespace
12 globalwrap<std::map<std::string, setting*>> settings;
14 function_ptr_command<tokensplitter&> set_setting("set-setting", "set a setting",
15 "Syntax: set-setting <setting> [<value>]\nSet setting to a new value. Omit <value> to set to ''\n",
16 [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
17 std::string syntax = "Syntax: set-setting <setting> [<value>]";
18 std::string settingname = t;
19 std::string settingvalue = t.tail();
20 if(settingname == "")
21 throw std::runtime_error("Setting name required.");
22 setting::set(settingname, settingvalue);
23 messages << "Setting '" << settingname << "' set to '" << settingvalue << "'"
24 << std::endl;
25 });
27 function_ptr_command<tokensplitter&> unset_setting("unset-setting", "unset a setting",
28 "Syntax: unset-setting <setting>\nTry to unset a setting. Note that not all settings can be unset\n",
29 [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
30 std::string syntax = "Syntax: unset-setting <setting>";
31 std::string settingname = t;
32 if(settingname == "" || t)
33 throw std::runtime_error("Expected setting name and nothing else");
34 setting::blank(settingname);
35 messages << "Setting '" << settingname << "' unset" << std::endl;
36 });
38 function_ptr_command<tokensplitter&> get_command("get-setting", "get value of a setting",
39 "Syntax: get-setting <setting>\nShow value of setting\n",
40 [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
41 std::string settingname = t;
42 if(settingname == "" || t.tail() != "")
43 throw std::runtime_error("Expected setting name and nothing else");
44 if(setting::is_set(settingname))
45 messages << "Setting '" << settingname << "' has value '"
46 << setting::get(settingname) << "'" << std::endl;
47 else
48 messages << "Setting '" << settingname << "' unset" << std::endl;
49 });
51 function_ptr_command<> show_settings("show-settings", "Show values of all settings",
52 "Syntax: show-settings\nShow value of all settings\n",
53 []() throw(std::bad_alloc, std::runtime_error) {
54 setting::print_all();
55 });
58 setting::setting(const std::string& name) throw(std::bad_alloc)
60 settings()[settingname = name] = this;
63 setting::~setting() throw()
65 settings().erase(settingname);
68 void setting::set(const std::string& _setting, const std::string& value) throw(std::bad_alloc, std::runtime_error)
70 if(!settings().count(_setting))
71 throw std::runtime_error("No such setting '" + _setting + "'");
72 try {
73 settings()[_setting]->set(value);
74 } catch(std::bad_alloc& e) {
75 throw;
76 } catch(std::exception& e) {
77 throw std::runtime_error("Can't set setting '" + _setting + "': " + e.what());
81 void setting::blank(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
83 if(!settings().count(_setting))
84 throw std::runtime_error("No such setting '" + _setting + "'");
85 try {
86 settings()[_setting]->blank();
87 } catch(std::bad_alloc& e) {
88 throw;
89 } catch(std::exception& e) {
90 throw std::runtime_error("Can't blank setting '" + _setting + "': " + e.what());
94 std::string setting::get(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
96 if(!settings().count(_setting))
97 throw std::runtime_error("No such setting '" + _setting + "'");
98 return settings()[_setting]->get();
101 bool setting::is_set(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
103 if(!settings().count(_setting))
104 throw std::runtime_error("No such setting '" + _setting + "'");
105 return settings()[_setting]->is_set();
108 void setting::print_all() throw(std::bad_alloc)
110 for(auto i : settings()) {
111 if(!i.second->is_set())
112 messages << i.first << ": (unset)" << std::endl;
113 else
114 messages << i.first << ": " << i.second->get() << std::endl;
118 numeric_setting::numeric_setting(const std::string& sname, int32_t minv, int32_t maxv, int32_t dflt)
119 throw(std::bad_alloc)
120 : setting(sname)
122 minimum = minv;
123 maximum = maxv;
124 value = dflt;
127 void numeric_setting::blank() throw(std::bad_alloc, std::runtime_error)
129 throw std::runtime_error("This setting can't be blanked");
132 bool numeric_setting::is_set() throw()
134 return true;
137 void numeric_setting::set(const std::string& _value) throw(std::bad_alloc, std::runtime_error)
139 int32_t v = parse_value<int32_t>(_value);
140 if(v < minimum || v > maximum) {
141 std::ostringstream x;
142 x << "Value out of range (" << minimum << " - " << maximum << ")";
143 throw std::runtime_error(x.str());
145 value = v;
148 std::string numeric_setting::get() throw(std::bad_alloc)
150 std::ostringstream x;
151 x << value;
152 return x.str();
155 numeric_setting::operator int32_t() throw()
157 return value;
160 boolean_setting::boolean_setting(const std::string& sname, bool dflt) throw(std::bad_alloc)
161 : setting(sname)
163 value = dflt;
165 void boolean_setting::blank() throw(std::bad_alloc, std::runtime_error)
167 throw std::runtime_error("This setting can't be unset");
170 bool boolean_setting::is_set() throw()
172 return true;
175 void boolean_setting::set(const std::string& v) throw(std::bad_alloc, std::runtime_error)
177 if(v == "true" || v == "yes" || v == "on" || v == "1" || v == "enable" || v == "enabled")
178 value = true;
179 else if(v == "false" || v == "no" || v == "off" || v == "0" || v == "disable" || v == "disabled")
180 value = false;
181 else
182 throw std::runtime_error("Invalid value for boolean setting");
184 std::string boolean_setting::get() throw(std::bad_alloc)
186 if(value)
187 return "true";
188 else
189 return "false";
192 boolean_setting::operator bool() throw()
194 return value;