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 #include <stdlib.h>
44 
45 #include <drain/Log.h>
46 #include <drain/String.h>
47 #include <drain/Type.h>
48 
49 #include "Dictionary.h"
50 
51 #include "FlagBase.h"
52 
53 namespace drain {
54 
55 
56 /*
57 template <typename E>
58 const SprinterLayout drain::FlaggerBase<E>::dictLayout = {",", "?", "=", ""};
59 */
60 
61 
62 
63 
64 
66 
69 template <typename E>
70 class SingleFlagger : public FlaggerBase<E,E> {
71 
72 public:
73 
74  //typedef typename FlaggerBase<E>::dict_value_t dict_value_t;
75  typedef E value_t;
76  typedef E storage_t;
77 
79  // typedef typename EnumDict<E>::dict_t dict_t;
80  typedef typename flagger_t::dict_t dict_t;
81  typedef typename dict_t::key_t key_t; // ~string
82 
83 protected:
84 
85  const dict_t & dict;
86  // dict_t ownDict;
87 
88 public:
89 
90  virtual
91  const dict_t & getDict() const override {
92  return dict;
93  };
94 
95 
96  inline
97  SingleFlagger(const dict_t & dict) : dict(dict) {
98  };
99 
100  /***
101  *
102  * storage_t == value_t
103  */
104  inline
105  SingleFlagger(const dict_t & dict, const storage_t &v) : dict(dict) {
106  this->value = v;
107  };
108 
109 
110  /***
111  *
112  * storage_t == value_t
113  */
114  inline
115  SingleFlagger(const dict_t & dict, storage_t & v, char sep=',') : flagger_t(v, sep), dict(dict){
116  };
117 
118 
119  virtual inline
120  ~SingleFlagger(){};
121 
122 
124  virtual
125  bool isSet(const storage_t & x) const override {
126  return (this->value == x);
127  };
128 
129  template <class T>
130  inline
131  SingleFlagger<E> & operator=(const T & v){
132  this->set(v);
133  return *this;
134  }
135 
137  virtual inline
138  const key_t & str() const override {
139  return this->getDict().getKey(this->value);
140  }
141 
142 protected:
143 
145 
150  virtual
151  void assign(const std::string & key) override {
152 
153  // NO this->set(s);
154 
155  if ((key.find(',')!= std::string::npos)||(key.find('|')!= std::string::npos)){
156  Logger mout(__FILE__, __FUNCTION__);
157  mout.unimplemented<LOG_ERR>(__FILE__, ':', TypeName<E>::str(), ": multi-key arg: '"+ key, "', for single-flagger: ", sprinter(this->getDict().getKeys()));
158  }
159 
160  if (this->getDict().hasKey(key)){
161  this->value = static_cast<storage_t>(this->getDict().getValue(key)); // Cast needed (only) if MultiFlagger converts enum value_t -> storage_t
162  }
163  else {
164  Logger mout(__FILE__, __FUNCTION__);
165  value_t v = static_cast<value_t>(atoi(key.c_str()));
166  if (!this->getDict().hasValue(v)){
167  mout.suspicious("value: ", v, " corresponds to no value in dict:", this->getDict());
168  //mout.error(__FILE__, ':', TypeName<E>::str(), ": no such key: '"+ key, "', keys=", sprinter(this->getDict().getKeys()));
169  mout.error("Flagger@", TypeName<E>::str(), ": no such key: '"+ key, "', dict=", sprinter(this->getDict()));
170  }
171  // this->value = FlagResolver::getIntValue(this->getDict(), key); // SingleFlagger does not like this.
172  // throw std::runtime_error(std::string("Dictionary[") + typeid(dict_value_t).name()+ "]: no such key: "+ key);
173  this->value = v;
174  }
175 
176  };
177 
178 
179 
180 };
181 
182 template <typename E>
183 inline
184 std::ostream & operator<<(std::ostream & ostr, const drain::SingleFlagger<E> & flagger) {
185  ostr << flagger.str();
186  return ostr;
187 }
188 
189 
191 
198 template <typename E, typename T=size_t>
199 class MultiFlagger : public FlaggerBase<E,T> {
200 
201 public:
202 
203  typedef E value_t;
204  //typedef typename FlaggerBase<E,size_t>::storage_t storage_t;
205  typedef T storage_t;
206  typedef FlaggerBase<E,T> flagger_t;
207  typedef typename flagger_t::dict_t dict_t;
208  typedef typename dict_t::key_t key_t; // ~string
209 
210  /*
211  inline
212  MultiFlagger(){
213  };
214 
215  inline
216  MultiFlagger(storage_t & v, char sep=',') : flagger_t(v,sep){
217  };
218 
219  template <typename ... V>
220  inline
221  MultiFlagger(const V &... args){
222  set(args...);
223  // this->value = v;
224  };
225  */
226 
227  inline
228  MultiFlagger(const dict_t & dict) : dict(dict) {
229  };
230 
231  template <typename ... V>
232  inline
233  MultiFlagger(const dict_t & dict, const V &... args) : dict(dict) {
234  set(args...);
235  };
236 
240  inline
241  MultiFlagger(const dict_t & dict, storage_t & target, char sep=',') : flagger_t(target, sep), dict(dict){
242  };
243 
244  virtual inline
245  ~MultiFlagger(){};
246 
247 
248 
249 public:
250 
251  virtual
252  const dict_t & getDict() const override {
253  return dict;
254  };
255 
257  virtual
258  bool isSet(const storage_t & x) const override {
259  return ((this->value & x) == x);
260  };
261 
263  void unset(const storage_t & x){
264  this->value = (this->value & ~x);
265  //return ((this->value & x) == x);
266  }
267 
269 
275  template <typename ... V>
276  inline
277  void set(const V &... args) {
278  this->reset();
279  add(args...);
280  }
281 
282 
284  template <typename V, typename ...VV>
285  inline
286  void add(const V & arg, const VV &... args) {
287  //std::cerr << __FUNCTION__ << ':' << arg << std::endl;
288  addOne(arg);
289  add(args...);
290  }
291 
293  virtual
294  const key_t & str() const override {
295  const dict_t & dict = this->getDict();
296  currentStr = FlagResolver::getKeys(dict, this->value, this->separator);
297  return currentStr;
298  }
299 
300 
302  virtual
303  std::string & str(){
304  return currentStr; // CHECK USAGE
305  }
306 
308  /*
309  virtual
310  std::string str(const dict_value_t & value){
311  return FlagResolver::getKeys(this->getDict(), value, this->separator);
312  }
313  */
315  /*
316  inline
317  void update(){
318  assign(currentStr);
319  }
320  */
321 
322 
323 protected:
324 
325  const dict_t & dict;
326  // dict_t ownDict;
327 
329  virtual
330  void assign(const std::string & s) override {
331  const dict_t & dict = this->getDict();
332  this->value = FlagResolver::getIntValue(dict, s, this->separator); // uses dict.separator if needed
333  }
334 
335 
336  inline
337  void add(){};
338 
339  /*
340  virtual inline
341  void addOne(const value_t & value){
342  // why OR op in dvalue
343  // this->value = static_cast<dict_value_t>((dvalue_t)this->value | (dvalue_t)value);
344  this->value |= static_cast<value_t>(value);
345  }
346  */
347 
348 
349  inline
350  void addOne(const key_t & key){
351 
352  // Resolves also "" and numeric keys.
353  this->value |= FlagResolver::getIntValue(this->getDict(), key, this->separator);
354 
355  /*
356  if (key.empty())
357  return;
358 
359  //dict_value_t v = ::atoi(key);
360 
361  const dict_t & dict = this->getDict();
362  if (dict.hasKey(key)){
363  //this->value |= (dict_value_t)dict.getValue(key); // why cast? dvalue_t -> value_t
364  addOne((dict_value_t)dict.getValue(key));
365  }
366  else {
368  Logger mout(__FILE__, __FUNCTION__);
369  mout.error(TypeName<E>::get(), ": no such key: '"+ key, "', keys=", sprinter(this->getDict().getKeys()));
370  // throw std::runtime_error(std::string("Dictionary/") + typeid(dict_value_t).name()+ ": no such key: "+ key);
371  }
372  */
373  }
374 
375  template <typename T2>
376  inline
377  void addOne(const T2 & value){
378  // why OR op in dvalue
379  // this->value = static_cast<dict_value_t>((dvalue_t)this->value | (dvalue_t)value);
380  this->value |= static_cast<value_t>(value);
381  }
382 
383 
384  mutable
385  std::string currentStr;
386  // key_t currentStr;
387 
388 
389 };
390 
391 
392 
393 template <typename E,typename T>
394 inline
395 std::ostream & operator<<(std::ostream & ostr, const drain::MultiFlagger<E,T> & flagger) {
396  return FlagResolver::keysToStream(flagger.getDict(), flagger.getValue(), ostr);
397 }
398 
399 
400 
401 
402 
403 
404 
405 
407 
414 /*
415 template <class F>
416 class Flagger2 : public F { // Consider renaming to IntFlagger !
417 
418 public:
419 
420  typedef F fbase_t;
421  typedef typename fbase_t::value_t value_t;
422  typedef typename fbase_t::dict_t dict_t;
423 
424 
425  inline
426  Flagger2(const dict_t & dict, value_t & value, char sep=',') : fbase_t(dict, value, sep) { // , dict(dict){
427  }
428 
429  inline
430  Flagger2(const Flagger2<F> & flagger) : fbase_t(flagger.dict) { // DANGEROUS if tmp ref? : dict(flagger.dict){
431  }
432 
433  template <class T>
434  inline
435  Flagger2<F> & operator=(const T & v){
436  this->set(v);
437  return *this;
438  }
439 
440 };
441 */
442 
444 
451 template <class F>
452 class Flags2 : public F {
453 
454 public:
455 
456  typedef F fbase_t;
457  typedef typename F::value_t value_t;
458  typedef typename F::dict_t dict_t;
459 
460 
461  virtual
462  const dict_t & getDict() const {
463  return dict;
464  };
465 
466  virtual
467  dict_t & getDict(){
468  return dict;
469  };
470 
471 
473 
477  inline
479  };
480 
482 
487  inline
488  Flags2(const std::initializer_list<typename dict_t::entry_t> & list) : dict(list){
489  };
490 
491  inline
492  Flags2(const Flags2<F> & flags) : dict(flags.dict){
493  }
494 
495  template <class T>
496  inline
497  Flags2<F> & operator=(const T & v){
498  this->set(v);
499  return *this;
500  }
501 
502 protected:
503 
504  // Consider inherited dictionary, through a wrapper (first inherit, to guarantee init ref validity?).
505  dict_t dict;
506 
507 
508 };
509 
510 
511 
512 } // drain::
513 
514 
515 #endif
Two-way mapping between strings and objects of template class T.
Definition: Dictionary.h:63
const K & getKey(const V &value, bool lenient=true) const
Identity mapping useful for type deduction of template arguments in functions.
Definition: Dictionary.h:172
bool hasValue(const V &value) const
Given a key, return the first value associated with it.
Definition: Dictionary.h:143
const V & getValue(const K &key, bool lenient=true) const
Given a key, return the first value associated with it.
Definition: Dictionary.h:149
static ivalue_t getIntValue(const drain::Dictionary< key_t, T > &dict, const std::string &keys, char separator=',')
Computes bitwise OR function on the numeric or alphabetic value(s) presented by a string.
Definition: FlagBase.h:199
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: FlagBase.h:278
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: FlagBase.h:266
Definition: FlagBase.h:361
virtual void set(const key_t &key)
Sets one or several flags.
Definition: FlagBase.h:423
Flagger with referenced/external dictionary accepting values of (integer) type T.
Definition: Flags.h:452
Flags2()
Definition: Flags.h:478
Flags2(const std::initializer_list< typename dict_t::entry_t > &list)
Constructor for relatively short dictionaries.
Definition: Flags.h:488
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:310
Logger & error(const TT &... args)
Echoes.
Definition: Log.h:414
Logger & unimplemented(const TT &... args)
Feature to be done. Special type of Logger::note().
Definition: Log.h:509
Logger & suspicious(const TT &... args)
A weak warning about something going possibly wrong.
Definition: Log.h:498
Definition: Flags.h:199
void unset(const storage_t &x)
Unset some bit(s).
Definition: Flags.h:263
MultiFlagger(const dict_t &dict, storage_t &target, char sep=',')
Definition: Flags.h:241
void add(const V &arg, const VV &... args)
Add bit values.
Definition: Flags.h:286
virtual void assign(const std::string &s) override
Split a string to separate keys and/or values and set them.
Definition: Flags.h:330
virtual bool isSet(const storage_t &x) const override
Return true, all the bits of argument x are set.
Definition: Flags.h:258
const dict_t & dict
Given only a numeric/enum value,.
Definition: Flags.h:325
void set(const V &... args)
Set bits, accepting numeric values or keys.
Definition: Flags.h:277
virtual const key_t & str() const override
For exporting values.
Definition: Flags.h:294
virtual std::string & str()
For importing values. After assignment, update() should be called. Experimental.
Definition: Flags.h:303
virtual const dict_t & getDict() const override
Returns the static dictionary created for this value_t .
Definition: Flags.h:252
Definition: Flags.h:70
virtual bool isSet(const storage_t &x) const override
Return true, if value is exactly x .
Definition: Flags.h:125
virtual const key_t & str() const override
String corresponding the current value. Returns empty, if not found.
Definition: Flags.h:138
virtual void assign(const std::string &key) override
Assign key. Expects a single key, not a combination of keys.
Definition: Flags.h:151
virtual const dict_t & getDict() const override
Returns the static dictionary created for this value_t .
Definition: Flags.h:91
Definition: DataSelector.cpp:1277
Definition: Type.h:542