Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2019 The plumed team
3 : (see the PEOPLE file at the root of the distribution for a list of names)
4 :
5 : See http://www.plumed.org for more information.
6 :
7 : This file is part of plumed, version 2.
8 :
9 : plumed is free software: you can redistribute it and/or modify
10 : it under the terms of the GNU Lesser General Public License as published by
11 : the Free Software Foundation, either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : plumed is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 : #include "ActionRegister.h"
23 : #include "tools/Tools.h"
24 : #include "Action.h"
25 : #include <algorithm>
26 : #include <iostream>
27 :
28 :
29 : using namespace std;
30 : namespace PLMD {
31 :
32 3214 : ActionRegister::~ActionRegister() {
33 1607 : if(m.size()>0) {
34 0 : string names="";
35 0 : for(const auto & p : m) names+=p.first+" ";
36 0 : std::cerr<<"WARNING: Directive "+ names +" has not been properly unregistered. This might lead to memory leak!!\n";
37 : }
38 1607 : }
39 :
40 722431 : ActionRegister& actionRegister() {
41 722431 : static ActionRegister ans;
42 722431 : return ans;
43 : }
44 :
45 358362 : void ActionRegister::remove(creator_pointer f) {
46 24556619 : for(auto p=m.begin(); p!=m.end(); ++p) {
47 24556619 : if((*p).second==f) {
48 358362 : m.erase(p); break;
49 : }
50 : }
51 358362 : }
52 :
53 358362 : void ActionRegister::add(string key,creator_pointer f,keywords_pointer k) {
54 358362 : if(m.count(key)) {
55 0 : m.erase(key);
56 0 : disabled.insert(key);
57 : } else {
58 358362 : m.insert(pair<string,creator_pointer>(key,f));
59 : // Store a pointer to the function that creates keywords
60 : // A pointer is stored and not the keywords because all
61 : // Vessels must be dynamically loaded before the actions.
62 358362 : mk.insert(pair<string,keywords_pointer>(key,k));
63 : };
64 358362 : }
65 :
66 5483 : bool ActionRegister::check(string key) {
67 5483 : if(m.count(key)>0 && mk.count(key)>0) return true;
68 2 : return false;
69 : }
70 :
71 5260 : Action* ActionRegister::create(const ActionOptions&ao) {
72 5260 : if(ao.line.size()<1)return NULL;
73 : // Create a copy of the manual locally. The manual is
74 : // then added to the ActionOptions. This allows us to
75 : // ensure during construction that all the keywords for
76 : // the action have been documented. In addition, we can
77 : // generate the documentation when the user makes an error
78 : // in the input.
79 : Action* action;
80 5260 : if( check(ao.line[0]) ) {
81 5258 : Keywords keys; mk[ao.line[0]](keys);
82 10516 : ActionOptions nao( ao,keys );
83 5258 : action=m[ao.line[0]](nao);
84 10479 : keys.destroyData();
85 2 : } else action=NULL;
86 5223 : return action;
87 : }
88 :
89 223 : bool ActionRegister::printManual( const std::string& action, const bool& vimout ) {
90 223 : if ( check(action) ) {
91 223 : Keywords keys; mk[action](keys);
92 223 : if( vimout ) {
93 223 : printf("%s",action.c_str()); keys.print_vim(); printf("\n");
94 : } else {
95 0 : keys.print_html();
96 : }
97 223 : keys.destroyData();
98 223 : return true;
99 : } else {
100 0 : return false;
101 : }
102 : }
103 :
104 0 : bool ActionRegister::printTemplate( const std::string& action, bool include_optional ) {
105 0 : if( check(action) ) {
106 0 : Keywords keys; mk[action](keys);
107 0 : keys.print_template(action, include_optional); keys.destroyData();
108 0 : return true;
109 : } else {
110 0 : return false;
111 : }
112 : }
113 :
114 224 : std::ostream & operator<<(std::ostream &log,const ActionRegister&ar) {
115 224 : vector<string> s;
116 224 : for(const auto & it : ar.m) s.push_back(it.first);
117 224 : sort(s.begin(),s.end());
118 224 : for(unsigned i=0; i<s.size(); i++) log<<" "<<s[i]<<"\n";
119 224 : if(!ar.disabled.empty()) {
120 0 : s.assign(ar.disabled.size(),"");
121 0 : copy(ar.disabled.begin(),ar.disabled.end(),s.begin());
122 0 : sort(s.begin(),s.end());
123 0 : log<<"+++++++ WARNING +++++++\n";
124 0 : log<<"The following keywords have been registered more than once and will be disabled:\n";
125 0 : for(unsigned i=0; i<s.size(); i++) log<<" - "<<s[i]<<"\n";
126 0 : log<<"+++++++ END WARNING +++++++\n";
127 : };
128 224 : return log;
129 : }
130 :
131 :
132 4821 : }
|