Flags.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 
32 #ifndef DRAIN_FLAGS
33 #define DRAIN_FLAGS
34 
35 #include <iostream>
36 #include <list>
37 #include <iterator>
38 #include <iostream>
39 #include <list>
40 #include <sstream>
41 #include <stdexcept>
42 #include <typeinfo>
43 
44 #include <drain/Log.h>
45 #include <drain/String.h>
46 #include <drain/Type.h>
47 
48 #include "Dictionary.h"
49 
50 namespace drain {
51 
53 
56 class FlagResolver {
57 
58 public:
59 
60  // Definite
61  typedef std::string key_t;
62 
63  // "Recommended" storage type for both numeric and enumerated-type flags.
64  typedef unsigned long int ivalue_t;
65 
68 
69  static
70  const ivalue_t ALL; // = std::numeric_limits<FlagResolver::ivalue_t>::max();
71 
72 
74 
79  // Consider: lenient: if true, bypasses unknown keys silently, otherwise throws exception
80  // Consider: FLAG for keys only, and for numerics throw exception
81  template <typename T>
82  static
83  ivalue_t getValue(const drain::Dictionary<key_t,T> & dict, const std::string & key, char separator=',');
84 
86  template <typename T>
87  static
88  std::string getKeys(const drain::Dictionary<key_t,T> & dict, ivalue_t, char separator=',');
89 
91  template <typename T>
92  static
93  std::ostream & keysToStream(const drain::Dictionary<key_t,T> &dict, ivalue_t value, std::ostream & ostr, char separator=',');
94 
96 
101  template <typename T, typename V>
102  static
103  void valuesToList(ivalue_t value, const drain::Dictionary<key_t,T> &dict, std::list<V> & container);
104 
106 
109  template <typename T>
110  static
111  ivalue_t addEntry(drain::Dictionary<key_t,T> & dict, const key_t & key, ivalue_t i=0);
112 
113 
115 
118  template <typename T>
119  static
120  ivalue_t getFreeBit(const drain::Dictionary<key_t,T> & dict);
121 
122 
123 };
124 
125 
126 template <typename T>
127 typename FlagResolver::ivalue_t FlagResolver::getFreeBit(const drain::Dictionary<key_t,T> & dict){
128 
129  drain::Logger mout(__FILE__, __FUNCTION__);
130 
131  // Bit mask containing all the values.
132  ivalue_t currentMask = 0;
133  for (const auto & entry: dict){
134  currentMask = currentMask | entry.second;
135  }
136 
137  mout.debug2("sum:" , currentMask );
138 
139  ivalue_t i = 1;
140  while ((i&currentMask) > 0){
141  mout.debug3("checking bit:" , i , " vs.\t" , currentMask );
142  //full = (full>>1);
143  i = (i<<1);
144  }
145  /*
146  while (full>0){
147  mout.debug2("checking bit:" , i , " vs.\t" , full );
148  full = (full>>1);
149  i = (i<<1);
150  }
151  */
152 
153  mout.debug("released: " , i );
154 
155  return i;
156 
157 }
158 
159 /*
160 template <typename T>
161 typename FlagResolver::ivalue_t FlagResolver::addEntry(drain::Dictionary<key_t,T> &dict, const typename dict_t::key_t & key){
162 
163  drain::Logger mout(__FILE__, __FUNCTION__);
164  if (dict.hasKey(key)){
165  mout.info(key , " already in dict: " , dict );
166  return dict.getValue(key);
167  }
168 
169  return addEntry(dict, key, )
170 }
171 */
172 
173 template <typename T>
174 typename FlagResolver::ivalue_t FlagResolver::addEntry(drain::Dictionary<key_t,T> &dict, const typename dict_t::key_t & key, ivalue_t i){
175 
176  drain::Logger mout(__FILE__, __FUNCTION__);
177 
178  if (dict.hasKey(key)){
179  mout.info(key , " already in dict: " , dict );
180  return dict.getValue(key);
181  }
182 
183  if (i==0)
184  i = getFreeBit(dict);
185 
186  if (i>0){
187  dict.add(key, i);
188  }
189  else {
190  mout.warn(key , " could not get a valid (non-zero) bit flag for dict: " , dict );
191  }
192 
193  return i;
194 };
195 
196 
197 template <typename T>
198 typename FlagResolver::ivalue_t FlagResolver::getValue(const drain::Dictionary<key_t,T> & dict, const std::string & args, char separator){
199 
200  drain::Logger mout(__FILE__, __FUNCTION__);
201 
202  FlagResolver::ivalue_t v = 0;
203 
204  std::list<key_t> keys;
205 
206  if (!separator)
207  separator = dict.separator;
208 
209 
210  drain::StringTools::split(args, keys, separator);
211 
212  for (const key_t & key: keys){
213 
214  if (key == ""){
215  continue;
216  }
217  else if (key == "0"){
218  v = 0; // TODO if resets and sets?
219  continue;
220  }
221  // mout.warn(" '" , *it , "'" );
222 
223  //typename dict_t::const_iterator dit = dict.findByKey(key);
224  typename drain::Dictionary<key_t,T>::const_iterator dit = dict.findByKey(key);
225 
226  if (dit != dict.end()){ // String key match,
227  // Numeric value for an alphabetic key was found
228  v = (v | static_cast<FlagResolver::ivalue_t>(dit->second) );
229  }
230  else {
231  // Numeric value
232  FlagResolver::ivalue_t x = 0;
233  std::stringstream sstr(key);
234  sstr >> x; // FIX if empty
235  if (x == 0){
236  // String "0" handled already above
237  // Consider: could advice keys only: sprinter(dict.getKeys()
238  // Or key-value pairs: sprinter(dict)
239  // static const SprinterLayout cmdArgLayout = {",", "?", "=", ""};
240  // mout.error("key '", key, "' not found in: ", sprinter(dict, Sprinter::cmdLineLayout));
241  // mout.error("key '", key, "' not föund in: ", sprinter(dict.getContainer(), cmdArgLayout) );
242  mout.error("key '", key, "' not found in: ", dict);
243  //throw std::runtime_error(key, ": key not found in Flags, dict: ", dict);
244  }
245  v = v | x;
246  // Nice to know
247  /*
248  dict_t::const_iterator vit = dictionaryRef.findByValue(v);
249  if (vit != dictionaryRef.end()){
250  std::cout << "(assigned key '" << vit->second << "')\n"; // or vit->first?
251  }
252  */
253  }
254  }
255 
256  return v;
257 }
258 
259 
261 template <typename T>
262 std::string FlagResolver::getKeys(const drain::Dictionary<key_t,T> &dict, ivalue_t v, char separator){
263  std::stringstream sstr;
264  keysToStream(dict, v, sstr, separator);
265  return sstr.str();
266 }
267 
268 
269 
270 //
271 
273 template <typename T>
274 std::ostream & FlagResolver::keysToStream(const drain::Dictionary<key_t,T> &dict, ivalue_t value, std::ostream & ostr, char separator) {
275 
276  /* note: instead of shifting bits of this->value, traverses the dictionary which can contain
277  - combined values
278  - repeated values (aliases)
279  */
280 
281  if (!separator)
282  separator = dict.separator;
283 
284  char sep = 0;
285 
286  for (const auto & entry: dict){
287  if ((entry.second > 0) && ((entry.second & value) == entry.second)){ // fully covered in value
288  if (sep)
289  ostr << sep;// "{" << (int)(sep) << "}" <<
290  else
291  sep = separator;
292  ostr << entry.first;
293  }
294  else {
295 
296  }
297  }
298 
299  return ostr;
300 }
301 
302 
303 
304 
305 template <typename T, typename V>
306 void FlagResolver::valuesToList(ivalue_t value, const drain::Dictionary<key_t,T> &dict, std::list<V> & container){
307  for (const auto & entry: dict){
308  if ((entry.second > 0) && ((entry.second & value) == entry.second)){ // fully covered in value
309  // ostr << entry.first;
310  container.push_back(static_cast<V>(entry.second));
311  // container.push_back(entry.first);
312  }
313  }
314 }
315 
316 
317 
318 // NEW 2022/2023
319 
320 
321 // typedef drain::Dictionary<std::string,unsigned long> FlaggerDict;
322 
323 // #define FlaggerDict FlagResolver::dict_t
324 
353 template <typename E=std::size_t> //, typename D=drain::Dictionary<std::string,unsigned long> >
354 class FlaggerBase {
355 
356 public:
357 
358  //static
359  //const SprinterLayout dictLayout = {",", "?", "=", ""};
360 
361  // Manifested numeric type (enum or unsigned integer)
362  typedef E value_t;
363 
365  typedef typename dict_t::key_t key_t; // ~string
366 
367  // Practical "storage" value
368  typedef typename dict_t::value_t dict_value_t;
369 
370  // Rember to add an initialized unit: template<> SingleFlagger<...>::dict = {{...,...}, ...}
371  // static const dict_t dict;
372 
376  inline
377  FlaggerBase(): value(ownValue), separator(','), ownValue((dict_value_t)0){
378  }
379 
381 
384  inline
385  FlaggerBase(dict_value_t & v): value(v), separator(','){
386  }
387 
388  /* Risky? (Ambiguous)
389  inline
390  FlaggerBase(const dict_value_t & v): value(ownValue), ownValue(v) {
391  }
392  */
393 
394  virtual inline
395  ~FlaggerBase(){
396  }
397 
398  virtual
399  const dict_t & getDict() const = 0;
400 
401  void reset(){
402  this->value = dict_value_t(0);
403  };
404 
405  virtual
406  inline
407  void set(const key_t & key){
408 
409  if (key.empty())
410  return;
411 
412  if (this->getDict().hasKey(key)){
413  this->value = (dict_value_t)this->getDict().getValue(key); // why cast? dvalue_t -> dict_value_t
414  }
415  else {
416  this->value = FlagResolver::getValue(this->getDict(), key);
417  //Logger mout(__FILE__, __FUNCTION__);
418  // mout.error(TypeName<E>::str(), ": no such key: '"+ key, "', keys=", sprinter(this->getDict().getKeys()));
419  // throw std::runtime_error(std::string("Dictionary[") + typeid(dict_value_t).name()+ "]: no such key: "+ key);
420  }
421  }
422 
423  virtual inline
424  void set(const dict_value_t & value){
425  this->value = value;
426  };
427 
428  virtual inline
429  void set(const FlaggerBase<E> & flagger){
430  this->value = flagger.value;
431  }
432 
433 
434  virtual
435  void assign(const std::string & s) = 0;
436 
438  inline
439  bool isSet(dict_value_t x) const {
440  return (value & x) != 0;
441  };
442 
443  inline
444  bool isSet(const key_t & key) const {
445  return isSet(getDict().getValue(key));
446  };
447 
448  inline
449  const dict_value_t & getValue() const {
450  return value;
451  }
452 
454  /*
455  inline
456  std::string getKeys(char separator=0) const {
457  return FlagResolver::getKeys(dictionary, value, separator ? separator : this->separator);
458  }
459  */
460 
461 
463  inline
464  operator const dict_value_t & () const {
465  return value;
466  }
467 
468  inline
469  operator dict_value_t & () {
470  return value;
471  }
472 
474  virtual
475  const key_t & str() const = 0;
476 
477  // String
478  operator const key_t & () const {
479  return str();
480  }
481 
482  // Own or external value.
483  dict_value_t & value;
484 
485  char separator;
486 
487  void debug(std::ostream & ostr) const;
488 
489 private:
490 
491  // Own value, discarded if external value referenced.
492  dict_value_t ownValue = 0;
493 
494 
495 };
496 
497 template <typename E>
498 void drain::FlaggerBase<E>::debug(std::ostream & ostr) const {
499  //ostr << typeid(drain::FlaggerBase<E>).name() << ": value=" << getValue() << ", ";
500  ostr << drain::TypeName<E>::str() << ": value=" << getValue() << ", ";
501  FlagResolver::keysToStream(getDict(), getValue(), ostr) << ", ";
502  ostr << " dict: " << getDict();
503 }
504 
505 /*
506 template <typename E>
507 const SprinterLayout drain::FlaggerBase<E>::dictLayout = {",", "?", "=", ""};
508 */
509 
510 
511 template <typename E>
512 inline
513 std::ostream & operator<<(std::ostream & ostr, const drain::FlaggerBase<E> & flagger) {
514  return ostr << flagger.str(); // flags.keysToStream(ostr);
515 }
516 
517 template <typename E>
518 class SingleFlagger : public FlaggerBase<E> {
519 
520 public:
521 
522  //typedef typename FlaggerBase<E>::dict_value_t dict_value_t;
523  typedef E ivalue_t;
524 
526  typedef typename dict_t::key_t key_t; // ~string
527  typedef typename dict_t::value_t dvalue_t;
528 
529  inline
530  SingleFlagger(){
531  };
532 
533  inline
534  SingleFlagger(ivalue_t v){
535  this->value = v;
536  };
537 
538  virtual inline
539  ~SingleFlagger(){};
540 
541  virtual
542  void assign(const std::string & s){
543  this->set(s);
544  };
545 
546  template <class T>
547  inline
548  SingleFlagger<E> & operator=(const T & v){
549  this->set(v);
550  return *this;
551  }
552 
554  virtual inline
555  const key_t & str() const {
556  //static const key_t SINGLE="SINGLE";
557  //return SINGLE;
558  return this->getDict().getKey(this->value);
559  }
560 
561 
562 
563 };
564 
565 template <typename E>
566 inline
567 std::ostream & operator<<(std::ostream & ostr, const drain::SingleFlagger<E> & flagger) {
568  ostr << flagger.str();
569  return ostr;
570 }
571 
572 
573 template <typename E>
574 class MultiFlagger : public FlaggerBase<E> {
575 
576 public:
577 
580 
583  typedef typename dict_t::key_t key_t; // ~string
585  typedef typename dict_t::value_t dvalue_t;
586 
587  inline
588  MultiFlagger(){
589  };
590 
591  /*
592  inline
593  MultiFlagger(value_t v){
594  this->value = v;
595  };
596  */
597 
598  template <typename ... T>
599  inline
600  MultiFlagger(const T &... args){
601  set(args...);
602  // this->value = v;
603  };
604 
605  virtual inline
606  ~MultiFlagger(){};
607 
608 
610 
616  template <typename ... T>
617  inline
618  void set(const T &... args) {
619  this->reset();
620  //this->value = 0;
621  add(args...);
622  }
623 
625 
637  virtual
638  void assign(const std::string & s) {
639  const dict_t & dict = this->getDict();
640  this->value = (dict_value_t)FlagResolver::getValue(dict, s, this->separator); // uses dict.separator if needed
641  }
642 
643 
645  template <typename T, typename ... TT>
646  inline
647  void add(const T & arg, const TT &... args) {
648  //std::cerr << __FUNCTION__ << ':' << arg << std::endl;
649  addOne(arg);
650  add(args...);
651  }
652 
653 
654 
656  virtual
657  const key_t & str() const {
658  const dict_t & dict = this->getDict();
659  currentStr = FlagResolver::getKeys(dict, this->value, this->separator);
660  return currentStr;
661  }
662 
664  /*
665  virtual
666  std::string str(const dict_value_t & value){
667  return FlagResolver::getKeys(this->getDict(), value, this->separator);
668  }
669  */
670 
672  virtual
673  std::string & str(){
674  return currentStr;
675  }
676 
678  /*
679  inline
680  void update(){
681  assign(currentStr);
682  }
683  */
684 
685 
686 
687 protected:
688 
689  inline
690  void add(){};
691 
692  virtual inline
693  void addOne(const dict_value_t & value){
694  // why OR op in dvalue
695  // this->value = static_cast<dict_value_t>((dvalue_t)this->value | (dvalue_t)value);
696  this->value |= static_cast<dict_value_t>(value);
697  }
698 
699  inline
700  void addOne(const key_t & key){
701 
702  // Resolves also "" and numeric keys.
703  this->value |= FlagResolver::getValue(this->getDict(), key, this->separator);
704 
705  /*
706  if (key.empty())
707  return;
708 
709  //dict_value_t v = ::atoi(key);
710 
711  const dict_t & dict = this->getDict();
712  if (dict.hasKey(key)){
713  //this->value |= (dict_value_t)dict.getValue(key); // why cast? dvalue_t -> value_t
714  addOne((dict_value_t)dict.getValue(key));
715  }
716  else {
718  Logger mout(__FILE__, __FUNCTION__);
719  mout.error(TypeName<E>::get(), ": no such key: '"+ key, "', keys=", sprinter(this->getDict().getKeys()));
720  // throw std::runtime_error(std::string("Dictionary/") + typeid(dict_value_t).name()+ ": no such key: "+ key);
721  }
722  */
723  }
724 
725 
726  mutable
727  std::string currentStr;
728  // key_t currentStr;
729 
730 
731 };
732 
733 
734 
735 template <typename E>
736 inline
737 std::ostream & operator<<(std::ostream & ostr, const drain::MultiFlagger<E> & flagger) {
738  return FlagResolver::keysToStream(flagger.getDict(), flagger.getValue(), ostr);
739 }
740 
741 
742 
743 template <class E>
744 struct EnumDict {
745 
747 
748  static
749  const dict_t dict;
750 };
751 
753 
762 template <class F> // F =SingleFlagger<E>
763 class EnumFlagger : public F {
764 
765 public:
766 
767  typedef F fbase_t;
768  typedef typename fbase_t::value_t value_t;
769  typedef FlagResolver::ivalue_t ivalue_t;
770 
771  inline
772  EnumFlagger(){
773  }
774 
775  /*
776  inline
777  EnumFlagger(value_t v): fbase_t(v) {
778  }
779  */
780 
781  template <typename ... T>
782  inline
783  EnumFlagger(const T & ... arg): fbase_t(arg...) { // designed for MultiFlagger
784  }
785 
786 
788 
793  virtual
794  const typename FlaggerBase<value_t>::dict_t & getDict() const {
796  };
797 
798  // risen ... void getValues(std::list<EnumFlagger::value_t> & container);
799 
800 
802 
806  static
807  ivalue_t getValueNEW(const std::string & key){
808  return (ivalue_t)EnumDict<value_t>::dict.getValue(key);
809  };
810 
811  static inline
812  std::string getKeysNEW2(const value_t & value, char separator = ','){
813  return FlagResolver::getKeys(EnumDict<value_t>::dict, value, separator);
814  }
815 
827  inline
829  this->set(flagger.value);
830  return *this;
831  }
832 
833  template <class T>
834  inline
835  EnumFlagger<F> & operator=(const T & v){
836  this->set(v);
837  return *this;
838  }
839 
840  inline
841  operator value_t() const {
842  return static_cast<value_t>(this->value);
843  }
844 
845  inline
846  operator bool() const {
847  return static_cast<ivalue_t>(this->value) != 0;
848  }
849 
850 };
851 
852 
853 
855 
862 template <class F>
863 class Flagger2 : public F { // Consider renaming to IntFlagger !
864 
865 public:
866 
867  typedef F fbase_t;
868  typedef typename fbase_t::value_t value_t;
869  typedef typename fbase_t::dict_t dict_t;
870 
871  virtual
872  const dict_t & getDict() const {
873  return dict;
874  };
875 
876  inline
877  Flagger2(const dict_t & dict) : dict(dict){
878  }
879 
880  inline
881  Flagger2(const Flagger2<F> & flagger) : dict(flagger.dict){
882  }
883 
884  template <class T>
885  inline
886  Flagger2<F> & operator=(const T & v){
887  this->set(v);
888  return *this;
889  }
890 
891 protected:
892 
893  const dict_t & dict;
894 
895 
896 };
897 
899 
906 template <class F>
907 class Flags2 : public F {
908 
909 public:
910 
911  typedef F fbase_t;
912  typedef typename fbase_t::value_t value_t;
913  typedef typename fbase_t::dict_t dict_t;
914 
915 
916  virtual
917  const dict_t & getDict() const {
918  return dict;
919  };
920 
921  virtual
922  dict_t & getDict(){
923  return dict;
924  };
925 
926 
928 
932  inline
934  };
935 
937 
942  inline
943  Flags2(std::initializer_list<typename dict_t::entry_t> list) : dict(list){
944  };
945 
946  inline
947  Flags2(const Flags2<F> & flags) : dict(flags.dict){
948  }
949 
950  template <class T>
951  inline
952  Flags2<F> & operator=(const T & v){
953  this->set(v);
954  return *this;
955  }
956 
957 protected:
958 
959  dict_t dict;
960 
961 
962 };
963 
964 
965 
966 } // drain::
967 
968 
969 #endif
const V & getValue(const K &key) const
Given a key, return the first value associated with it.
Definition: Dictionary.h:149
const K & getKey(const V &value) const
Given a value, return the first key associated with it.
Definition: Dictionary.h:161
Flagger accepting values of enum type E.
Definition: Flags.h:763
virtual const FlaggerBase< value_t >::dict_t & getDict() const
Returns the static dictionary created for this value_t .
Definition: Flags.h:794
EnumFlagger< F > & operator=(const EnumFlagger< F > &flagger)
Definition: Flags.h:828
static ivalue_t getValueNEW(const std::string &key)
Return the integer value corresponding to a key.
Definition: Flags.h:807
Referencing a dictionary of binary values: {"A",1: "B":2, "C": 4, "D": 8, ...} resolves two-way mappi...
Definition: Flags.h:56
drain::Dictionary< key_t, ivalue_t > dict_t
"Recommended" dictionary type. All the methods are templates, however.
Definition: Flags.h:67
static std::ostream & keysToStream(const drain::Dictionary< key_t, T > &dict, ivalue_t value, std::ostream &ostr, char separator=',')
Write keys in a stream, in numeric order.
Definition: Flags.h:274
static ivalue_t getValue(const drain::Dictionary< key_t, T > &dict, const std::string &key, char separator=',')
Computes bitwise OR function on the numeric or alphabetic value(s) presented by a string.
Definition: Flags.h:198
static void valuesToList(ivalue_t value, const drain::Dictionary< key_t, T > &dict, std::list< V > &container)
Given a bit vector (integer value), extracts separate flag values to a list.
Definition: Flags.h:306
static ivalue_t addEntry(drain::Dictionary< key_t, T > &dict, const key_t &key, ivalue_t i=0)
Add a new entry in the dictionary.
static ivalue_t getFreeBit(const drain::Dictionary< key_t, T > &dict)
Return an interger (bit vector) with a new, previously unused value.
Definition: Flags.h:127
static std::string getKeys(const drain::Dictionary< key_t, T > &dict, ivalue_t, char separator=',')
Given an integer, retrieves dictionary keys corresponding to each index of set bits.
Definition: Flags.h:262
Flagger with referenced/external dictionary accepting values of (integer) type T.
Definition: Flags.h:863
Definition: Flags.h:354
FlaggerBase(dict_value_t &v)
Own value will be unused (and invisible).
Definition: Flags.h:385
virtual const key_t & str() const =0
String corresponding the current value. Returns empty, if not found.
bool isSet(dict_value_t x) const
Checks if a given bit, or any of given bits, is set.
Definition: Flags.h:439
Flagger with own dictionary, and accepting values of (integer) type T.
Definition: Flags.h:907
Flags2(std::initializer_list< typename dict_t::entry_t > list)
Constructor for relatively short dictionaries.
Definition: Flags.h:943
Flags2()
Definition: Flags.h:933
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:308
Logger & error(const TT &... args)
Echoes.
Definition: Log.h:412
Logger & debug(const TT &... args)
Public, yet typically used "internally", when TIMING=true.
Definition: Log.h:676
Logger & debug2(const TT &... args)
Debug information.
Definition: Log.h:686
Definition: Flags.h:574
void add(const T &arg, const TT &... args)
Add bit values.
Definition: Flags.h:647
virtual void assign(const std::string &s)
Set bits, accepting keys only.
Definition: Flags.h:638
virtual const key_t & str() const
For exporting values.
Definition: Flags.h:657
void add()
This should be called after assigning a string to & str() .
Definition: Flags.h:690
void set(const T &... args)
Set bits, accepting numeric values or keys.
Definition: Flags.h:618
dict_t::key_t key_t
Fundamental type of the bitvector - an integral type.
Definition: Flags.h:583
FlaggerBase< E >::dict_value_t dict_value_t
Fundamental type – in this case an enum.
Definition: Flags.h:579
virtual std::string & str()
Given only a numeric/enum value,.
Definition: Flags.h:673
dict_t::value_t dvalue_t
Fundamental type of the bitvector - an integral type.
Definition: Flags.h:585
Definition: Flags.h:518
virtual const key_t & str() const
String corresponding the current value. Returns empty, if not found.
Definition: Flags.h:555
static void split(const std::string &s, T &sequence, const C &separators, const std::string &trimChars=" \t\n")
Splits and trims a given std::string to a std Sequence.
Definition: String.h:309
Definition: DataSelector.cpp:1277
Definition: Flags.h:744