*** empty log message ***
[folded-ctf.git] / param_parser.cc
1
2 ///////////////////////////////////////////////////////////////////////////
3 // This program is free software: you can redistribute it and/or modify  //
4 // it under the terms of the version 3 of the GNU General Public License //
5 // as published by the Free Software Foundation.                         //
6 //                                                                       //
7 // This program is distributed in the hope that it will be useful, but   //
8 // WITHOUT ANY WARRANTY; without even the implied warranty of            //
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      //
10 // General Public License for more details.                              //
11 //                                                                       //
12 // You should have received a copy of the GNU General Public License     //
13 // along with this program. If not, see <http://www.gnu.org/licenses/>.  //
14 //                                                                       //
15 // Written by Francois Fleuret, (C) IDIAP                                //
16 // Contact <francois.fleuret@idiap.ch> for comments & bug reports        //
17 ///////////////////////////////////////////////////////////////////////////
18
19 // All this is clearly non-optimal, loaded with news and deletes and
20 // should be rewritten.
21
22 #include <string.h>
23
24 #include "param_parser.h"
25
26 ParamParser::ParamParser() : _nb_max(10),
27                              _nb(0),
28                              _names(new char *[_nb_max]),
29                              _values(new char *[_nb_max]),
30                              _changed(new bool[_nb_max]) { }
31
32 ParamParser::~ParamParser() {
33   for(int k = 0; k < _nb; k++) {
34     delete[] _names[k];
35     delete[] _values[k];
36   }
37   delete[] _names;
38   delete[] _values;
39   delete[] _changed;
40 }
41
42 void ParamParser::add_association(const char *variable_name, const char *variable_value, bool change) {
43   int n;
44
45   for(n = 0; n < _nb && strcmp(variable_name, _names[n]) != 0; n++);
46
47   if(n < _nb) {
48     delete[] _values[n];
49     _values[n] = new char[strlen(variable_value) + 1];
50     strcpy(_values[n], variable_value);
51     _changed[n] = change;
52   } else {
53     int nm;
54     nm = _nb_max; grow(&nm, _nb, &_names, 2);
55     nm = _nb_max; grow(&nm, _nb, &_values, 2);
56     grow(&_nb_max, _nb, &_changed, 2);
57
58     _names[_nb] = new char[strlen(variable_name) + 1];
59     strcpy(_names[_nb], variable_name);
60     _values[_nb] = new char[strlen(variable_value) + 1];
61     strcpy(_values[_nb], variable_value);
62     _changed[_nb] = change;
63     _nb++;
64   }
65 }
66
67 char *ParamParser::get_association(const char *variable_name) {
68   int n;
69   for(n = 0; n < _nb && strcmp(variable_name, _names[n]) != 0; n++);
70   if(n < _nb) return _values[n];
71   else        {
72     cerr << "Unknown parameter \"" << variable_name << "\", existing ones are" << endl;
73     for(int n = 0; n < _nb; n++)
74       cerr << "   \"" << _names[n] << "\"" << endl;
75     exit(1);
76   }
77 }
78
79 int ParamParser::get_association_int(const char *variable_name) {
80   char *u = get_association(variable_name);
81   char *s = u;
82   while(*s)
83     if((*s < '0' || *s > '9') && *s != '-') {
84       cerr << "Non-numerical value for " << variable_name << " (" << u << ")" << endl;
85       exit(1);
86     } else s++;
87   return atoi(u);
88 }
89
90 scalar_t ParamParser::get_association_scalar(const char *variable_name) {
91   char *u = get_association(variable_name);
92   char *s = u;
93   while(*s)
94     if((*s < '0' || *s > '9') && *s != '.' && *s != 'e' && *s != '-') {
95       cerr << "Non-numerical value for " << variable_name << " (" << u << ")" << endl;
96       exit(1);
97     } else s++;
98   return atof(u);
99 }
100
101 bool ParamParser::get_association_bool(const char *variable_name) {
102   char *value = get_association(variable_name);
103   if(strcasecmp(value, "") == 0 || strcasecmp(value, "y") == 0 || strcasecmp(value, "yes") == 0) return true;
104   if(strcasecmp(value, "n") == 0 || strcasecmp(value, "no") == 0) return false;
105   cerr << "Expects nothing (for yes), or y[es] or n[o] for a boolean argument and got '" << value << "'" << endl;
106   exit(1);
107 }
108
109 void ParamParser::parse_options(int argc, char **argv,
110                                 bool allow_undefined,
111                                 int *new_argc, char **new_argv) {
112
113   int i = 1;
114
115   if(new_argc && new_argv)
116     new_argv[(*new_argc)++] = argv[0];
117
118   while(i < argc) {
119     if(strncmp(argv[i], "--", 2) == 0) {
120       // This is so 70s! I luuuuv it!
121       char variable_name[buffer_size] = "", variable_value[buffer_size] = "";
122       char *o = argv[i] + 2, *s = variable_name, *u = variable_value;
123       while(*o && *o != '=') *s++ = *o++;
124       *s = '\0';
125       if(*o) { o++; while(*o) *u++ = *o++; }
126       *u = '\0';
127       if(!allow_undefined) get_association(variable_name);
128       add_association(variable_name, variable_value, true);
129     } else {
130       if(new_argc && new_argv)
131         new_argv[(*new_argc)++] = argv[i];
132       else {
133         cerr << "Can not parse " << argv[i] << endl;
134         exit(1);
135       }
136     }
137     i++;
138   }
139 }
140
141 void ParamParser::print_all(ostream *os) {
142   for(int n = 0; n < _nb; n++) {
143     (*os) << (_changed[n] ? " * " : "   ") << "\"" << _names[n] << "\" \"" << _values[n] << "\"" << endl;
144   }
145 }
146