Actually call on_reset callback
[lsnes.git] / include / library / settingvar.hpp
blob33a9f1373b6e18fc1b9186aaca33dabf704c7ce7
1 #ifndef _library__settingvar__hpp__included__
2 #define _library__settingvar__hpp__included__
4 #include <string>
5 #include <map>
6 #include <set>
7 #include "threads.hpp"
8 #include "string.hpp"
9 #include <string>
11 namespace settingvar
13 class base;
14 class group;
15 class description;
16 class set;
17 class superbase;
19 threads::rlock& get_setting_lock();
21 /**
22 * A settings listener.
24 struct listener
26 /**
27 * Destructor.
29 virtual ~listener() throw();
30 /**
31 * Listen for setting changing value.
33 virtual void on_setting_change(group& _group, const base& val) = 0;
36 /**
37 * A set of setting variables.
39 class set
41 public:
42 /**
43 * Set add/drop listener.
45 class listener
47 public:
48 /**
49 * Dtor.
51 virtual ~listener();
52 /**
53 * New item in set.
55 virtual void create(set& s, const std::string& name, superbase& svar) = 0;
56 /**
57 * Deleted item from set.
59 virtual void destroy(set& s, const std::string& name) = 0;
60 /**
61 * Destroyed the entiere set.
63 virtual void kill(set& s) = 0;
65 /**
66 * Create a set.
68 set();
69 /**
70 * Destructor.
72 ~set();
73 /**
74 * Register a supervariable.
76 void do_register(const std::string& name, superbase& info);
77 /**
78 * Unregister a supervariable.
80 void do_unregister(const std::string& name, superbase& info);
81 /**
82 * Add a callback on new supervariable.
84 void add_callback(listener& listener);
85 /**
86 * Drop a callback on new supervariable.
88 void drop_callback(listener& listener);
89 private:
90 char dummy;
93 /**
94 * Group of setting variables.
96 class group
98 public:
99 /**
100 * Constructor.
102 group();
104 * Destructor.
106 ~group() throw();
108 * Get all settings.
110 std::set<std::string> get_settings_set();
112 * Get setting.
114 base& operator[](const std::string& name);
116 * Add a listener.
118 void add_listener(struct listener& _listener);
120 * Remove a listener.
122 void remove_listener(struct listener& _listener);
124 * Register a setting.
126 void do_register(const std::string& name, base& _setting);
128 * Unregister a setting.
130 void do_unregister(const std::string& name, base& _setting);
132 * Fire listener.
134 void fire_listener(base& var) throw();
136 * Add a set of settings.
138 void add_set(set& s);
140 * Remove a set of settings.
142 void drop_set(set& s);
143 private:
145 * Set listener.
147 class xlistener : public set::listener
149 public:
150 xlistener(group& _grp);
151 ~xlistener();
152 void create(set& s, const std::string& name, superbase& sb);
153 void destroy(set& s, const std::string& name);
154 void kill(set& s);
155 private:
156 group& grp;
157 } _listener;
161 * Write-trough value cache.
163 class cache
165 public:
167 * Constructor.
169 cache(group& grp);
171 * Enumerate contents.
173 * Note: This reads cached values in perference to actual values.
175 std::map<std::string, std::string> get_all();
177 * Enumerate valid keys.
179 * Returns: The set of actually valid keys.
181 std::set<std::string> get_keys();
183 * Set a value.
185 * Parameter name: Name of the setting.
186 * Parameter value: New value for the setting.
187 * Parameter allow_invalid: Cache value if invalid, instead of throwing.
188 * Throws std::runtime_error: Failed to set the setting and invalid values not allowed.
190 * Note: If setting has cached value and setting it succeeds, the cached value is cleared.
192 void set(const std::string& name, const std::string& value, bool allow_invalid = false);
194 * Get a value.
196 * Parameter name: Name of the setting.
197 * Return: Actual value of the setting.
198 * Throws std::runtime_error: Setting doesn't exist.
200 std::string get(const std::string& name);
202 * Get descriptor for.
204 const description& get_description(const std::string& name);
206 * Get human-readable name.
208 * Parameter name: Name of the setting.
209 * Return: Human-readable name of the setting.
210 * Throws std::runtime_error: Setting doesn't exist.
212 std::string get_hname(const std::string& name);
213 private:
214 group& grp;
215 std::map<std::string, std::string> badcache;
219 * Enumeration.
221 struct enumeration
223 enumeration(std::initializer_list<const char*> v)
225 unsigned x = 0;
226 for(auto i : v) {
227 values[bound = x++] = i;
230 std::string get(unsigned val) { return values.count(val) ? values[val] : ""; }
231 unsigned max_val() { return bound; }
232 private:
233 std::map<unsigned, std::string> values;
234 unsigned bound;
238 * Description of setting.
240 struct description
242 enum _type
244 T_BOOLEAN,
245 T_NUMERIC,
246 T_STRING,
247 T_PATH,
248 T_ENUMERATION
250 _type type;
251 int64_t min_val;
252 int64_t max_val;
253 enumeration* _enumeration;
257 * Get the description.
259 template<class T> static class description& description_get(T dummy);
262 * Supervariable.
264 class superbase
266 public:
268 * Constructor.
270 void _superbase(set& _s, const std::string& iname);
272 * Destructor.
274 virtual ~superbase() throw();
276 * Make a variable.
278 virtual base* make(group& grp) = 0;
280 * Notify set death.
282 void set_died();
283 private:
284 set* s;
285 std::string iname;
289 * Setting variable.
291 class base
293 public:
295 * Constructor.
297 base(group& _group, const std::string& iname, const std::string& hname, bool dynamic);
299 * Destructor.
301 virtual ~base() throw();
303 * Set setting.
305 virtual void str(const std::string& val) = 0;
307 * Get setting.
309 virtual std::string str() const = 0;
311 * Get setting name.
313 const std::string& get_iname() const throw() { return iname; }
314 const std::string& get_hname() const throw() { return hname; }
316 * Get setting description.
318 virtual const description& get_description() const throw() = 0;
320 * Notify group death.
322 void group_died();
323 protected:
324 base(const base&);
325 base& operator=(const base&);
326 group* sgroup;
327 std::string iname;
328 std::string hname;
329 bool is_dynamic;
333 * Setting variable.
335 template<class model> class variable : public base
337 typedef typename model::valtype_t valtype_t;
338 variable(const variable<model>&);
339 variable<model>& operator=(const variable<model>&);
340 public:
342 * Constructor.
344 variable(group& sgroup, const std::string& iname, const std::string& hname,
345 valtype_t defaultvalue, bool dynamic = false)
346 : base(sgroup, iname, hname, dynamic)
348 value = defaultvalue;
351 * Destructor.
353 virtual ~variable() throw()
357 * Set setting.
359 void str(const std::string& val)
362 threads::arlock h(get_setting_lock());
363 value = model::read(val);
365 sgroup->fire_listener(*this);
368 * Get setting.
370 std::string str() const
372 threads::arlock h(get_setting_lock());
373 return model::write(value);
376 * Set setting.
378 void set(valtype_t _value)
381 threads::arlock h(get_setting_lock());
382 if(!model::valid(value))
383 throw std::runtime_error("Invalid value");
384 value = _value;
386 sgroup->fire_listener(*this);
389 * Get setting.
391 valtype_t get() const
393 threads::arlock h(get_setting_lock());
394 return model::transform(value);
397 * Get setting.
399 operator valtype_t() const
401 return get();
404 * Get setting description.
406 const description& get_description() const throw()
408 return description_get(dummy);
410 private:
411 valtype_t value;
412 model dummy;
416 * Supervariable with model.
418 template<class model> class supervariable : public superbase
420 typedef typename model::valtype_t valtype_t;
421 supervariable(const supervariable<model>&);
422 supervariable<model>& operator=(const supervariable<model>&);
423 public:
425 * Constructor.
427 supervariable(set& _s, const std::string& _iname, const std::string& _hname, valtype_t _defaultvalue)
428 : s(_s)
430 iname = _iname;
431 hname = _hname;
432 defaultvalue = _defaultvalue;
433 _superbase(_s, iname);
436 * Destructor.
438 ~supervariable() throw()
442 * Make a variable.
444 base* make(group& grp)
446 return new variable<model>(grp, iname, hname, defaultvalue, true);
449 * Read value in instance.
451 valtype_t operator()(group& grp)
453 base* b = &grp[iname];
454 variable<model>* m = dynamic_cast<variable<model>*>(b);
455 if(!m)
456 throw std::runtime_error("No such setting in target group");
457 return m->get();
460 * Write value in instance.
462 void operator()(group& grp, valtype_t val)
464 base* b = &grp[iname];
465 variable<model>* m = dynamic_cast<variable<model>*>(b);
466 if(!m)
467 throw std::runtime_error("No such setting in target group");
468 m->set(val);
470 private:
471 set& s;
472 std::string iname;
473 std::string hname;
474 valtype_t defaultvalue;
478 * Yes-no.
480 struct yes_no
482 static const char* enable;
483 static const char* disable;
487 * Model: Boolean.
489 template<typename values> struct model_bool
491 typedef bool valtype_t;
492 static bool valid(bool val) { return true; /* Any boolean is valid boolean. */ }
493 static bool read(const std::string& val)
495 int x = string_to_bool(val);
496 if(x < 0)
497 throw std::runtime_error("Invalid boolean value");
498 return (x != 0);
500 static std::string write(bool val)
502 return val ? values::enable : values::disable;
504 static bool transform(bool val) { return val; }
507 template<typename values> description& description_get(
508 model_bool<values> X)
510 static description x;
511 static bool init = false;
512 if(!init) {
513 x.type = description::T_BOOLEAN;
514 init = true;
516 return x;
520 * Model: Integer.
522 template<int32_t minimum, int32_t maximum> struct model_int
524 typedef int32_t valtype_t;
525 static bool valid(int32_t val) { return (val >= minimum && val <= maximum); }
526 static int32_t read(const std::string& val)
528 int x = parse_value<int32_t>(val);
529 if(x < minimum || x > maximum)
530 (stringfmt() << "Value out of range (" << minimum << " to " << maximum << ")").throwex();
531 return x;
533 static std::string write(int32_t val)
535 return (stringfmt() << val).str();
537 static int transform(int val) { return val; }
540 template<int32_t m, int32_t M> description& description_get(model_int<m, M> X)
542 static description x;
543 static bool init = false;
544 if(!init) {
545 x.type = description::T_NUMERIC;
546 x.min_val = m;
547 x.max_val = M;
548 init = true;
550 return x;
554 * Model: Path.
556 struct model_path
558 typedef std::string valtype_t;
559 static bool valid(std::string val) { return true; /* Any boolean is valid boolean. */ }
560 static std::string read(const std::string& val)
562 return val;
564 static std::string write(std::string val)
566 return val;
568 static std::string transform(std::string val)
570 return (val != "") ? val : ".";
574 template<> description& description_get(model_path X)
576 static description x;
577 static bool init = false;
578 if(!init) {
579 x.type = description::T_PATH;
580 init = true;
582 return x;
586 * Model: Enumerated.
588 template<enumeration* e> struct model_enumerated
590 typedef unsigned valtype_t;
591 static bool valid(unsigned val) { return (val <= e->max_val()); }
592 static unsigned read(const std::string& val)
594 for(unsigned i = 0; i <= e->max_val(); i++)
595 if(val == e->get(i))
596 return i;
597 unsigned x = parse_value<unsigned>(val);
598 if(x > e->max_val())
599 (stringfmt() << "Value out of range (0 to " << e->max_val() << ")").throwex();
600 return x;
602 static std::string write(unsigned val)
604 return e->get(val);
606 static int transform(int val) { return val; }
609 template<enumeration* e> description& description_get(model_enumerated<e> X)
611 static description x;
612 static bool init = false;
613 if(!init) {
614 x.type = description::T_ENUMERATION;
615 x._enumeration = e;
616 init = true;
618 return x;
622 #endif