Save bitmaps as PNG
[lsnes.git] / include / library / settingvar.hpp
blobb891e5b8174872b6f4c3c0ff327231686e6df877
1 #ifndef _library__settingvar__hpp__included__
2 #define _library__settingvar__hpp__included__
4 #include <string>
5 #include <map>
6 #include <set>
7 #include "threadtypes.hpp"
8 #include "string.hpp"
9 #include <string>
11 class setting_var_base;
12 class setting_var_group;
13 class setting_var_description;
15 /**
16 * A settings listener.
18 struct setting_var_listener
20 /**
21 * Destructor.
23 virtual ~setting_var_listener() throw();
24 /**
25 * Listen for setting changing value.
27 virtual void on_setting_change(setting_var_group& group, const setting_var_base& val) = 0;
30 /**
31 * Group of setting variables.
33 class setting_var_group
35 public:
36 /**
37 * Constructor.
39 setting_var_group() throw(std::bad_alloc);
40 /**
41 * Destructor.
43 ~setting_var_group() throw();
44 /**
45 * Get all settings.
47 std::set<std::string> get_settings_set() throw(std::bad_alloc);
48 /**
49 * Get setting.
51 setting_var_base& operator[](const std::string& name);
52 /**
53 * Add a listener.
55 void add_listener(struct setting_var_listener& listener) throw(std::bad_alloc);
56 /**
57 * Remove a listener.
59 void remove_listener(struct setting_var_listener& listener) throw(std::bad_alloc);
60 /**
61 * Register a setting.
63 void do_register(const std::string& name, setting_var_base& _setting) throw(std::bad_alloc);
64 /**
65 * Unregister a setting.
67 void do_unregister(const std::string& name) throw(std::bad_alloc);
68 /**
69 * Fire listener.
71 void fire_listener(setting_var_base& var) throw();
72 private:
73 std::map<std::string, class setting_var_base*> settings;
74 std::set<struct setting_var_listener*> listeners;
75 mutex_class lock;
78 /**
79 * Write-trough value cache.
81 class setting_var_cache
83 public:
84 /**
85 * Constructor.
87 setting_var_cache(setting_var_group& grp);
88 /**
89 * Enumerate contents.
91 * Note: This reads cached values in perference to actual values.
93 std::map<std::string, std::string> get_all();
94 /**
95 * Enumerate valid keys.
97 * Returns: The set of actually valid keys.
99 std::set<std::string> get_keys();
101 * Set a value.
103 * Parameter name: Name of the setting.
104 * Parameter value: New value for the setting.
105 * Parameter allow_invalid: Cache value if invalid, instead of throwing.
106 * Throws std::runtime_error: Failed to set the setting and invalid values not allowed.
108 * Note: If setting has cached value and setting it succeeds, the cached value is cleared.
110 void set(const std::string& name, const std::string& value, bool allow_invalid = false) throw(std::bad_alloc,
111 std::runtime_error);
113 * Get a value.
115 * Parameter name: Name of the setting.
116 * Return: Actual value of the setting.
117 * Throws std::runtime_error: Setting doesn't exist.
119 std::string get(const std::string& name) throw(std::bad_alloc, std::runtime_error);
121 * Get descriptor for.
123 const setting_var_description& get_description(const std::string& name) throw(std::bad_alloc,
124 std::runtime_error);
125 private:
126 setting_var_group& grp;
127 mutex_class lock;
128 std::map<std::string, std::string> badcache;
132 * Enumeration.
134 struct setting_enumeration
136 setting_enumeration(std::initializer_list<const char*> v)
138 unsigned x = 0;
139 for(auto i : v) {
140 values[bound = x++] = i;
143 std::string get(unsigned val) { return values.count(val) ? values[val] : ""; }
144 unsigned max_val() { return bound; }
145 private:
146 std::map<unsigned, std::string> values;
147 unsigned bound;
151 * Description of setting.
153 struct setting_var_description
155 enum _type
157 T_BOOLEAN,
158 T_NUMERIC,
159 T_STRING,
160 T_PATH,
161 T_ENUMERATION
163 _type type;
164 int64_t min_val;
165 int64_t max_val;
166 setting_enumeration* enumeration;
170 * Get the description.
172 template<class T> static class setting_var_description& setting_var_description_get(T dummy);
175 * Setting variable.
177 class setting_var_base
179 public:
181 * Constructor.
183 setting_var_base(setting_var_group& group, const std::string& iname, const std::string& hname)
184 throw(std::bad_alloc);
186 * Destructor.
188 virtual ~setting_var_base() throw();
190 * Set setting.
192 virtual void str(const std::string& val) throw(std::runtime_error, std::bad_alloc) = 0;
194 * Get setting.
196 virtual std::string str() const throw(std::runtime_error, std::bad_alloc) = 0;
198 * Get setting name.
200 const std::string& get_iname() const throw() { return iname; }
201 const std::string& get_hname() const throw() { return hname; }
203 * Get setting description.
205 virtual const setting_var_description& get_description() const throw() = 0;
206 protected:
207 setting_var_base(const setting_var_base&);
208 setting_var_base& operator=(const setting_var_base&);
209 setting_var_group& group;
210 std::string iname;
211 std::string hname;
212 mutable mutex_class lock;
216 * Setting variable.
218 template<class model> class setting_var : public setting_var_base
220 typedef typename model::valtype_t valtype_t;
221 setting_var(const setting_var<model>&);
222 setting_var<model>& operator=(const setting_var<model>&);
223 public:
225 * Constructor.
227 setting_var(setting_var_group& group, const std::string& iname, const std::string& hname,
228 valtype_t defaultvalue)
229 : setting_var_base(group, iname, hname)
231 value = defaultvalue;
234 * Destructor.
236 virtual ~setting_var() throw()
240 * Set setting.
242 void str(const std::string& val) throw(std::runtime_error, std::bad_alloc)
245 umutex_class h(lock);
246 value = model::read(val);
248 group.fire_listener(*this);
251 * Get setting.
253 std::string str() const throw(std::runtime_error, std::bad_alloc)
255 umutex_class h(lock);
256 return model::write(value);
259 * Set setting.
261 void set(valtype_t _value) throw(std::runtime_error, std::bad_alloc)
264 umutex_class h(lock);
265 if(!model::valid(value))
266 throw std::runtime_error("Invalid value");
267 value = _value;
269 group.fire_listener(*this);
272 * Get setting.
274 valtype_t get() throw(std::bad_alloc)
276 umutex_class h(lock);
277 return model::transform(value);
280 * Get setting.
282 operator valtype_t()
284 return get();
287 * Get setting description.
289 const setting_var_description& get_description() const throw()
291 return setting_var_description_get(dummy);
293 private:
294 valtype_t value;
295 model dummy;
299 * Yes-no.
301 struct setting_yes_no
303 static const char* enable;
304 static const char* disable;
308 * Model: Boolean.
310 template<typename values> struct setting_var_model_bool
312 typedef bool valtype_t;
313 static bool valid(bool val) { return true; /* Any boolean is valid boolean. */ }
314 static bool read(const std::string& val)
316 int x = string_to_bool(val);
317 if(x < 0)
318 throw std::runtime_error("Invalid boolean value");
319 return (x != 0);
321 static std::string write(bool val)
323 return val ? values::enable : values::disable;
325 static bool transform(bool val) { return val; }
328 template<typename values> setting_var_description& setting_var_description_get(
329 setting_var_model_bool<values> X)
331 static setting_var_description x;
332 static bool init = false;
333 if(!init) {
334 x.type = setting_var_description::T_BOOLEAN;
335 init = true;
337 return x;
341 * Model: Integer.
343 template<int32_t minimum, int32_t maximum> struct setting_var_model_int
345 typedef int32_t valtype_t;
346 static bool valid(int32_t val) { return (val >= minimum && val <= maximum); }
347 static int32_t read(const std::string& val)
349 int x = parse_value<int32_t>(val);
350 if(x < minimum || x > maximum)
351 (stringfmt() << "Value out of range (" << minimum << " to " << maximum << ")").throwex();
352 return x;
354 static std::string write(int32_t val)
356 return (stringfmt() << val).str();
358 static int transform(int val) { return val; }
361 template<int32_t m, int32_t M> setting_var_description& setting_var_description_get(setting_var_model_int<m, M> X)
363 static setting_var_description x;
364 static bool init = false;
365 if(!init) {
366 x.type = setting_var_description::T_NUMERIC;
367 x.min_val = m;
368 x.max_val = M;
369 init = true;
371 return x;
375 * Model: Path.
377 struct setting_var_model_path
379 typedef std::string valtype_t;
380 static bool valid(std::string val) { return true; /* Any boolean is valid boolean. */ }
381 static std::string read(const std::string& val)
383 return val;
385 static std::string write(std::string val)
387 return val;
389 static std::string transform(std::string val)
391 return (val != "") ? val : ".";
395 template<> setting_var_description& setting_var_description_get(setting_var_model_path X)
397 static setting_var_description x;
398 static bool init = false;
399 if(!init) {
400 x.type = setting_var_description::T_PATH;
401 init = true;
403 return x;
407 * Model: Enumerated.
409 template<setting_enumeration* e> struct setting_var_model_enumerated
411 typedef unsigned valtype_t;
412 static bool valid(unsigned val) { return (val <= e->max_val()); }
413 static unsigned read(const std::string& val)
415 for(unsigned i = 0; i <= e->max_val(); i++)
416 if(val == e->get(i))
417 return i;
418 unsigned x = parse_value<unsigned>(val);
419 if(x > e->max_val())
420 (stringfmt() << "Value out of range (0 to " << e->max_val() << ")").throwex();
421 return x;
423 static std::string write(unsigned val)
425 return e->get(val);
427 static int transform(int val) { return val; }
430 template<setting_enumeration* e> setting_var_description& setting_var_description_get(
431 setting_var_model_enumerated<e> X)
433 static setting_var_description x;
434 static bool init = false;
435 if(!init) {
436 x.type = setting_var_description::T_ENUMERATION;
437 x.enumeration = e;
438 init = true;
440 return x;
444 #endif