viminfo
[gnucap-felix.git] / include / l_dispatcher.h
blob0f2bbe6a5c12616ce4b0643ab4c963417713eac4
1 /*$Id: l_dispatcher.h,v 26.134 2009/11/29 03:47:06 al Exp $ -*- 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)
10 * any later version.
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
20 * 02110-1301, USA.
21 *------------------------------------------------------------------
22 * dispatcher -- for dynamically loaded modules
24 //testing=informal
25 #ifndef L_DISPATCHER_H
26 #define L_DISPATCHER_H
27 #include "l_stlextra.h"
28 #include "u_opt.h"
29 #include "ap.h"
30 /*--------------------------------------------------------------------------*/
31 template <class T>
32 class INTERFACE DISPATCHER {
33 private:
34 std::map<std::string, T*> * _map;
35 public:
36 DISPATCHER() {
37 if (!_map) {
38 _map = new std::map<std::string, T*>;
39 }else{
43 typedef typename std::map<std::string, T*>::const_iterator const_iterator;
44 //class const_iterator : public std::map<std::string, T*>::const_iterator {};
46 const_iterator begin()const {assert(_map); return _map->begin();}
47 const_iterator end()const {assert(_map); return _map->end();}
49 void install(const std::string& s, T* p) {
50 assert(s.find(',', 0) == std::string::npos);
51 if (!_map) {
52 _map = new std::map<std::string, T*>;
53 }else{
55 trace0(s.c_str());
56 // loop over all keys, separated by '|'
57 for (std::string::size_type // bss: begin sub-string
58 bss = 0, ess = s.find('|', bss); // ess: end sub-string
59 bss != std::string::npos;
60 bss = (ess != std::string::npos) ? ess+1 : std::string::npos,
61 ess = s.find('|', bss)) {
62 std::string name = s.substr(bss,
63 (ess != std::string::npos) ? ess-bss : std::string::npos);
64 trace2(name.c_str(), bss, ess);
65 if (name == "") {
66 // quietly ignore empty string
67 }else if ((*_map)[name]) {
68 // duplicate .. stash the old one so we can get it back
69 error(bWARNING, name + ": already installed, replacing\n");
70 std::string save_name = name + ":0";
71 for (int ii = 0; (*_map)[save_name]; ++ii) {
72 save_name = name + ":" + to_string(ii);
74 (*_map)[save_name] = (*_map)[name];
75 error(bWARNING, "stashing as " + save_name + "\n");
76 }else{
77 // it's new, just put it in
79 (*_map)[name] = p;
83 void uninstall(T* p) {
84 assert(_map);
85 for (typename std::map<std::string, T*>::iterator
86 ii = _map->begin();
87 ii != _map->end();
88 ++ii) {
89 if (ii->second == p) {
90 ii->second = NULL;
91 }else{
94 #if !defined(NDEBUG)
95 for (typename std::map<std::string, T*>::iterator
96 ii = _map->begin();
97 ii != _map->end();
98 ++ii) {
99 assert(ii->second != p);
101 #endif
104 void uninstall(const std::string& s) {
105 assert(_map);
106 // loop over all keys, separated by '|'
107 for (std::string::size_type // bss: begin sub-string
108 bss = 0, ess = s.find('|', bss); // ess: end sub-string
109 bss != std::string::npos;
110 bss = (ess != std::string::npos) ? ess+1 : std::string::npos,
111 ess = s.find('|', bss)) {
112 std::string name = s.substr(bss,
113 (ess != std::string::npos) ? ess-bss : std::string::npos);
114 if (name == "") {
115 // quietly ignore empty string
116 }else if ((*_map)[name]) {
117 // delete, try to get back the old one
118 int ii = 0;
119 std::string save_name = name + ":0";
120 for (ii = 0; (*_map)[save_name]; ++ii) {
121 save_name = name + ":" + to_string(ii);
123 if (ii > 1) {
124 save_name = name + ":" + to_string(ii-2);
125 (*_map)[name] = (*_map)[save_name];
126 (*_map)[save_name] = NULL;
127 error(bWARNING, "restoring " + save_name + " as " + name + "\n");
128 }else{
129 (*_map)[name] = NULL;
131 }else{
132 error(bWARNING, name + ": not installed, doing nothing\n");
137 T* operator[](std::string s) {
138 assert(_map);
139 T* rv = (*_map)[s];
140 if (!rv && OPT::case_insensitive) {
141 notstd::to_lower(&s);
142 rv = (*_map)[s];
143 }else{
145 return rv;
148 T* operator[](CS& cmd) {
149 unsigned here = cmd.cursor();
150 std::string s;
151 cmd >> s;
152 //------------------------
153 T* p = (*this)[s];
154 //------------------------
155 if (!p) {
156 cmd.reset(here);
157 }else{
159 return p;
162 T* clone(std::string s) {
163 T* proto = (*this)[s];
164 if (proto) {
165 return proto->clone();
166 }else{itested();
167 return NULL;
171 class INSTALL {
172 private:
173 const std::string _name;
174 DISPATCHER<T>* _d;
175 T* _p;
176 public:
177 INSTALL(DISPATCHER<T>* d, const std::string& name, T* p) :
178 _name(name),
179 _d(d),
180 _p(p)
182 assert(_d);
183 assert(p);
184 _d->install(_name, p);
187 ~INSTALL() {
188 //_d->uninstall(_name);
189 _d->uninstall(_p);
193 /*--------------------------------------------------------------------------*/
194 /*--------------------------------------------------------------------------*/
195 #endif
196 // vim:ts=8:sw=2:noet: