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