Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2012-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 : #ifndef __PLUMED_core_CLTool_h
23 : #define __PLUMED_core_CLTool_h
24 : #include <cstdio>
25 : #include <vector>
26 : #include <string>
27 : #include <cstdio>
28 : #include "tools/Tools.h"
29 : #include "tools/Keywords.h"
30 :
31 : namespace PLMD {
32 :
33 : class Communicator;
34 :
35 2490 : class CLToolOptions {
36 : friend class CLTool;
37 : friend class CLToolRegister;
38 : private:
39 : std::vector<std::string> line;
40 : /// The documentation for this command line tool
41 : const Keywords& keys;
42 : static Keywords emptyKeys;
43 : public:
44 : explicit CLToolOptions(const std::string &name);
45 : CLToolOptions(const CLToolOptions& co, const Keywords& k);
46 : };
47 :
48 : /**
49 : \ingroup INHERIT
50 : This is the abstract base class to use for implementing new command line tool, within it there
51 : is \ref AddingACLTool "information" as to how to go about implemneting a new tool.
52 : */
53 :
54 : class CLTool {
55 : private:
56 : /// The name of this command line tool
57 : const std::string name;
58 : /// The list of keywords for this CLTool
59 : const Keywords& keywords;
60 : /// The data read in from the command line stored in a map with the keywords
61 : std::map<std::string,std::string> inputData;
62 : /// Read the arguments from the command line
63 : bool readCommandLineArgs( int argc, char**argv, FILE*out );
64 : /// Read the arguments from an input file specified on the command line
65 : bool readInputFile( int argc, char**argv, FILE* in, FILE*out );
66 : /// Set arguments from the default options provided to Keywords
67 : void setRemainingToDefault(FILE* out);
68 : public:
69 : /// Set the input data:
70 : void setInputData(const std::map<std::string,std::string>&inputData) {
71 : this->inputData=inputData;
72 : }
73 : const std::map<std::string,std::string>&getInputData() {
74 : return this->inputData;
75 : }
76 : protected:
77 : /// Get the value of one of the command line arguments
78 : template<class T>
79 : bool parse(const std::string&key,T&t);
80 : /// Find out whether one of the command line flags is present or not
81 : void parseFlag(const std::string&key,bool&t);
82 : /// Crash the command line tool with an error
83 : void error(const std::string& msg);
84 : template<class T>
85 : bool parseVector(const std::string&key,std::vector<T>&t);
86 : public:
87 : /// How is the input specified on the command line or in an input file
88 : enum {unset,commandline,ifile} inputdata;
89 : /// Create the help keywords
90 : static void registerKeywords( Keywords& keys );
91 : explicit CLTool(const CLToolOptions& co );
92 : /// Read the arguments from the command line
93 : bool readInput( int argc, char**argv, FILE* in, FILE*out );
94 : /// virtual function mapping to the specific main for each tool
95 : virtual int main( FILE* in, FILE*out, Communicator&pc )=0;
96 : /// virtual function returning a one-line descriptor for the tool
97 0 : virtual std::string description()const {return "(no description available)";}
98 : /// virtual destructor to allow inheritance
99 2490 : virtual ~CLTool() {}
100 : };
101 :
102 : template<class T>
103 16837 : bool CLTool::parse(const std::string&key,T&t) {
104 16837 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
105 33674 : if(keywords.style(key,"compulsory") ) {
106 0 : if(inputData.count(key)==0) error("missing data for keyword " + key);
107 2742 : bool check=Tools::convert(inputData[key],t);
108 2742 : if(!check) error("data input for keyword " + key + " has wrong type");
109 : return true;
110 : }
111 : if( inputData.count(key)==0 ) return false;
112 1290 : Tools::convert(inputData[key],t);
113 1290 : return true;
114 : }
115 : // very limited support and check: take more from core/Action.h parseVector
116 : template<class T>
117 318 : bool CLTool::parseVector(const std::string&key,std::vector<T>&t) {
118 :
119 : // Check keyword has been registered
120 318 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
121 : // initial size
122 318 : unsigned size=t.size();
123 : bool skipcheck=false;
124 318 : if(size==0) skipcheck=true; // if the vector in input has size zero, skip the check if size of input vector is the same of argument read
125 :
126 : // check if there is some value
127 :
128 636 : plumed_massert(inputData[key]!="false","compulsory keyword "+std::string(key)+"has no data");
129 636 : std::vector<std::string> words=Tools::getWords(inputData[key],"\t\n ,");
130 318 : t.resize(0);
131 318 : if(words.size()==0)return false;
132 :
133 1837 : for(unsigned i=0; i<words.size(); ++i) {
134 : T v;
135 443 : Tools::convert(words[i],v);
136 443 : t.push_back(v);
137 : }
138 : // check the size
139 266 : if( !skipcheck && t.size()!=size ) {
140 0 : plumed_merror("vector read in for keyword "+key+" has wrong size" );
141 : }
142 : std::string def;
143 : T val;
144 987 : if ( keywords.style(key,"compulsory") && t.size()==0 ) {
145 0 : if( keywords.getDefaultValue(key,def) ) {
146 0 : if( def.length()==0 || !Tools::convert(def,val) ) {
147 0 : plumed_merror("ERROR in keyword "+key+ " has weird default value" );
148 : } else {
149 0 : for(unsigned i=0; i<t.size(); ++i) t[i]=val;
150 : }
151 : } else {
152 0 : plumed_merror("keyword " + key + " is compulsory for this action");
153 : }
154 : }
155 : return true;
156 : }
157 :
158 :
159 :
160 : }
161 :
162 : #endif
|