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