1 /*$Id: l_dispatcher.h 2016/03/29 al -*- C++ -*-
2 * Copyright (C) 2006 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 *------------------------------------------------------------------
22 * dispatcher -- for dynamically loaded modules
24 //testing=script 2015.01.21
25 #ifndef L_DISPATCHER_H
26 #define L_DISPATCHER_H
28 #include "l_stlextra.h"
31 /*--------------------------------------------------------------------------*/
32 class DISPATCHER_BASE
{
34 std::map
<std::string
, CKT_BASE
*> * _map
;
36 explicit DISPATCHER_BASE(DISPATCHER_BASE
*) {unreachable();incomplete();}
38 DISPATCHER_BASE() /*: _map(new std::map<std::string, CKT_BASE*>)*/ {
40 _map
= new std::map
<std::string
, CKT_BASE
*>;
42 fprintf(stderr
, "build error: link order: constructing dispatcher that already has contents\n");
47 for (typename
std::map
<std::string
, CKT_BASE
*>::iterator
52 std::cerr
<< ii
->second
->long_label() << "\n";
61 typedef typename
std::map
<std::string
, CKT_BASE
*>::const_iterator const_iterator
;
62 //class const_iterator : public std::map<std::string, CKT_BASE*>::const_iterator {};
64 const_iterator
begin()const {assert(_map
); return _map
->begin();}
65 const_iterator
end()const {assert(_map
); return _map
->end();}
67 CKT_BASE
* operator[](std::string s
) {
69 CKT_BASE
* rv
= (*_map
)[s
];
70 if (!rv
&& OPT::case_insensitive
) {
78 /*--------------------------------------------------------------------------*/
80 class INTERFACE DISPATCHER
: public DISPATCHER_BASE
{
82 void install(const std::string
& s
, TT
* p
) {
83 assert(s
.find(',', 0) == std::string::npos
);
84 if (!_map
) {unreachable();
85 puts("build error: link order: dispatcher not yet constructed\n");
86 _map
= new std::map
<std::string
, CKT_BASE
*>;
89 trace1("DISPATCHER ", s
);
90 // loop over all keys, separated by '|'
91 for (std::string::size_type
// bss: begin sub-string
92 bss
= 0, ess
= s
.find('|', bss
); // ess: end sub-string
93 bss
!= std::string::npos
;
94 bss
= (ess
!= std::string::npos
) ? ess
+1 : std::string::npos
,
95 ess
= s
.find('|', bss
)) {
96 std::string name
= s
.substr(bss
,
97 (ess
!= std::string::npos
) ? ess
-bss
: std::string::npos
);
98 trace2(name
.c_str(), bss
, ess
);
100 // quietly ignore empty string
101 }else if ((*_map
)[name
]) {
102 // duplicate .. stash the old one so we can get it back
103 error(bWARNING
, name
+ ": already installed, replacing\n");
104 std::string save_name
= name
+ ":0";
105 for (int ii
= 0; (*_map
)[save_name
]; ++ii
) {
106 save_name
= name
+ ":" + ::to_string(ii
);
108 (*_map
)[save_name
] = (*_map
)[name
];
109 error(bWARNING
, "stashing as " + save_name
+ "\n");
111 // it's new, just put it in
117 void uninstall(TT
* p
) {
119 for (typename
std::map
<std::string
, CKT_BASE
*>::iterator
123 if (ii
->second
== p
) {
129 for (typename
std::map
<std::string
, CKT_BASE
*>::iterator
133 assert(ii
->second
!= p
);
138 void uninstall(const std::string
& s
) {untested();
140 // loop over all keys, separated by '|'
141 for (std::string::size_type
// bss: begin sub-string
142 bss
= 0, ess
= s
.find('|', bss
); // ess: end sub-string
143 bss
!= std::string::npos
;
144 bss
= (ess
!= std::string::npos
) ? ess
+1 : std::string::npos
,
145 ess
= s
.find('|', bss
)) {untested();
146 std::string name
= s
.substr(bss
,
147 (ess
!= std::string::npos
) ? ess
-bss
: std::string::npos
);
148 if (name
== "") {untested();
149 // quietly ignore empty string
150 }else if ((*_map
)[name
]) {untested();
151 // delete, try to get back the old one
153 std::string save_name
= name
+ ":0";
154 for (ii
= 0; (*_map
)[save_name
]; ++ii
) {
155 save_name
= name
+ ":" + ::to_string(ii
);
158 save_name
= name
+ ":" + ::to_string(ii
-2);
159 (*_map
)[name
] = (*_map
)[save_name
];
160 (*_map
)[save_name
] = NULL
;
161 error(bWARNING
, "restoring " + save_name
+ " as " + name
+ "\n");
163 (*_map
)[name
] = NULL
;
166 error(bWARNING
, name
+ ": not installed, doing nothing\n");
171 TT
* operator[](std::string s
) {
173 CKT_BASE
* rv
= (*_map
)[s
];
174 if (!rv
&& OPT::case_insensitive
) {
175 notstd::to_lower(&s
);
179 return prechecked_cast
<TT
*>(rv
);
182 TT
* operator[](CS
& cmd
) {
183 unsigned here
= cmd
.cursor();
186 //------------------------
188 //------------------------
196 TT
* clone(std::string s
) {
197 TT
* proto
= (*this)[s
];
199 return proto
->clone();
207 const std::string _name
;
211 INSTALL(DISPATCHER
<TT
>* d
, const std::string
& name
, TT
* p
) :
216 trace1("INSTALL ", _name
);
219 _d
->install(_name
, p
);
223 //_d->uninstall(_name);
228 /*--------------------------------------------------------------------------*/
229 /*--------------------------------------------------------------------------*/
231 // vim:ts=8:sw=2:noet: