Loading...
Searching...
No Matches
Flags.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31
32#ifndef DRAIN_FLAGS
33#define DRAIN_FLAGS
34
35#include <iostream>
36#include <iostream>
37//#include <typeinfo>
38#include <stdlib.h>
39
40#include <drain/Log.h>
41#include <drain/TypeName.h>
42
43#include "FlagBase.h"
44
45namespace drain {
46
47
48/*
49template <typename E>
50const SprinterLayout drain::FlaggerBase<E>::dictLayout = {",", "?", "=", ""};
51*/
52
53
54
55
56
58
61template <typename E>
62class SingleFlagger : public FlaggerBase<E,E> {
63
64public:
65
66 //typedef typename FlaggerBase<E>::dict_value_t dict_value_t;
67 typedef E value_t;
68 typedef E storage_t;
69
71 // typedef typename Enum<E>::dict_t dict_t;
72 typedef typename flagger_t::dict_t dict_t;
73 typedef typename dict_t::key_t key_t; // ~string
74
75protected:
76
77 const dict_t & dict;
78 // dict_t ownDict;
79
80public:
81
82 virtual
83 const dict_t & getDict() const override {
84 return dict;
85 };
86
87
88 inline
89 SingleFlagger(const dict_t & dict) : dict(dict) {
90 };
91
92 /***
93 *
94 * storage_t == value_t
95 */
96 inline
97 SingleFlagger(const dict_t & dict, const storage_t &v) : dict(dict) {
98 this->value = v;
99 };
100
101
102 /***
103 *
104 * storage_t == value_t
105 */
106 inline
107 SingleFlagger(const dict_t & dict, storage_t & v, char sep=',') : flagger_t(v, sep), dict(dict){
108 };
109
110
111 virtual inline
112 ~SingleFlagger(){};
113
114 // Explicit (not =deleted) despite the reference member 'dict': copy-constructing binds the
115 // new object's reference to the same (typically static, shared) dictionary as the source,
116 // which is fine; only copy-assignment would be unable to rebind it (and stays deleted).
117 SingleFlagger(const SingleFlagger &) = default;
118
120 virtual
121 bool isSet(const storage_t & x) const override {
122 return (this->value == x);
123 };
124
125 // Start copy Base
126 virtual inline
127 void set(const key_t & key){
128 if (key.empty())
129 return; // needed?
130 assign(key);
131 }
132
134 virtual inline
135 void set(const value_t & value){
136 this->value = value;
137 };
138
139 virtual inline
140 void set(const FlaggerBase<E> & flagger){
141 this->value = flagger.value;
142 }
143
144 // END Base
145
146 template <class T>
147 inline
148 SingleFlagger<E> & operator=(const T & v){
149 this->set(v);
150 return *this;
151 }
152
154 virtual inline
155 const key_t & str() const override {
156 return this->getDict().getKey(this->value);
157 }
158
159protected:
160
162
167 virtual
168 void assign(const std::string & key) override {
169
170 // NO this->set(s);
171
172 if ((key.find(',')!= std::string::npos)||(key.find('|')!= std::string::npos)){
173 Logger mout(__FILE__, __FUNCTION__);
174 mout.unimplemented<LOG_ERR>(__FILE__, ':', TypeName<E>::str(), ": multi-key arg: '"+ key, "', for single-flagger: ", sprinter(this->getDict().getKeys()));
175 }
176
177 if (this->getDict().hasKey(key)){
178 this->value = static_cast<storage_t>(this->getDict().getValue(key)); // Cast needed (only) if MultiFlagger converts enum value_t -> storage_t
179 }
180 else {
181 Logger mout(__FILE__, __FUNCTION__);
182 value_t v = static_cast<value_t>(atoi(key.c_str()));
183 if (!this->getDict().hasValue(v)){
184 mout.suspicious("value: ", v, " corresponds to no value in dict:", this->getDict());
185 //mout.error(__FILE__, ':', TypeName<E>::str(), ": no such key: '"+ key, "', keys=", sprinter(this->getDict().getKeys()));
186 mout.error("Flagger@", TypeName<E>::str(), ": no such key: '"+ key, "', dict=", sprinter(this->getDict()));
187 }
188 // this->value = FlagResolver::getIntValue(this->getDict(), key); // SingleFlagger does not like this.
189 // throw std::runtime_error(std::string("Dictionary[") + typeid(dict_value_t).name()+ "]: no such key: "+ key);
190 this->value = v;
191 }
192
193 };
194
195
196
197};
198
199template <typename E>
200inline
201std::ostream & operator<<(std::ostream & ostr, const SingleFlagger<E> & flagger) {
202 ostr << flagger.str();
203 return ostr;
204}
205
206DRAIN_TYPENAME_T(SingleFlagger,E);
207
209
216template <typename E, typename T=size_t>
217class MultiFlagger : public FlaggerBase<E,T> { // <E,FlagResolver::ivalue_t> { //
218
219public:
220
221 typedef E value_t;
222 typedef T storage_t;
224 //typedef FlagResolver::ivalue_t storage_t;
225 //typedef FlaggerBase<E,FlagResolver::ivalue_t> flagger_t;
226 typedef typename flagger_t::dict_t dict_t;
227 typedef typename dict_t::key_t key_t; // ~string
228
229
230 inline
231 MultiFlagger(const dict_t & dict) : dict(dict) {
232 };
233
234 template <typename ... V>
235 inline
236 MultiFlagger(const dict_t & dict, const V &... args) : dict(dict) {
237 set(args...);
238 }
239
243 inline
244 MultiFlagger(const dict_t & dict, storage_t & target, char sep=',') : flagger_t(target, sep), dict(dict){
245 };
246
247 virtual inline
248 ~MultiFlagger(){};
249
250 // Explicit (not =deleted) despite the reference member 'dict': copy-constructing binds the
251 // new object's reference to the same (typically static, shared) dictionary as the source,
252 // which is fine; only copy-assignment would be unable to rebind it (and stays deleted).
253 MultiFlagger(const MultiFlagger &) = default;
254
255
256 virtual inline
257 const dict_t & getDict() const override {
258 return dict;
259 };
260
262
266 virtual inline
267 bool isSet(const storage_t & x) const override {
268 return ((this->value & x) == x);
269 };
270
272 inline
273 bool isAnySet(const storage_t & x) const {
274 return ((this->value & x) != 0);
275 };
276
278 inline
279 void unset(const storage_t & x){
280 this->value = (this->value & ~x);
281 //return ((this->value & x) == x);
282 }
283
285
291 template <typename ... V>
292 inline
293 void set(const V &... args) {
294 this->reset();
295 add(args...);
296 }
297
298
300 template <typename V, typename ...VV>
301 inline
302 void add(const V & arg, const VV &... args) {
303 //std::cerr << __FUNCTION__ << ':' << arg << std::endl;
304 addOne(arg);
305 add(args...);
306 }
307
309 virtual
310 const key_t & str() const override {
311 // const dict_t & dict = this->getDict();
312 currentStr = FlagResolver::getKeys(this->getDict(), this->value, this->separator);
313 return currentStr;
314 }
315
316
318 virtual
319 std::string & str(){
320 // NEW: also non-const is updated
321 // const dict_t & dict = this->getDict();
322 currentStr = FlagResolver::getKeys(this->getDict(), this->value, this->separator);
323 return currentStr; // CHECK USAGE
324 }
325
326
327
328protected:
329
330 const dict_t & dict;
331
333 virtual
334 void assign(const std::string & s) override {
335 const dict_t & dict = this->getDict();
336 this->value = FlagResolver::getIntValue(dict, s, this->separator); // uses dict.separator if needed
337 }
338
339
340 inline
341 void add(){};
342
343 inline
344 void addOne(const key_t & key){
345 // Resolves also "" and numeric keys.
346 this->value |= FlagResolver::getIntValue(this->getDict(), key, this->separator);
347 }
348
349 // New
350 inline
351 void addOne(const storage_t & value){
352 this->value |= value;
353 }
354
355 template <typename T2>
356 inline
357 void addOne(const T2 & value){
358 // why OR op in dvalue
359 // this->value = static_cast<dict_value_t>((dvalue_t)this->value | (dvalue_t)value);
360 this->value |= static_cast<value_t>(value);
361 }
362
363 mutable
364 std::string currentStr;
365
366
367};
368
369
370
371template <typename E,typename T>
372inline
373std::ostream & operator<<(std::ostream & ostr, const drain::MultiFlagger<E,T> & flagger) { // ,T
374 return FlagResolver::keysToStream(flagger.getDict(), flagger.getValue(), ostr);
375}
376
377DRAIN_TYPENAME_T(MultiFlagger,E);
378
379
380
381
382
384
391template <class F>
392class Flags2 : public F {
393
394public:
395
396 typedef F fbase_t;
397 typedef typename F::value_t value_t;
398 typedef typename F::dict_t dict_t;
399
400
401 virtual
402 const dict_t & getDict() const {
403 return dict;
404 };
405
406 virtual
407 dict_t & getDict(){
408 return dict;
409 };
410
411
413
417 inline
419 };
420
422
427 inline
428 Flags2(const std::initializer_list<typename dict_t::entry_t> & list) : dict(list){
429 };
430
431 inline
432 Flags2(const Flags2<F> & flags) : dict(flags.dict){
433 }
434
435 template <class T>
436 inline
437 Flags2<F> & operator=(const T & v){
438 this->set(v);
439 return *this;
440 }
441
442protected:
443
444 // Consider inherited dictionary, through a wrapper (first inherit, to guarantee init ref validity?).
445 dict_t dict;
446
447
448};
449
450
451
452} // drain::
453
454
455#endif
Two-way mapping between strings and objects of template class T.
Definition Dictionary.h:61
const K & getKey(const V &value, bool lenient=true) const
Identity mapping useful for type deduction of template arguments in functions.
Definition Dictionary.h:170
const V & getValue(const K &key, bool lenient=true) const
Given a key, return the first value associated with it.
Definition Dictionary.h:147
bool hasValue(const V &value) const
Given a key, return the first value associated with it.
Definition Dictionary.h:141
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:195
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:276
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:264
Definition FlagBase.h:359
Flagger with own dictionary, and accepting values of (integer) type T.
Definition Flags.h:392
Flags2()
Definition Flags.h:418
Flags2(const std::initializer_list< typename dict_t::entry_t > &list)
Constructor for relatively short dictionaries.
Definition Flags.h:428
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:326
Logger & error(const TT &... args)
Echoes.
Definition Log.h:426
Logger & suspicious(const TT &... args)
A weak warning about something going possibly wrong.
Definition Log.h:510
Logger & unimplemented(const TT &... args)
Feature to be done. Special type of Logger::note().
Definition Log.h:521
Definition Flags.h:217
virtual std::string & str()
For importing values. After assignment, update() should be called. Experimental.
Definition Flags.h:319
void unset(const storage_t &x)
Unset some bit(s).
Definition Flags.h:279
MultiFlagger(const dict_t &dict, storage_t &target, char sep=',')
Definition Flags.h:244
void add(const V &arg, const VV &... args)
Add bit values.
Definition Flags.h:302
virtual void assign(const std::string &s) override
Split a string to separate keys and/or values and set them.
Definition Flags.h:334
virtual bool isSet(const storage_t &x) const override
Return true, all the bits of argument x are set.
Definition Flags.h:267
bool isAnySet(const storage_t &x) const
Return true, all the bits of argument x are set.
Definition Flags.h:273
void set(const V &... args)
Set bits, accepting numeric values or keys.
Definition Flags.h:293
virtual const dict_t & getDict() const override
Returns the static dictionary created for this value_t .
Definition Flags.h:257
virtual const key_t & str() const override
For exporting values.
Definition Flags.h:310
Definition Flags.h:62
virtual void set(const value_t &value)
Set a single flag.
Definition Flags.h:135
virtual bool isSet(const storage_t &x) const override
Return true, if value is exactly x .
Definition Flags.h:121
virtual const dict_t & getDict() const override
Returns the static dictionary created for this value_t .
Definition Flags.h:83
virtual const key_t & str() const override
String corresponding the current value. Returns empty, if not found.
Definition Flags.h:155
virtual void assign(const std::string &key) override
Assign key. Expects a single key, not a combination of keys.
Definition Flags.h:168
Definition Data.h:1473
std::ostream & operator<<(std::ostream &ostr, const PlainData< DT > &d)
Definition Data.h:631
Default implementation.
Definition TypeName.h:54
static const std::string & str()
Default implementation: name returned by std::type_info::name()
Definition TypeName.h:68