-
Notifications
You must be signed in to change notification settings - Fork 0
/
cmd_line_interface.h
292 lines (245 loc) · 7.35 KB
/
cmd_line_interface.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
/**
* @file cmd_line_interface.h
* @brief simplifies the command-line parsing interface in a new application
*
*/
/*
* Original Author: Gheorghe Postelnicu
* CVS Revision Info:
* $Author: nicks $
* $Date: 2009/11/20 00:32:39 $
* $Revision: 1.4 $
*
* Copyright (C) 2004-2009,
* The General Hospital Corporation (Boston, MA).
* All rights reserved.
*
* Distribution, usage and copying of this software is covered under the
* terms found in the License Agreement file named 'COPYING' found in the
* FreeSurfer source code root directory, and duplicated here:
* https://surfer.nmr.mgh.harvard.edu/fswiki/FreeSurferOpenSourceLicense
*
* General inquiries: [email protected]
* Bug reports: [email protected]
*
*/
#ifndef H_CMD_LINE_INTERFACE_H
#define H_CMD_LINE_INTERFACE_H
#include <iostream>
#include <list>
#include <vector>
#include <string>
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h> // printf
#include <stdlib.h>
#ifdef __cplusplus
}
#endif
#define GMP_ISOPTION(c) ((c) == '-')
// generic class that will hold and handle data for a specific type of option
// when the user wants a certain type of option to be handled
// they will just have to specify
// - name
// - add pointers to the addresses that will be affected
// when the option is found
// - help text that gives a generic description
template <class T>
class CCmdLineOption {
protected:
std::string m_strOption;
std::string m_strHelp;
std::vector<T *> m_pars; // this contains parameters assigned to the option
int m_iPars;
int m_iCur;
bool m_bInput;
public:
CCmdLineOption() {}
CCmdLineOption(const char *i_strName, int i_iPars, const char *i_strHelp)
: m_strOption(), m_strHelp() {
m_strOption = i_strName;
m_iPars = i_iPars;
if ( i_strHelp )
m_strHelp = i_strHelp;
else
m_strHelp = " no help available for this option ";
m_iCur = 0;
m_bInput = false;
}
void Add(T *i_par) {
if ( m_iCur < m_iPars && !m_bInput) {
m_pars.push_back(i_par);
m_iCur++;
} else {
std::cerr << " ERROR - too many parameters for option " << m_strOption
<< std::endl;
exit(-1);
}
if ( m_iCur == m_iPars ) {
m_bInput = true;
m_iCur = 0;
}
}
bool Compare(const std::string i_strOption) const {
return ( m_strOption.compare(i_strOption) == 0 );
}
bool Compare(const char *i_strOption) const {
std::string strBuf = i_strOption;
return ( m_strOption.compare(strBuf) == 0 );
}
void Set(T val) {
if ( !m_bInput ) {
std::cout << " can not set values for option " << m_strOption
<< " until all the pars have been set\n";
}
if ( (unsigned)m_iCur < m_pars.size() ) {
*(m_pars[m_iCur]) = val;
m_iCur++;
}
}
int GetArgs() const {
return m_iPars;
}
std::string GetHelp() const {
char chBuf[10];
sprintf(chBuf, "%d", m_iPars);
std::string strBuf = std::string("--")
+ m_strOption + "\t pars = " + chBuf + "\t" + m_strHelp;
return strBuf;
}
void outStatus() const {
std::cout << m_strOption ;
for ( typename std::vector<T*>::const_iterator cit = m_pars.begin();
cit != m_pars.end(); cit++) {
std::cout << "\t" << *(*cit) ;
}
std::cout << "\n";
}
};
// specializations to be able to do strong-typing
typedef CCmdLineOption<int> CCmdLineOptionInt;
typedef CCmdLineOption<float> CCmdLineOptionFloat;
typedef CCmdLineOption<std::string> CCmdLineOptionString;
//
// a partial specialization is dedicated to the bool class
// in the case of a boolean - this will act like a flag
// the sole presence of the option will be enough to activate the flag
//
class CCmdLineOptionBool : public CCmdLineOption<bool> {
public:
CCmdLineOptionBool(const char *i_strName, const char *i_strHelp)
: CCmdLineOption<bool>(i_strName, 1, i_strHelp) {}
void Set() {
*(m_pars[0]) = true;
}
int GetArgs() const {
return 0; // there is no actual parameter involved
// - the presence of the option IS the flag
}
std::string GetHelp() const {
char chBuf[10];
sprintf(chBuf, "%d", m_iPars);
std::string strBuf = std::string("--") + m_strOption + "\t" + m_strHelp;
return strBuf;
}
void outStatus() const {
std::cout << m_strOption << "\t" << *(m_pars[0]) << "\n";
}
};
class CCmdLineIo {
std::string *m_pStrItem;
std::string m_strHelp;
bool m_bOk;
public:
CCmdLineIo() {
m_pStrItem = NULL;
m_bOk = false;
}
CCmdLineIo(std::string *i_pStrItem, const char* i_strHelp=NULL) {
m_pStrItem = i_pStrItem;
if ( i_strHelp )
m_strHelp = i_strHelp;
else
m_strHelp = " no help available for IO item";
m_bOk = false;
}
void Set(std::string i_strItem) {
*m_pStrItem = i_strItem;
m_bOk = true;
}
std::string printHelp() {
return m_strHelp;
}
bool Ok() const {
return m_bOk;
}
std::string GetHelp() const {
return m_strHelp;
}
void outStatus() const {
std::cout << *m_pStrItem << "\n";
}
};
//
// class CCmdLineInterface
//
// this is a placeholder for a list of potential options
// the redundance in the code is present here because I did not
// know how to handle the typing in a generic way
//
// one must notice that another limitation is that all options
// are only allowed to have parameters that have the same type
class CCmdLineInterface {
std::string m_strProgName;
std::list<CCmdLineOptionFloat> m_lstFloatOption;
std::list<CCmdLineOptionInt> m_lstIntOption;
std::list<CCmdLineOptionString> m_lstStringOption;
std::list<CCmdLineOptionBool> m_lstBoolOption;
std::list<CCmdLineIo> m_lstIo;
public:
CCmdLineInterface(char *i_strProgName) {
m_strProgName = i_strProgName;
}
// the pointers in the following functions HAVE to be
// initialized at the time of the call
// this code has been designed so that these pointers
// hold variables addresses
// this simplifies the writing and the passage of parameters....
void AddOptionInt
(const char *i_cstrName, int *piVal, const char *help=NULL);
void AddOptionInt
(const char *i_cstrName, int *piVal1,int *piVal2, const char *help=NULL);
void AddOptionFloat
(const char *i_cstrName, float *pfVal, char *help=NULL);
void AddOptionFloat
(const char *i_cstrName, float *pfVal1, float *pfVal2, char *help=NULL);
void AddOptionString
(const char *i_cstrName, std::string *pstrVal, const char *help=NULL);
void AddOptionString
(const char *i_cstrName, std::string *pstrVal_1,
std::string *pstrVal_2, const char* help=NULL);
// a bool option is basically just a flag
// no parameters at all
void AddOptionBool
(const char *i_cstrName, bool *pbVal, const char *help=NULL);
void AddIoItem(std::string *pStrItem, const char *help=NULL) {
CCmdLineIo item(pStrItem, help);
m_lstIo.push_back(item);
}
//
// this will do the actual parsing
// all the options should of course be registered
// using one of the preceding functions
// at the time of this call
//
// any option name should be preceded by a '-'
//
// the return value is the number of read items in the
// command-line string array
bool Parse(int argc, char *argv[]);
void PrintHelp() const;
void print() const;
};
#endif // H_CMD_LINE_INTERFACE_H