Async 1.9.1
AsyncConfig.h
Go to the documentation of this file.
1
32
36
37
38#ifndef ASYNC_CONFIG_INCLUDED
39#define ASYNC_CONFIG_INCLUDED
40
41
42/****************************************************************************
43 *
44 * System Includes
45 *
46 ****************************************************************************/
47
48#include <stdio.h>
49#include <sigc++/sigc++.h>
50
51#include <string>
52#include <map>
53#include <list>
54#include <memory>
55#include <sstream>
56#include <locale>
57#include <vector>
58#include <cassert>
59
60
61/****************************************************************************
62 *
63 * Project Includes
64 *
65 ****************************************************************************/
66
67
68
69/****************************************************************************
70 *
71 * Local Includes
72 *
73 ****************************************************************************/
74
75
76
77/****************************************************************************
78 *
79 * Forward declarations
80 *
81 ****************************************************************************/
82
83
84
85/****************************************************************************
86 *
87 * Namespace
88 *
89 ****************************************************************************/
90
91namespace Async
92{
93
94
95/****************************************************************************
96 *
97 * Forward declarations of classes inside of the declared namespace
98 *
99 ****************************************************************************/
100
101
102
103/****************************************************************************
104 *
105 * Defines & typedefs
106 *
107 ****************************************************************************/
108
109
110
111/****************************************************************************
112 *
113 * Exported Global Variables
114 *
115 ****************************************************************************/
116
117
118
119/****************************************************************************
120 *
121 * Class definitions
122 *
123 ****************************************************************************/
124
139{
140 public:
144 Config(void) {}
145
149 ~Config(void);
150
160 bool open(const std::string& name);
161
174 const std::string &getValue(const std::string& section,
175 const std::string& tag) const;
176
189 bool getValue(const std::string& section, const std::string& tag,
190 std::string& value, bool missing_ok = false) const;
191
205 bool getValue(const std::string& section, const std::string& tag,
206 char& value, bool missing_ok = false) const;
227 template <typename Rsp>
228 bool getValue(const std::string& section, const std::string& tag,
229 Rsp &rsp, bool missing_ok = false) const
230 {
231 std::string str_val;
232 if (!getValue(section, tag, str_val))
233 {
234 return missing_ok;
235 }
236 std::stringstream ssval(str_val);
237 Rsp tmp;
238 ssval >> tmp;
239 if(!ssval.eof())
240 {
241 ssval >> std::ws;
242 }
243 if (ssval.fail() || !ssval.eof())
244 {
245 return false;
246 }
247 rsp = tmp;
248 return true;
249 } /* Config::getValue */
250
271 template <template <typename, typename> class Container,
272 typename Value>
273 bool getValue(const std::string& section, const std::string& tag,
274 Container<Value, std::allocator<Value> > &c,
275 bool missing_ok = false) const
276 {
277 std::string str_val;
278 if (!getValue(section, tag, str_val))
279 {
280 return missing_ok;
281 }
282 if (str_val.empty())
283 {
284 c.clear();
285 return true;
286 }
287 std::stringstream ssval(str_val);
288 ssval.imbue(std::locale(ssval.getloc(), new csv_whitespace));
289 while (!ssval.eof())
290 {
291 Value tmp;
292 ssval >> tmp;
293 if(!ssval.eof())
294 {
295 ssval >> std::ws;
296 }
297 if (ssval.fail())
298 {
299 return false;
300 }
301 c.push_back(tmp);
302 }
303 return true;
304 } /* Config::getValue */
305
327 template <template <typename, typename, typename> class Container,
328 typename Key>
329 bool getValue(const std::string& section, const std::string& tag,
330 Container<Key, std::less<Key>, std::allocator<Key> > &c,
331 bool missing_ok = false) const
332 {
333 std::string str_val;
334 if (!getValue(section, tag, str_val))
335 {
336 return missing_ok;
337 }
338 if (str_val.empty())
339 {
340 c.clear();
341 return true;
342 }
343 std::stringstream ssval(str_val);
344 ssval.imbue(std::locale(ssval.getloc(), new csv_whitespace));
345 while (!ssval.eof())
346 {
347 Key tmp;
348 ssval >> tmp;
349 if(!ssval.eof())
350 {
351 ssval >> std::ws;
352 }
353 if (ssval.fail())
354 {
355 return false;
356 }
357 c.insert(tmp);
358 }
359 return true;
360 } /* Config::getValue */
361
383 template <template <typename, typename, typename, typename> class Container,
384 class Key, class T, class Compare=std::less<Key>,
385 class Allocator=std::allocator<std::pair<const Key, T>>>
386 bool getValue(const std::string& section, const std::string& tag,
387 Container<Key, T, Compare, Allocator>& c,
388 char sep = ':', bool missing_ok = false) const
389 {
390 std::string str_val;
391 if (!getValue(section, tag, str_val))
392 {
393 return missing_ok;
394 }
395 if (str_val.empty())
396 {
397 c.clear();
398 return true;
399 }
400 std::stringstream ssval(str_val);
401 ssval.imbue(std::locale(ssval.getloc(), new csv_whitespace));
402 while (!ssval.eof())
403 {
404 std::string entry;
405 ssval >> entry;
406 std::string::size_type seppos = entry.find(sep);
407 if (seppos == std::string::npos)
408 {
409 return false;
410 }
411 std::string keystr(entry.substr(0, seppos));
412 std::string valuestr(entry.substr(seppos+1));
413 Key key;
414 T value;
415 if (!setValueFromString(key, keystr) ||
416 !setValueFromString(value, valuestr))
417 {
418 return false;
419 }
420 if(!ssval.eof())
421 {
422 ssval >> std::ws;
423 }
424 if (ssval.fail())
425 {
426 return false;
427 }
428 c.insert(std::pair<Key, T>(key, value));
429 }
430 return true;
431 } /* Config::getValue */
432
454 template <typename Rsp>
455 bool getValue(const std::string& section, const std::string& tag,
456 const Rsp& min, const Rsp& max, Rsp &rsp,
457 bool missing_ok = false) const
458 {
459 std::string str_val;
460 if (!getValue(section, tag, str_val))
461 {
462 return missing_ok;
463 }
464 std::stringstream ssval(str_val);
465 Rsp tmp;
466 ssval >> tmp;
467 if(!ssval.eof())
468 {
469 ssval >> std::ws;
470 }
471 if (ssval.fail() || !ssval.eof() || (tmp < min) || (tmp > max))
472 {
473 return false;
474 }
475 rsp = tmp;
476 return true;
477 } /* Config::getValue */
478
495 template <typename F=std::function<void(const char*)>>
496 void subscribeValue(const std::string& section, const std::string& tag,
497 const char* def, F func)
498 {
499 subscribeValue(section, tag, std::string(def),
500 [=](const std::string& str_val) -> void
501 {
502 func(str_val.c_str());
503 });
504 } /* subscribeValue */
505
522 template <typename Rsp, typename F=std::function<void(const Rsp&)>>
523 void subscribeValue(const std::string& section, const std::string& tag,
524 const Rsp& def, F func)
525 {
526 Value& v = getValueP(section, tag, def);
527 v.subs.push_back(
528 [=](const std::string& str_val) -> void
529 {
530 std::stringstream ssval(str_val);
531 ssval.imbue(std::locale(ssval.getloc(), new empty_ctype));
532 Rsp tmp;
533 ssval >> tmp;
534 func(tmp);
535 });
536 v.subs.back()(v.val);
537 } /* subscribeValue */
538
555 template <template <typename, typename> class Container,
556 typename Rsp, typename F=std::function<void(const Rsp&)>>
557 void subscribeValue(const std::string& section, const std::string& tag,
558 const Container<Rsp, std::allocator<Rsp>>& def, F func)
559 {
560 Value& v = getValueP(section, tag, def);
561 v.subs.push_back(
562 [=](const std::string& str_val) -> void
563 {
564 std::stringstream ssval(str_val);
565 ssval.imbue(std::locale(ssval.getloc(), new csv_whitespace));
566 Container<Rsp, std::allocator<Rsp>> c;
567 while (!ssval.eof())
568 {
569 Rsp tmp;
570 ssval >> tmp;
571 if(!ssval.eof())
572 {
573 ssval >> std::ws;
574 }
575 if (ssval.fail())
576 {
577 return;
578 }
579 c.push_back(tmp);
580 }
581 func(std::move(c));
582 });
583 v.subs.back()(v.val);
584 } /* Config::subscribeValue */
585
590 std::list<std::string> listSections(void);
591
598 std::list<std::string> listSection(const std::string& section);
599
616 void setValue(const std::string& section, const std::string& tag,
617 const std::string& value);
618
636 template <typename Rsp>
637 void setValue(const std::string& section, const std::string& tag,
638 const Rsp& value)
639 {
640 std::ostringstream ss;
641 ss << value;
642 setValue(section, tag, ss.str());
643 }
644
664 template <template <typename, typename> class Container,
665 typename Rsp>
666 void setValue(const std::string& section, const std::string& tag,
667 const Container<Rsp, std::allocator<Rsp>>& c)
668 {
669 std::ostringstream ss;
670 bool first_val = true;
671 for (const auto& val : c)
672 {
673 if (!first_val)
674 {
675 ss << ",";
676 }
677 first_val = false;
678 ss << val;
679 }
680 setValue(section, tag, ss.str());
681 } /* setValue */
682
692 sigc::signal<void(const std::string&, const std::string&)> valueUpdated;
693
694 private:
695 using Subscriber = std::function<void(const std::string&)>;
696 struct Value
697 {
698 std::string val;
699 std::vector<Subscriber> subs;
700 };
701 typedef std::map<std::string, Value> Values;
702 typedef std::map<std::string, Values> Sections;
703
704 // Really wanted to use classic_table() but it returns nullptr on Alpine
705 static const std::ctype<char>::mask* empty_table()
706 {
707 static const auto table_size = std::ctype<char>::table_size;
708 static std::ctype<char>::mask v[table_size];
709 std::fill(&v[0], &v[table_size], 0);
710 return &v[0];
711 }
712
713 struct empty_ctype : std::ctype<char>
714 {
715 static const mask* make_table(void) { return empty_table(); }
716 empty_ctype(std::size_t refs=0) : ctype(make_table(), false, refs) {}
717 };
718
719 struct csv_whitespace : std::ctype<char>
720 {
721 static const mask* make_table()
722 {
723 auto tbl = empty_table();
724 static std::vector<mask> v(tbl, tbl + table_size);
725 v[' '] |= space;
726 v[','] |= space;
727 return &v[0];
728 }
729 csv_whitespace(std::size_t refs=0) : ctype(make_table(), false, refs) {}
730 };
731
732 Sections sections;
733
734 bool parseCfgFile(FILE *file);
735 char *trimSpaces(char *line);
736 char *parseSection(char *line);
737 char *parseDelimitedString(char *str, char begin_tok, char end_tok);
738 bool parseValueLine(char *line, std::string& tag, std::string& value);
739 char *parseValue(char *value);
740 char *translateEscapedChars(char *val);
741
742 template <class T>
743 bool setValueFromString(T& val, const std::string &str) const
744 {
745 std::istringstream ss(str);
746 ss >> std::noskipws >> val;
747 if(!ss.eof())
748 {
749 ss >> std::ws;
750 }
751 return !ss.fail() && ss.eof();
752 }
753
754 template <typename T>
755 Value& getValueP(const std::string& section, const std::string& tag,
756 const T& def)
757 {
758 Values::iterator val_it = sections[section].find(tag);
759 if (val_it == sections[section].end())
760 {
761 setValue(section, tag, def);
762 }
763
764 return sections[section][tag];
765 } /* getValueP */
766
767}; /* class Config */
768
769
770} /* namespace */
771
772#endif /* ASYNC_CONFIG_INCLUDED */
773
774
775
776/*
777 * This file has not been truncated
778 */
779
bool getValue(const std::string &section, const std::string &tag, const Rsp &min, const Rsp &max, Rsp &rsp, bool missing_ok=false) const
Get a range checked variable value.
Config(void)
Default constuctor.
std::list< std::string > listSection(const std::string &section)
Return the name of all the tags in the given section.
sigc::signal< void(const std::string &, const std::string &)> valueUpdated
A signal that is emitted when a config value is updated.
void setValue(const std::string &section, const std::string &tag, const Container< Rsp, std::allocator< Rsp > > &c)
Set the value of a configuration variable (sequence container).
void subscribeValue(const std::string &section, const std::string &tag, const Rsp &def, F func)
Subscribe to the given configuration variable.
bool getValue(const std::string &section, const std::string &tag, Container< Key, std::less< Key >, std::allocator< Key > > &c, bool missing_ok=false) const
Get the value of the given config variable into keyed container.
bool getValue(const std::string &section, const std::string &tag, Rsp &rsp, bool missing_ok=false) const
Get the value of the given configuration variable.
void subscribeValue(const std::string &section, const std::string &tag, const Container< Rsp, std::allocator< Rsp > > &def, F func)
Subscribe to the given configuration variable (sequence).
bool getValue(const std::string &section, const std::string &tag, Container< Key, T, Compare, Allocator > &c, char sep=':', bool missing_ok=false) const
Get value of given config variable into associative container.
bool open(const std::string &name)
Open the given config file.
bool getValue(const std::string &section, const std::string &tag, Container< Value, std::allocator< Value > > &c, bool missing_ok=false) const
Get the value of the given config variable into container.
~Config(void)
Destructor.
const std::string & getValue(const std::string &section, const std::string &tag) const
Return the string value of the given configuration variable.
void setValue(const std::string &section, const std::string &tag, const Rsp &value)
Set the value of a configuration variable (generic type).
bool getValue(const std::string &section, const std::string &tag, std::string &value, bool missing_ok=false) const
Get the string value of the given configuration variable.
bool getValue(const std::string &section, const std::string &tag, char &value, bool missing_ok=false) const
Get the char value of the given configuration variable.
std::list< std::string > listSections(void)
Return the name of all configuration sections.
void setValue(const std::string &section, const std::string &tag, const std::string &value)
Set the value of a configuration variable.
void subscribeValue(const std::string &section, const std::string &tag, const char *def, F func)
Subscribe to the given configuration variable (char*).
Namespace for the asynchronous programming classes.