Loading...
Searching...
No Matches
Bank.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#ifndef DRAIN_BANK_H_
32#define DRAIN_BANK_H_
33
34//
35#include <drain/Log.h>
36#include <iostream>
37#include <map>
38
39
40#include "Cloner.h"
41#include "Flags.h"
42#include "Static.h"
43
44namespace drain
45{
46
47// NEW
48
49// Container storing entries of different classes derived from T.
61// TODO: remove resolve(key), lower it to superbank, with applying functions; redefine has(), get(), etc.
62template <class T, class K=std::string>
63class Bank : protected std::map<K, ClonerBase<T> *> {
64
65public:
66
68 typedef K key_t;
69
71 typedef T value_t;
72
74 typedef ClonerBase<T> cloner_t;
75
77 typedef std::map<K, cloner_t *> map_t;
78
80 typedef std::set<K> key_set_t;
81
82 struct bank_id {
83 };
84
85 virtual inline
86 ~Bank(){
87 }
88
89 template <class D>
90 static
91 Cloner<T,D> & getCloner(){
92 static Cloner<T,D> & cloner = Static::get<Cloner<T,D>, bank_id>();
93 return cloner;
94 }
95
96
98
105 template <class D>
106 D & add(const K & key){
107 static Cloner<T,D> & cloner = Bank<T,K>::getCloner<D>(); // Static::get<Cloner<T,D>, bank_id>();
108 set(key, cloner);
109 return cloner.src;
110 }
111
112 // Add something that has getName()
113 template <class D>
114 D & add(){
115 static Cloner<T,D> & cloner = Bank<T,K>::getCloner<D>(); // Static::get<Cloner<T,D>, bank_id>();
116 set(cloner.src.getName(), cloner);
117 return cloner.src;
118 }
119
121
129 template <class D>
130 D & addExternal(const D & entry, const K & key){
131 //static Cloner<T,D> & cloner = Static::get<Cloner<T,D>, bank_id>();
132 static drain::Cloner<T,D> cloner(entry);
133 //set(resolve(key), cloner);
134 set(key, cloner);
135 return cloner.src;
136 }
137
139 inline
140 bool has(const K & key) const {
141 return (this->find(resolve(key)) != this->end());
142 }
143
145 inline
146 T & clone(const K & key) const {
147 typename map_t::const_iterator it = this->find(resolve(key));
148 if (it != this->end()){
149 return it->second->getCloned();
150 }
151 else {
152 throw std::runtime_error(resolve(key) + '[' + key + "]: no such entry");
153 }
154 }
155
157 inline
158 const T & get(const K & key) const {
159 typename map_t::const_iterator it = this->find(resolve(key));
160 if (it != this->end()){
161 return it->second->getSource();
162 }
163 else {
164 throw std::runtime_error(resolve(key) + '[' + key + "]: no such entry");
165 }
166 }
167
169 inline
170 T & get(const K & key){
171 typename map_t::iterator it = this->find(resolve(key));
172 if (it != this->end()){
173 return it->second->getSource();
174 }
175 else {
176 throw std::runtime_error(resolve(key) + '[' + key + "]: no such entry");
177 }
178 }
179
181 template <class D>
182 typename map_t::const_iterator get() const {
183 static const cloner_t & cloner = Bank<T,K>::getCloner<D>();
184 for (typename map_t::const_iterator it = this->begin(); it != this->end(); ++it){
185 if (it->second == &cloner)
186 return it;
187 }
188 throw std::runtime_error("find(): no such entry");
189 return this->end();
190 }
191
193 /*
194 * This method is useful if one wants to first set parameters of the
195 * source and the create clones of it.
196 *
197 */
198 inline
199 cloner_t & getCloner(const K & key) const {
200 typename map_t::const_iterator it = this->find(resolve(key));
201 if (it != this->end()){
202 return *(it->second);
203 }
204 else {
205 throw std::runtime_error(key + ": no such entry");
206 }
207 }
208
209 /*
210 template <class D>
211 cloner_t & getCloner() const {
212 static const cloner_t & cloner = Bank<T,K>::getCloner<D>();
213 for (typename map_t::const_iterator it = this->begin(); it != this->end(); ++it){
214 if (it->second == &cloner)
215 return it;
216 }
217 throw std::runtime_error("getCloner(): no such entry");
218 return this->end();
219 }
220 */
221
222 /*
223 inline
224 void clear(const K &key, T *ptr){
225 cloner_t & cloner = getCloner(key);
226 cloner.clear(*ptr);
227 }
228 */
229
231 inline
232 const map_t & getMap() const{
233 return *this;
234 }
235
237
240 // TODO: remove this stupid resolve(key), it works only with K=std::string, and cannot work (easily) with other classes.
241 // lower it to superbank, with applying functions; redefine has(), get(), etc.
242 virtual
243 const std::string & resolve(const K & key) const {
244 return key;
245 }
246
247 void toStream(std::ostream & ostr = std::cout) const {
248 /*
249 Sprinter::sequenceToStream(ostr, getMap(), Sprinter::lineLayout);
250 for (typename map_t::const_iterator it = this->begin(); it != this->end(); ++it) {
251 ostr << it->first << ':' << it->second->getSource() << '\n';
252 }
253 */
254 for (const auto & entry: *this) {
255 ostr << entry.first << ':' << entry.second->getSource() << '\n';
256 }
257
258
259 //std::cout << it->first << ' ' << it->second->getSource() << '\n';
260 }
261
262 inline
263 key_set_t & getKeys(){
264 return keys;
265 }
266
267
268protected:
269
270 key_set_t keys;
271
275 drain::ClonerBase<T> & set(const std::string & key, drain::ClonerBase<T> & cloner){
276
277 const typename map_t::iterator it = this->find(key);
278
279 if (it != this->end()){
280 // Redefined existing (making brief?)
281 if (it->second != &cloner){
282 std::cerr << __FILE__ << " warning: changing cloner source for: " << key << "\n";
283 //throw std::runtime_error(key + ": no such entry");
284 }
285 else {
286 // Re-introduce existing?
287 std::cerr << __FILE__ << " warning: re-defining: " << key << "\n";
288 }
289 it->second = &cloner;
290 }
291 else {
292 // Create new
293 this->operator [](key) = &cloner;
294 keys.insert(key);
295 }
296
297 return cloner;
298
299 }
300
301};
302
303template <class T>
304std::ostream & operator<<(std::ostream & ostr, const Bank<T> & bank) {
305 bank.toStream(ostr);
306 return ostr;
307}
308
310
314template <class T>
315class BankSuper : public Bank<T, std::string> {
316
317public:
318
320 typedef typename bank_t::key_t key_t;
321 typedef typename bank_t::bank_id bank_id;
322
323 typedef T data_t;
324
325 BankSuper(): bank_t() { //, sectionFlags(sections){
326 }
327
328 BankSuper(const BankSuper & bank): bank_t(bank){ //, sectionFlags(sections){
329 std::cerr << __FUNCTION__ << ": copy const" << std::endl;
330 }
331
332
333 // Short (brief) keys needs repeating code or Bank::add()
334 // Note: BankSuper uses same cloner as Bank. Consider leniency.
335 template <class D>
336 D & add(const std::string & key, char brief=0){
337 static Cloner<T,D> & cloner = Static::get<Cloner<T,D>, bank_id>();
338 // static const D & clonerSrc = Static<Cloner<T,D>, bank_id>::getSource().src;
339 if (brief)
340 setBriefKey(brief, key);
341 bank_t::set(key, cloner);
342 return cloner.src;
343 }
344
346 // Short (brief) key needs repeating code or Bank::add()
347 template <class D>
348 D & add(char brief=0){
349 static Cloner<T,D> & cloner = Static::get<Cloner<T,D>, bank_id>();
350 if (brief)
351 setBriefKey(brief, cloner.src.getName());
352 bank_t::set(cloner.src.getName(), cloner);
353 return cloner.src;
354 }
355
356
357 /*
358 template <class D>
359 D & addExternal(D & entry, const std::string & key ){
360 return Bank<T, std::string>::template addExternal<D>(key, entry);
361 }
362 */
363
364 template <class D>
365 D & addExternal(const D & entry, const std::string & key, char brief = 0){
366 if (brief)
367 setBriefKey(brief, key);
368 return Bank<T, std::string>::addExternal(entry, key);
369 //return Bank<T, std::string>::template addExternal<D>(entry, key);
370 }
371
373 /* well, ok
374 template <class D>
375 D & addExternal(D & entry, char brief = 0){
376 std::string key = entry.getName()+"MIKA";
377 if (brief)
378 setBriefKey(brief, key);
379 // TODO: what if the KEY is a single char?
380 return Bank<T, std::string>::template addExternal<D>(key, entry);
381 }
382 */
383
384
385
386 inline
387 void setBriefKey(char brief, const std::string & value){
388 briefKeys.add(brief, value);
389 }
390
391 inline
392 bool hasAlias(const std::string & value) const {
393 if (value.empty())
394 return false;
395 else if (value.length()==1)
396 return hasAlias(value.at(0));
397 else
398 return briefKeys.hasValue(value);
399 }
400
401 inline
402 bool hasAlias(char brief) const {
403 return briefKeys.hasKey(brief);
404 }
405
406 inline
407 char getAlias(const std::string & value) const {
408 if (value.length() > 1)
409 return briefKeys.getKey(value);
410 else if (value.length()==1){
411 // Warn ?
412 char c = value.at(0);
413 if (briefKeys.hasKey(c))
414 return c;
415 }
416 return '\0';
417 }
418
419
420
421 inline
422 const drain::Dictionary<char, key_t> & getAliases() const {
423 return briefKeys;
424 }
425
426
428
431 // TODO: what is the KEY is a single char?
432 virtual inline
433 const std::string & resolve(const key_t & value) const {
434 //std::cout << __FUNCTION__ << ':' << value << '\n';
435 if (value.length() == 1)
436 return briefKeys.getValue(value.at(0));
437 else
438 return value;
439 }
440
441
443 inline
444 void setTitle(const std::string & title){
445 this->title = title;
446 };
447
449 inline
450 const std::string & getTitle() const {
451 return this->title;
452 };
453
454 FlagResolver::ivalue_t addSection(const FlagResolver::dict_t::key_t & title, const FlagResolver::dict_t::value_t index=0){
455 // Flagger2<int>::value_t addSection(const FlagResolver::dict_t::key_t & title, const FlagResolver::dict_t::value_t index=0){
456 return FlagResolver::addEntry(sections, title, index);
457 }
458
459
460 FlagResolver::dict_t sections;
461
462
463protected:
464
466
468 std::string title;
469
470};
471
472
474
481template <class B>
483
484public:
485
486 typedef Bank<B> bank_t;
487
488 // Inherit type
489 typedef typename bank_t::cloner_t cloner_t;
490
491 // Inherit type
492 typedef typename cloner_t::entry_t entry_t;
493
494 // Inherit type
495 typedef typename cloner_t::index_t index_t;
496
497 const bank_t & bank;
498
499 typedef std::map<cloner_t *, std::set<index_t> > book_t;
500
501 LocalCloner(const bank_t & bank) : bank(bank), idx(0) { // , cloner(nullptr)
502 };
503
504 ~LocalCloner(){
505 for (typename book_t::value_type & v : this->book){
506 drain::Logger mout(__FILE__, __FUNCTION__);
507 mout.debug() << "Freeing: ";
508 for (index_t i : v.second){ // << v.first->getSource().getName() not universal
509 //std::cerr << __FILE__ << ':' << __FUNCTION__ << ": dropping " << i << '\n';
510 mout << i << ", ";
511 v.first->drop(i);
512 }
513 mout << mout;
514 }
515 };
516
517 B & getCloned(const typename bank_t::key_t & key){
518
519 cloner_t & cloner = bank.getCloner(key);
520 entry_t entry = cloner.getClonerEntry();
521 idx = entry.first;
522 book[&cloner].insert(entry.first);
523 return *entry.second;
524 //return cloner.cloneUnique();
525 }
526
527 template <class T>
528 B & getCloned(){
529
530 typename bank_t::map_t::const_iterator it = bank.template get<T>();
531 cloner_t *cloner = it->second;
532 entry_t entry = cloner->getClonerEntry();
533 idx = entry.first;
534 book[cloner].insert(entry.first);
535 return *entry.second;
536 //idx = entry.first;
537 //return *(it->second->getCloned());
538 //return cloner.cloneUnique();
539 }
540
541
542 // Returns last index
543
544 inline
545 index_t getIndex() const{
546 return idx;
547 }
548
549
550protected:
551
552 book_t book;
553
554 //cloner_t *cloner;
555 //entry_t entry;
556 index_t idx;
557
558
559};
560
561
562
563
564
565
566
567
568
569// OLD:
570/*
572template <class T>
573class BankOLD : public Registry<ClonerBase<T> > {
574
575public:
576
578 template <class D>
579 void add2(const std::string & key){
580 static drain::Cloner<T,D> cloner;
581 this->add(cloner, key);
582 }
583
584 inline
585 T & clone(const std::string & key) const {
586 // return this->template Registry<ClonerBase<T> >::get(key).clone();
587 return this->Registry<ClonerBase<T> >::get(key).getCloned();
588 }
589
590 inline
591 T & get(const std::string & key){
592 return this->Registry<ClonerBase<T> >::get(key).getSource();
593 //return this->Registry<ClonerBase<T> >::get(key).get();
594 }
595
596
597};
598*/
599
600}
601
602#endif
603
604// Drain
A Bank with additional support for brief, single char keys.
Definition Bank.h:315
const std::string & getTitle() const
Get the name of this program (command set)
Definition Bank.h:450
virtual const std::string & resolve(const key_t &value) const
Given brief or long key, returns the long key .
Definition Bank.h:433
void setBriefKey(char brief, const std::string &value)
Now, D::getName() is required.
Definition Bank.h:387
void setTitle(const std::string &title)
Set name and brief description of a program, to appear in help dumps.
Definition Bank.h:444
std::string title
For example, name of the program, to appear in help dumps etc.
Definition Bank.h:468
D & add(char brief=0)
Add something that has getName()
Definition Bank.h:348
Definition Bank.h:63
std::map< K, cloner_t * > map_t
Base class.
Definition Bank.h:77
bool has(const K &key) const
Check if a cloner is defined for this key.
Definition Bank.h:140
drain::ClonerBase< T > & set(const std::string &key, drain::ClonerBase< T > &cloner)
Definition Bank.h:275
K key_t
Public key type. (Key type used in the public interface.)
Definition Bank.h:68
map_t::const_iterator get() const
Returns a map entry: pair<Key,D *>()
Definition Bank.h:182
T & get(const K &key)
Returns the base instance.
Definition Bank.h:170
const T & get(const K &key) const
Returns the base instance.
Definition Bank.h:158
T & clone(const K &key) const
Return a copy of the base instance.
Definition Bank.h:146
D & addExternal(const D &entry, const K &key)
Adds class D using a copy constructor on an external instance.
Definition Bank.h:130
D & add(const K &key)
Adds class D as an internal instance.
Definition Bank.h:106
T value_t
Base type of cloned objects.
Definition Bank.h:71
cloner_t & getCloner(const K &key) const
Return the internal static entry.
Definition Bank.h:199
std::set< K > key_set_t
For enumerating keys.
Definition Bank.h:80
virtual const std::string & resolve(const K &key) const
Definition Bank.h:243
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
drain::Dictionary< key_t, ivalue_t > dict_t
"Recommended" dictionary type. All the methods are templates, however.
Definition FlagBase.h:64
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.
Creates an entries offered by a bank and destroys them upon exit.
Definition Bank.h:482
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:313
Logger & debug(const TT &... args)
Debug information.
Definition Log.h:667
Definition DataSelector.cpp:1277
Definition Bank.h:82
Definition Cloner.h:46
size_t index_t
Each cloned entry has an index.
Definition Cloner.h:52
Wrapper for derived class S, returning base class T.
Definition Cloner.h:118
S src
Default instance, also the source for cloning.
Definition Cloner.h:275