2e73e7bc
David Mayerich
basic changes for...
|
1
2
|
#ifndef STIM_ARGUMENTS
#define STIM_ARGUMENTS
|
7a2d0012
David Mayerich
mirst1d updates
|
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#include <string>
#include <vector>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <iterator>
#include <algorithm>
#ifdef _WIN32
#include <Windows.h>
#endif
|
2e73e7bc
David Mayerich
basic changes for...
|
16
|
namespace stim{
|
7a2d0012
David Mayerich
mirst1d updates
|
17
|
|
81e0d221
David Mayerich
separated executa...
|
18
|
class cmd_option
|
7a2d0012
David Mayerich
mirst1d updates
|
19
20
21
22
23
24
25
26
27
28
29
|
{
private:
bool ansi;
//argument name
std::string name;
//description of the argument
std::vector<std::string> desc;
//argument values
|
3b012a80
David Mayerich
added code for co...
|
30
31
32
33
34
35
|
std::vector<std::string> vals;
//range or example
std::string range;
//flag is true when the argument is user-specified
|
7a2d0012
David Mayerich
mirst1d updates
|
36
37
38
39
|
bool flag;
void parse_val(const std::string &s){
|
3b012a80
David Mayerich
added code for co...
|
40
41
|
vals.clear();
|
7a2d0012
David Mayerich
mirst1d updates
|
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, ' ')) {
vals.push_back(item);
}
}
void parse_desc(const std::string &s){
desc.clear();
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, '\n')) {
desc.push_back(item);
}
}
|
3b012a80
David Mayerich
added code for co...
|
60
61
|
public:
void set_ansi(bool b){ ansi = b; }
|
81e0d221
David Mayerich
separated executa...
|
62
63
|
//create an option with a given name, description, and default value
cmd_option(std::string _name, std::string _desc, std::string _default = "", std::string _range = "")
|
7a2d0012
David Mayerich
mirst1d updates
|
64
65
66
|
{
name = _name;
parse_desc(_desc);
|
3b012a80
David Mayerich
added code for co...
|
67
68
69
70
71
72
73
74
75
|
parse_val(_default);
//if a default value is provided, set the flag
if(_default != "")
flag = true;
else flag = false;
range = _range;
|
7a2d0012
David Mayerich
mirst1d updates
|
76
|
|
3b012a80
David Mayerich
added code for co...
|
77
78
79
80
81
82
83
|
}
int nargs()
{
return vals.size();
}
|
81e0d221
David Mayerich
separated executa...
|
84
|
//return the value of a text option
|
2e73e7bc
David Mayerich
basic changes for...
|
85
|
std::string as_string(unsigned int n = 0)
|
3b012a80
David Mayerich
added code for co...
|
86
87
88
|
{
if(!flag)
{
|
81e0d221
David Mayerich
separated executa...
|
89
|
std::cout<<"ERROR - Option requested without being set: "<<name<<std::endl;
|
3b012a80
David Mayerich
added code for co...
|
90
91
92
93
94
95
96
97
98
|
exit(1);
}
if(vals.size() > n)
return vals[n];
else return "";
}
|
81e0d221
David Mayerich
separated executa...
|
99
|
//return the value of a floating point option
|
2e73e7bc
David Mayerich
basic changes for...
|
100
|
float as_float(unsigned int n = 0)
|
3b012a80
David Mayerich
added code for co...
|
101
102
103
|
{
if(!flag)
{
|
81e0d221
David Mayerich
separated executa...
|
104
|
std::cout<<"ERROR - option requested without being set: "<<name<<std::endl;
|
3b012a80
David Mayerich
added code for co...
|
105
106
107
108
109
110
|
exit(1);
}
if(vals.size() > n)
{
float r;
|
2e73e7bc
David Mayerich
basic changes for...
|
111
|
if ( ! (std::istringstream(vals[n]) >> r) ) r = 0;
|
3b012a80
David Mayerich
added code for co...
|
112
113
114
115
116
117
|
return r;
}
else return 0;
}
|
81e0d221
David Mayerich
separated executa...
|
118
|
//return the value of an integer option
|
2e73e7bc
David Mayerich
basic changes for...
|
119
|
int as_int(unsigned int n = 0)
|
3b012a80
David Mayerich
added code for co...
|
120
121
122
|
{
if(!flag)
{
|
81e0d221
David Mayerich
separated executa...
|
123
|
std::cout<<"ERROR - option requested without being set: "<<name<<std::endl;
|
3b012a80
David Mayerich
added code for co...
|
124
125
126
127
128
129
|
exit(1);
}
if(vals.size() > n)
{
int r;
|
2e73e7bc
David Mayerich
basic changes for...
|
130
|
if ( ! (std::istringstream(vals[n]) >> r) ) r = 0;
|
3b012a80
David Mayerich
added code for co...
|
131
132
133
134
135
136
137
138
139
140
|
return r;
}
else return 0;
}
//get the width of the left column
int col_width()
{
int n = 3;
|
81e0d221
David Mayerich
separated executa...
|
141
|
//add the length of the option name
|
3b012a80
David Mayerich
added code for co...
|
142
143
144
145
146
147
148
149
|
n += name.size();
//if there are any default parameters
if(vals.size() > 0)
{
//padding (parenthesis, =, etc.)
n += 6;
|
81e0d221
David Mayerich
separated executa...
|
150
|
//for each default option value
|
2e73e7bc
David Mayerich
basic changes for...
|
151
|
for(unsigned int v=0; v<vals.size(); v++)
|
3b012a80
David Mayerich
added code for co...
|
152
153
154
155
156
157
158
|
n += vals[v].size() + 1;
}
//add a buffer of 4 characters
n += 4;
return n;
|
7a2d0012
David Mayerich
mirst1d updates
|
159
160
161
162
163
164
|
}
//string output
std::string toStr(int width = 0)
{
|
3b012a80
David Mayerich
added code for co...
|
165
166
167
168
|
std::stringstream ss;
int color_size = 0;
|
7a2d0012
David Mayerich
mirst1d updates
|
169
170
171
172
|
//create the left column
std::string left_part = std::string(" --") + name;
if(vals.size() != 0)
|
3b012a80
David Mayerich
added code for co...
|
173
174
175
|
{
if(ansi)
left_part += "\033[1;32m";
|
7a2d0012
David Mayerich
mirst1d updates
|
176
|
left_part += " ( = ";
|
2e73e7bc
David Mayerich
basic changes for...
|
177
|
for(unsigned int v=0; v<vals.size(); v++)
|
7a2d0012
David Mayerich
mirst1d updates
|
178
|
left_part += vals[v] + std::string(" ");
|
3b012a80
David Mayerich
added code for co...
|
179
180
181
182
183
184
185
|
left_part += ")";
if(ansi)
left_part += "\033[0m";
if(ansi)
color_size = 11;
}
else
|
7a2d0012
David Mayerich
mirst1d updates
|
186
187
188
|
color_size = 0;
//if no width is passed, put 4 spaces between left and right columns
|
3b012a80
David Mayerich
added code for co...
|
189
|
if(width == 0) width = col_width();
|
7a2d0012
David Mayerich
mirst1d updates
|
190
191
192
193
|
ss<<std::left<<std::setw(width + color_size)<<left_part;
//output right column
|
2e73e7bc
David Mayerich
basic changes for...
|
194
|
for(unsigned int d=0; d<desc.size(); d++)
|
7a2d0012
David Mayerich
mirst1d updates
|
195
196
197
|
{
if(d == 0)
ss<<desc[0];
|
3b012a80
David Mayerich
added code for co...
|
198
|
else
|
0ef519a4
David Mayerich
optimized materia...
|
199
|
ss<<std::endl<<std::setfill(' ')<<std::setw(width)<<" "<<desc[d];
|
7a2d0012
David Mayerich
mirst1d updates
|
200
|
|
3b012a80
David Mayerich
added code for co...
|
201
202
203
204
|
}
//output the range in the right column
if(range != "" && ansi)
|
0ef519a4
David Mayerich
optimized materia...
|
205
|
ss<<std::endl<<std::setfill(' ')<<std::setw(width)<<" "<<" "<<std::string("\033[1;36m") + range + "\033[0m";
|
7a2d0012
David Mayerich
mirst1d updates
|
206
|
else if(range != "")
|
0ef519a4
David Mayerich
optimized materia...
|
207
|
ss<<std::endl<<std::setfill(' ')<<std::setw(width)<<" "<<" "<<range;
|
7a2d0012
David Mayerich
mirst1d updates
|
208
209
|
return ss.str();
|
3b012a80
David Mayerich
added code for co...
|
210
211
|
}
|
81e0d221
David Mayerich
separated executa...
|
212
|
//compare the name of the option to a string
|
3b012a80
David Mayerich
added code for co...
|
213
214
215
216
217
|
bool operator==(std::string rhs)
{
return (name == rhs);
}
|
81e0d221
David Mayerich
separated executa...
|
218
|
//set the option to a given value
|
3b012a80
David Mayerich
added code for co...
|
219
220
221
222
223
224
225
226
227
228
229
|
void set(std::string _value)
{
parse_val(_value);
//set the flag
flag = true;
}
bool is_set()
{
return flag;
|
7a2d0012
David Mayerich
mirst1d updates
|
230
231
|
}
|
3b012a80
David Mayerich
added code for co...
|
232
233
234
235
236
237
238
239
240
241
242
243
244
|
};
struct argsection
{
std::string name;
unsigned int index;
};
class arglist
{
private:
bool ansi;
|
81e0d221
David Mayerich
separated executa...
|
245
246
247
|
//vector of options
std::vector<cmd_option> opts;
std::vector<std::string> args;
|
3b012a80
David Mayerich
added code for co...
|
248
|
|
81e0d221
David Mayerich
separated executa...
|
249
|
//column width of the longest option
|
3b012a80
David Mayerich
added code for co...
|
250
251
252
253
254
255
256
|
int col_width;
//list of sections
std::vector<argsection> sections;
public:
|
0ef519a4
David Mayerich
optimized materia...
|
257
258
259
260
|
arglist(){
col_width = 0;
ansi = true;
}
|
3b012a80
David Mayerich
added code for co...
|
261
262
263
264
|
void set_ansi(bool b)
{
ansi = b;
|
81e0d221
David Mayerich
separated executa...
|
265
266
|
for(unsigned int i=0; i<opts.size(); i++)
opts[i].set_ansi(ansi);
|
3b012a80
David Mayerich
added code for co...
|
267
268
269
270
|
}
void add(std::string _name, std::string _desc, std::string _default = "", std::string _range = "")
{
|
81e0d221
David Mayerich
separated executa...
|
271
272
273
|
cmd_option opt(_name, _desc, _default, _range);
opt.set_ansi(ansi);
opts.push_back(opt);
|
3b012a80
David Mayerich
added code for co...
|
274
|
|
81e0d221
David Mayerich
separated executa...
|
275
|
col_width = std::max<int>(col_width, opt.col_width());
|
3b012a80
David Mayerich
added code for co...
|
276
277
278
279
280
281
|
}
void section(std::string _name)
{
argsection s;
s.name = _name;
|
81e0d221
David Mayerich
separated executa...
|
282
|
s.index = opts.size();
|
3b012a80
David Mayerich
added code for co...
|
283
284
285
|
sections.push_back(s);
}
|
81e0d221
David Mayerich
separated executa...
|
286
|
//output the options (generally in response to --help)
|
7a2d0012
David Mayerich
mirst1d updates
|
287
|
std::string str()
|
3b012a80
David Mayerich
added code for co...
|
288
289
290
291
292
293
294
295
|
{
std::stringstream ss;
int si = -1;
if(sections.size() > 0)
si = 0;
|
81e0d221
David Mayerich
separated executa...
|
296
297
|
//for each option
for(unsigned int a=0; a<opts.size(); a++)
|
3b012a80
David Mayerich
added code for co...
|
298
299
300
301
|
{
if(si != -1 && a == sections[si].index)
{
if(ansi)
|
0ef519a4
David Mayerich
optimized materia...
|
302
|
ss<<std::endl<<std::left<<std::setfill('=')<<std::setw(col_width)<<std::string("\033[1;31m") + sections[si].name<<"\033[0m"<<std::endl;
|
3b012a80
David Mayerich
added code for co...
|
303
|
else
|
0ef519a4
David Mayerich
optimized materia...
|
304
|
ss<<std::endl<<std::left<<std::setfill('=')<<std::setw(col_width)<<sections[si].name<<std::endl;
|
3b012a80
David Mayerich
added code for co...
|
305
|
si++;
|
2e73e7bc
David Mayerich
basic changes for...
|
306
|
if(si == (int)sections.size()) si = -1;
|
3b012a80
David Mayerich
added code for co...
|
307
308
|
}
|
81e0d221
David Mayerich
separated executa...
|
309
|
ss<<opts[a].toStr(col_width)<<std::endl;
|
3b012a80
David Mayerich
added code for co...
|
310
311
312
313
314
315
316
|
}
return ss.str();
}
int index(std::string _name)
{
|
81e0d221
David Mayerich
separated executa...
|
317
|
unsigned int i = find(opts.begin(), opts.end(), _name) - opts.begin();
|
3b012a80
David Mayerich
added code for co...
|
318
|
|
81e0d221
David Mayerich
separated executa...
|
319
|
if(i >= opts.size())
|
cac62fd3
David Mayerich
modified to work ...
|
320
|
return -1;
|
3b012a80
David Mayerich
added code for co...
|
321
|
|
cac62fd3
David Mayerich
modified to work ...
|
322
|
return (int)i;
|
3b012a80
David Mayerich
added code for co...
|
323
324
325
326
327
328
329
330
|
}
void set(std::string _name, std::string _value)
{
int i = index(_name);
if(i != -1)
{
|
81e0d221
David Mayerich
separated executa...
|
331
|
opts[i].set(_value);
|
3b012a80
David Mayerich
added code for co...
|
332
|
//adjust the column width if necessary
|
81e0d221
David Mayerich
separated executa...
|
333
|
col_width = (std::max)(col_width, opts[i].col_width());
|
3b012a80
David Mayerich
added code for co...
|
334
335
|
}
else
|
81e0d221
David Mayerich
separated executa...
|
336
|
std::cout<<"ERROR - option not recognized: "<<_name<<std::endl;
|
3b012a80
David Mayerich
added code for co...
|
337
338
339
340
341
|
}
//parse a parameter string
void parse(int argc, char* argv[])
{
|
81e0d221
David Mayerich
separated executa...
|
342
|
//if the number of options is 1, we're done
|
3b012a80
David Mayerich
added code for co...
|
343
344
345
346
347
|
if(argc <= 1) return;
std::string name;
std::string params;
|
81e0d221
David Mayerich
separated executa...
|
348
349
|
bool args_done = false; //create a flag that turns true when the first option is encountered
|
3b012a80
David Mayerich
added code for co...
|
350
351
|
for(int i=1; i<argc; i++)
{
|
81e0d221
David Mayerich
separated executa...
|
352
|
//if the argument is an option
|
3b012a80
David Mayerich
added code for co...
|
353
354
|
if(argv[i][0] == '-' && argv[i][1] == '-')
{
|
81e0d221
David Mayerich
separated executa...
|
355
356
|
args_done = true; //arguments for the executable are done, all options now
//add any previous options
|
3b012a80
David Mayerich
added code for co...
|
357
358
|
if(name != "")
set(name, params);
|
81e0d221
David Mayerich
separated executa...
|
359
|
//set the current option to this name
|
3b012a80
David Mayerich
added code for co...
|
360
361
362
363
|
name = argv[i]+2;
//clear the parameters list
params = "";
}
|
81e0d221
David Mayerich
separated executa...
|
364
365
366
367
|
else if(!args_done){
args.push_back(argv[i]);
}
else{ //everything else is an arg for the most recent option
|
3b012a80
David Mayerich
added code for co...
|
368
369
370
371
372
373
|
if(params != "")
params += " ";
params += argv[i];
}
}
|
81e0d221
David Mayerich
separated executa...
|
374
|
//set the last option
|
3b012a80
David Mayerich
added code for co...
|
375
376
377
378
379
380
|
set(name, params);
}
//determine if a parameter has been set (either specified by the user or with a default value)
bool operator()(std::string _name)
{
|
81e0d221
David Mayerich
separated executa...
|
381
|
int i = find(opts.begin(), opts.end(), _name) - opts.begin();
|
3b012a80
David Mayerich
added code for co...
|
382
383
384
385
386
387
388
|
if(i < 0)
{
std::cout<<"ERROR - Unspecified parameter name: "<<_name<<std::endl;
exit(1);
}
|
81e0d221
David Mayerich
separated executa...
|
389
|
return opts[i].is_set();
|
3b012a80
David Mayerich
added code for co...
|
390
391
|
}
|
81e0d221
David Mayerich
separated executa...
|
392
393
|
//number of arguments in a specified option
unsigned int nargs(std::string _name)
|
3b012a80
David Mayerich
added code for co...
|
394
|
{
|
81e0d221
David Mayerich
separated executa...
|
395
|
int i = find(opts.begin(), opts.end(), _name) - opts.begin();
|
3b012a80
David Mayerich
added code for co...
|
396
397
398
399
400
401
402
|
if(i < 0)
{
std::cout<<"ERROR - Unspecified parameter name: "<<_name<<std::endl;
exit(1);
}
|
81e0d221
David Mayerich
separated executa...
|
403
404
405
406
407
408
409
410
411
412
413
|
return opts[i].nargs();
}
//number of arguments for the executable
unsigned int nargs(){
return args.size();
}
//return the a'th executable argument
std::string arg(unsigned int a){
return args[a];
|
3b012a80
David Mayerich
added code for co...
|
414
415
|
}
|
81e0d221
David Mayerich
separated executa...
|
416
|
cmd_option operator[](std::string _name)
|
3b012a80
David Mayerich
added code for co...
|
417
|
{
|
81e0d221
David Mayerich
separated executa...
|
418
|
int i = find(opts.begin(), opts.end(), _name) - opts.begin();
|
3b012a80
David Mayerich
added code for co...
|
419
|
|
695d32fa
unknown
David's changes t...
|
420
|
if(i < 0 || i >= opts.size())
|
3b012a80
David Mayerich
added code for co...
|
421
422
423
424
425
|
{
std::cout<<"ERROR - Unspecified parameter name: "<<_name<<std::endl;
exit(1);
}
|
81e0d221
David Mayerich
separated executa...
|
426
|
return opts[i];
|
3b012a80
David Mayerich
added code for co...
|
427
428
429
|
}
|
7a2d0012
David Mayerich
mirst1d updates
|
430
431
432
433
|
};
|
2e73e7bc
David Mayerich
basic changes for...
|
434
|
} //end namespace stim
|
3b012a80
David Mayerich
added code for co...
|
435
436
|
#endif
|