lsnes rr0-β2
[lsnes.git] / settings.cpp
blob6cf25832fd2127faf8d06ba3844b3875a5686831
1 #include "settings.hpp"
2 #include "misc.hpp"
3 #include <map>
4 #include <sstream>
5 #include "misc.hpp"
6 #include "command.hpp"
7 #include <iostream>
9 namespace
11 std::map<std::string, setting*>* settings;
13 function_ptr_command<tokensplitter&> set_setting("set-setting", "set a setting",
14 "Syntax: set-setting <setting> [<value>]\nSet setting to a new value. Omit <value> to set to ''\n",
15 [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
16 std::string syntax = "Syntax: set-setting <setting> [<value>]";
17 std::string settingname = t;
18 std::string settingvalue = t.tail();
19 if(settingname == "")
20 throw std::runtime_error("Setting name required.");
21 setting::set(settingname, settingvalue);
22 messages << "Setting '" << settingname << "' set to '" << settingvalue << "'"
23 << std::endl;
24 });
26 function_ptr_command<tokensplitter&> unset_setting("unset-setting", "unset a setting",
27 "Syntax: unset-setting <setting>\nTry to unset a setting. Note that not all settings can be unset\n",
28 [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
29 std::string syntax = "Syntax: unset-setting <setting>";
30 std::string settingname = t;
31 if(settingname == "" || t)
32 throw std::runtime_error("Expected setting name and nothing else");
33 setting::blank(settingname);
34 messages << "Setting '" << settingname << "' unset" << std::endl;
35 });
37 function_ptr_command<tokensplitter&> get_command("get-setting", "get value of a setting",
38 "Syntax: get-setting <setting>\nShow value of setting\n",
39 [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
40 std::string settingname = t;
41 if(settingname == "" || t.tail() != "")
42 throw std::runtime_error("Expected setting name and nothing else");
43 if(setting::is_set(settingname))
44 messages << "Setting '" << settingname << "' has value '"
45 << setting::get(settingname) << "'" << std::endl;
46 else
47 messages << "Setting '" << settingname << "' unset" << std::endl;
48 });
50 function_ptr_command<> show_settings("show-settings", "Show values of all settings",
51 "Syntax: show-settings\nShow value of all settings\n",
52 []() throw(std::bad_alloc, std::runtime_error) {
53 setting::print_all();
54 });
57 setting::setting(const std::string& name) throw(std::bad_alloc)
59 if(!settings)
60 settings = new std::map<std::string, setting*>();
61 (*settings)[settingname = name] = this;
64 setting::~setting() throw()
66 if(!settings)
67 return;
68 settings->erase(settingname);
71 void setting::set(const std::string& _setting, const std::string& value) throw(std::bad_alloc, std::runtime_error)
73 if(!settings || !settings->count(_setting))
74 throw std::runtime_error("No such setting '" + _setting + "'");
75 try {
76 (*settings)[_setting]->set(value);
77 } catch(std::bad_alloc& e) {
78 throw;
79 } catch(std::exception& e) {
80 throw std::runtime_error("Can't set setting '" + _setting + "': " + e.what());
84 void setting::blank(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
86 if(!settings || !settings->count(_setting))
87 throw std::runtime_error("No such setting '" + _setting + "'");
88 try {
89 (*settings)[_setting]->blank();
90 } catch(std::bad_alloc& e) {
91 throw;
92 } catch(std::exception& e) {
93 throw std::runtime_error("Can't blank setting '" + _setting + "': " + e.what());
97 std::string setting::get(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
99 if(!settings || !settings->count(_setting))
100 throw std::runtime_error("No such setting '" + _setting + "'");
101 return (*settings)[_setting]->get();
104 bool setting::is_set(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
106 if(!settings || !settings->count(_setting))
107 throw std::runtime_error("No such setting '" + _setting + "'");
108 return (*settings)[_setting]->is_set();
111 void setting::print_all() throw(std::bad_alloc)
113 if(!settings)
114 return;
115 for(auto i = settings->begin(); i != settings->end(); i++) {
116 if(!i->second->is_set())
117 messages << i->first << ": (unset)" << std::endl;
118 else
119 messages << i->first << ": " << i->second->get() << std::endl;
123 numeric_setting::numeric_setting(const std::string& sname, int32_t minv, int32_t maxv, int32_t dflt)
124 throw(std::bad_alloc)
125 : setting(sname)
127 minimum = minv;
128 maximum = maxv;
129 value = dflt;
132 void numeric_setting::blank() throw(std::bad_alloc, std::runtime_error)
134 throw std::runtime_error("This setting can't be blanked");
137 bool numeric_setting::is_set() throw()
139 return true;
142 void numeric_setting::set(const std::string& _value) throw(std::bad_alloc, std::runtime_error)
144 int32_t v = parse_value<int32_t>(_value);
145 if(v < minimum || v > maximum) {
146 std::ostringstream x;
147 x << "Value out of range (" << minimum << " - " << maximum << ")";
148 throw std::runtime_error(x.str());
150 value = v;
153 std::string numeric_setting::get() throw(std::bad_alloc)
155 std::ostringstream x;
156 x << value;
157 return x.str();
160 numeric_setting::operator int32_t() throw()
162 return value;
165 boolean_setting::boolean_setting(const std::string& sname, bool dflt) throw(std::bad_alloc)
166 : setting(sname)
168 value = dflt;
170 void boolean_setting::blank() throw(std::bad_alloc, std::runtime_error)
172 throw std::runtime_error("This setting can't be unset");
175 bool boolean_setting::is_set() throw()
177 return true;
180 void boolean_setting::set(const std::string& v) throw(std::bad_alloc, std::runtime_error)
182 if(v == "true" || v == "yes" || v == "on" || v == "1" || v == "enable" || v == "enabled")
183 value = true;
184 else if(v == "false" || v == "no" || v == "off" || v == "0" || v == "disable" || v == "disabled")
185 value = false;
186 else
187 throw std::runtime_error("Invalid value for boolean setting");
189 std::string boolean_setting::get() throw(std::bad_alloc)
191 if(value)
192 return "true";
193 else
194 return "false";
197 boolean_setting::operator bool() throw()
199 return value;