1 #ifndef _library__settingvar__hpp__included__
2 #define _library__settingvar__hpp__included__
19 threads::rlock
& get_setting_lock();
22 * A settings listener.
29 virtual ~listener() throw();
31 * Listen for setting changing value.
33 virtual void on_setting_change(group
& _group
, const base
& val
) = 0;
37 * A set of setting variables.
43 * Set add/drop listener.
55 virtual void create(set
& s
, const std::string
& name
, superbase
& svar
) = 0;
57 * Deleted item from set.
59 virtual void destroy(set
& s
, const std::string
& name
) = 0;
61 * Destroyed the entiere set.
63 virtual void kill(set
& s
) = 0;
74 * Register a supervariable.
76 void do_register(const std::string
& name
, superbase
& info
);
78 * Unregister a supervariable.
80 void do_unregister(const std::string
& name
, superbase
& info
);
82 * Add a callback on new supervariable.
84 void add_callback(listener
& listener
) throw(std::bad_alloc
);
86 * Drop a callback on new supervariable.
88 void drop_callback(listener
& listener
);
94 * Group of setting variables.
102 group() throw(std::bad_alloc
);
110 std::set
<std::string
> get_settings_set() throw(std::bad_alloc
);
114 base
& operator[](const std::string
& name
);
118 void add_listener(struct listener
& _listener
) throw(std::bad_alloc
);
122 void remove_listener(struct listener
& _listener
) throw(std::bad_alloc
);
124 * Register a setting.
126 void do_register(const std::string
& name
, base
& _setting
) throw(std::bad_alloc
);
128 * Unregister a setting.
130 void do_unregister(const std::string
& name
, base
& _setting
) throw(std::bad_alloc
);
134 void fire_listener(base
& var
) throw();
136 * Add a set of settings.
138 void add_set(set
& s
) throw(std::bad_alloc
);
140 * Remove a set of settings.
142 void drop_set(set
& s
);
147 class xlistener
: public set::listener
150 xlistener(group
& _grp
);
152 void create(set
& s
, const std::string
& name
, superbase
& sb
);
153 void destroy(set
& s
, const std::string
& name
);
161 * Write-trough value cache.
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();
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) throw(std::bad_alloc
,
197 * Parameter name: Name of the setting.
198 * Return: Actual value of the setting.
199 * Throws std::runtime_error: Setting doesn't exist.
201 std::string
get(const std::string
& name
) throw(std::bad_alloc
, std::runtime_error
);
203 * Get descriptor for.
205 const description
& get_description(const std::string
& name
) throw(std::bad_alloc
,
208 * Get human-readable name.
210 * Parameter name: Name of the setting.
211 * Return: Human-readable name of the setting.
212 * Throws std::runtime_error: Setting doesn't exist.
214 std::string
get_hname(const std::string
& name
) throw(std::bad_alloc
, std::runtime_error
);
217 std::map
<std::string
, std::string
> badcache
;
225 enumeration(std::initializer_list
<const char*> v
)
229 values
[bound
= x
++] = i
;
232 std::string
get(unsigned val
) { return values
.count(val
) ? values
[val
] : ""; }
233 unsigned max_val() { return bound
; }
235 std::map
<unsigned, std::string
> values
;
240 * Description of setting.
255 enumeration
* _enumeration
;
259 * Get the description.
261 template<class T
> static class description
& description_get(T dummy
);
272 void _superbase(set
& _s
, const std::string
& iname
) throw(std::bad_alloc
);
276 virtual ~superbase() throw();
280 virtual base
* make(group
& grp
) = 0;
299 base(group
& _group
, const std::string
& iname
, const std::string
& hname
, bool dynamic
) throw(std::bad_alloc
);
303 virtual ~base() throw();
307 virtual void str(const std::string
& val
) throw(std::runtime_error
, std::bad_alloc
) = 0;
311 virtual std::string
str() const throw(std::runtime_error
, std::bad_alloc
) = 0;
315 const std::string
& get_iname() const throw() { return iname
; }
316 const std::string
& get_hname() const throw() { return hname
; }
318 * Get setting description.
320 virtual const description
& get_description() const throw() = 0;
322 * Notify group death.
327 base
& operator=(const base
&);
337 template<class model
> class variable
: public base
339 typedef typename
model::valtype_t valtype_t
;
340 variable(const variable
<model
>&);
341 variable
<model
>& operator=(const variable
<model
>&);
346 variable(group
& sgroup
, const std::string
& iname
, const std::string
& hname
,
347 valtype_t defaultvalue
, bool dynamic
= false)
348 : base(sgroup
, iname
, hname
, dynamic
)
350 value
= defaultvalue
;
355 virtual ~variable() throw()
361 void str(const std::string
& val
) throw(std::runtime_error
, std::bad_alloc
)
364 threads::arlock
h(get_setting_lock());
365 value
= model::read(val
);
367 sgroup
->fire_listener(*this);
372 std::string
str() const throw(std::runtime_error
, std::bad_alloc
)
374 threads::arlock
h(get_setting_lock());
375 return model::write(value
);
380 void set(valtype_t _value
) throw(std::runtime_error
, std::bad_alloc
)
383 threads::arlock
h(get_setting_lock());
384 if(!model::valid(value
))
385 throw std::runtime_error("Invalid value");
388 sgroup
->fire_listener(*this);
393 valtype_t
get() throw(std::bad_alloc
)
395 threads::arlock
h(get_setting_lock());
396 return model::transform(value
);
406 * Get setting description.
408 const description
& get_description() const throw()
410 return description_get(dummy
);
418 * Supervariable with model.
420 template<class model
> class supervariable
: public superbase
422 typedef typename
model::valtype_t valtype_t
;
423 supervariable(const supervariable
<model
>&);
424 supervariable
<model
>& operator=(const supervariable
<model
>&);
429 supervariable(set
& _s
, const std::string
& _iname
, const std::string
& _hname
, valtype_t _defaultvalue
)
430 throw(std::bad_alloc
)
435 defaultvalue
= _defaultvalue
;
436 _superbase(_s
, iname
);
441 ~supervariable() throw()
447 base
* make(group
& grp
)
449 return new variable
<model
>(grp
, iname
, hname
, defaultvalue
, true);
452 * Read value in instance.
454 valtype_t
operator()(group
& grp
)
456 base
* b
= &grp
[iname
];
457 variable
<model
>* m
= dynamic_cast<variable
<model
>*>(b
);
459 throw std::runtime_error("No such setting in target group");
463 * Write value in instance.
465 void operator()(group
& grp
, valtype_t val
)
467 base
* b
= &grp
[iname
];
468 variable
<model
>* m
= dynamic_cast<variable
<model
>*>(b
);
470 throw std::runtime_error("No such setting in target group");
477 valtype_t defaultvalue
;
485 static const char* enable
;
486 static const char* disable
;
492 template<typename values
> struct model_bool
494 typedef bool valtype_t
;
495 static bool valid(bool val
) { return true; /* Any boolean is valid boolean. */ }
496 static bool read(const std::string
& val
)
498 int x
= string_to_bool(val
);
500 throw std::runtime_error("Invalid boolean value");
503 static std::string
write(bool val
)
505 return val
? values::enable
: values::disable
;
507 static bool transform(bool val
) { return val
; }
510 template<typename values
> description
& description_get(
511 model_bool
<values
> X
)
513 static description x
;
514 static bool init
= false;
516 x
.type
= description::T_BOOLEAN
;
525 template<int32_t minimum
, int32_t maximum
> struct model_int
527 typedef int32_t valtype_t
;
528 static bool valid(int32_t val
) { return (val
>= minimum
&& val
<= maximum
); }
529 static int32_t read(const std::string
& val
)
531 int x
= parse_value
<int32_t>(val
);
532 if(x
< minimum
|| x
> maximum
)
533 (stringfmt() << "Value out of range (" << minimum
<< " to " << maximum
<< ")").throwex();
536 static std::string
write(int32_t val
)
538 return (stringfmt() << val
).str();
540 static int transform(int val
) { return val
; }
543 template<int32_t m
, int32_t M
> description
& description_get(model_int
<m
, M
> X
)
545 static description x
;
546 static bool init
= false;
548 x
.type
= description::T_NUMERIC
;
561 typedef std::string valtype_t
;
562 static bool valid(std::string val
) { return true; /* Any boolean is valid boolean. */ }
563 static std::string
read(const std::string
& val
)
567 static std::string
write(std::string val
)
571 static std::string
transform(std::string val
)
573 return (val
!= "") ? val
: ".";
577 template<> description
& description_get(model_path X
)
579 static description x
;
580 static bool init
= false;
582 x
.type
= description::T_PATH
;
591 template<enumeration
* e
> struct model_enumerated
593 typedef unsigned valtype_t
;
594 static bool valid(unsigned val
) { return (val
<= e
->max_val()); }
595 static unsigned read(const std::string
& val
)
597 for(unsigned i
= 0; i
<= e
->max_val(); i
++)
600 unsigned x
= parse_value
<unsigned>(val
);
602 (stringfmt() << "Value out of range (0 to " << e
->max_val() << ")").throwex();
605 static std::string
write(unsigned val
)
609 static int transform(int val
) { return val
; }
612 template<enumeration
* e
> description
& description_get(model_enumerated
<e
> X
)
614 static description x
;
615 static bool init
= false;
617 x
.type
= description::T_ENUMERATION
;