automatic commit
[folded-ctf.git] / param_parser.cc
diff --git a/param_parser.cc b/param_parser.cc
new file mode 100644 (file)
index 0000000..5ae8a41
--- /dev/null
@@ -0,0 +1,146 @@
+
+///////////////////////////////////////////////////////////////////////////
+// This program is free software: you can redistribute it and/or modify  //
+// it under the terms of the version 3 of the GNU General Public License //
+// as published by the Free Software Foundation.                         //
+//                                                                       //
+// This program is distributed in the hope that it will be useful, but   //
+// WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      //
+// General Public License for more details.                              //
+//                                                                       //
+// You should have received a copy of the GNU General Public License     //
+// along with this program. If not, see <http://www.gnu.org/licenses/>.  //
+//                                                                       //
+// Written by Francois Fleuret, (C) IDIAP                                //
+// Contact <francois.fleuret@idiap.ch> for comments & bug reports        //
+///////////////////////////////////////////////////////////////////////////
+
+// All this is clearly non-optimal, loaded with news and deletes and
+// should be rewritten.
+
+#include <string.h>
+
+#include "param_parser.h"
+
+ParamParser::ParamParser() : _nb_max(10),
+                             _nb(0),
+                             _names(new char *[_nb_max]),
+                             _values(new char *[_nb_max]),
+                             _changed(new bool[_nb_max]) { }
+
+ParamParser::~ParamParser() {
+  for(int k = 0; k < _nb; k++) {
+    delete[] _names[k];
+    delete[] _values[k];
+  }
+  delete[] _names;
+  delete[] _values;
+  delete[] _changed;
+}
+
+void ParamParser::add_association(const char *variable_name, const char *variable_value, bool change) {
+  int n;
+
+  for(n = 0; n < _nb && strcmp(variable_name, _names[n]) != 0; n++);
+
+  if(n < _nb) {
+    delete[] _values[n];
+    _values[n] = new char[strlen(variable_value) + 1];
+    strcpy(_values[n], variable_value);
+    _changed[n] = change;
+  } else {
+    int nm;
+    nm = _nb_max; grow(&nm, _nb, &_names, 2);
+    nm = _nb_max; grow(&nm, _nb, &_values, 2);
+    grow(&_nb_max, _nb, &_changed, 2);
+
+    _names[_nb] = new char[strlen(variable_name) + 1];
+    strcpy(_names[_nb], variable_name);
+    _values[_nb] = new char[strlen(variable_value) + 1];
+    strcpy(_values[_nb], variable_value);
+    _changed[_nb] = change;
+    _nb++;
+  }
+}
+
+char *ParamParser::get_association(const char *variable_name) {
+  int n;
+  for(n = 0; n < _nb && strcmp(variable_name, _names[n]) != 0; n++);
+  if(n < _nb) return _values[n];
+  else        {
+    cerr << "Unknown parameter \"" << variable_name << "\", existing ones are" << endl;
+    for(int n = 0; n < _nb; n++)
+      cerr << "   \"" << _names[n] << "\"" << endl;
+    exit(1);
+  }
+}
+
+int ParamParser::get_association_int(const char *variable_name) {
+  char *u = get_association(variable_name);
+  char *s = u;
+  while(*s)
+    if((*s < '0' || *s > '9') && *s != '-') {
+      cerr << "Non-numerical value for " << variable_name << " (" << u << ")" << endl;
+      exit(1);
+    } else s++;
+  return atoi(u);
+}
+
+scalar_t ParamParser::get_association_scalar(const char *variable_name) {
+  char *u = get_association(variable_name);
+  char *s = u;
+  while(*s)
+    if((*s < '0' || *s > '9') && *s != '.' && *s != 'e' && *s != '-') {
+      cerr << "Non-numerical value for " << variable_name << " (" << u << ")" << endl;
+      exit(1);
+    } else s++;
+  return atof(u);
+}
+
+bool ParamParser::get_association_bool(const char *variable_name) {
+  char *value = get_association(variable_name);
+  if(strcasecmp(value, "") == 0 || strcasecmp(value, "y") == 0 || strcasecmp(value, "yes") == 0) return true;
+  if(strcasecmp(value, "n") == 0 || strcasecmp(value, "no") == 0) return false;
+  cerr << "Expects nothing (for yes), or y[es] or n[o] for a boolean argument and got '" << value << "'" << endl;
+  exit(1);
+}
+
+void ParamParser::parse_options(int argc, char **argv,
+                                bool allow_undefined,
+                                int *new_argc, char **new_argv) {
+
+  int i = 1;
+
+  if(new_argc && new_argv)
+    new_argv[(*new_argc)++] = argv[0];
+
+  while(i < argc) {
+    if(strncmp(argv[i], "--", 2) == 0) {
+      // This is so 70s! I luuuuv it!
+      char variable_name[buffer_size] = "", variable_value[buffer_size] = "";
+      char *o = argv[i] + 2, *s = variable_name, *u = variable_value;
+      while(*o && *o != '=') *s++ = *o++;
+      *s = '\0';
+      if(*o) { o++; while(*o) *u++ = *o++; }
+      *u = '\0';
+      if(!allow_undefined) get_association(variable_name);
+      add_association(variable_name, variable_value, true);
+    } else {
+      if(new_argc && new_argv)
+        new_argv[(*new_argc)++] = argv[i];
+      else {
+        cerr << "Can not parse " << argv[i] << endl;
+        exit(1);
+      }
+    }
+    i++;
+  }
+}
+
+void ParamParser::print_all(ostream *os) {
+  for(int n = 0; n < _nb; n++) {
+    (*os) << (_changed[n] ? " * " : "   ") << "\"" << _names[n] << "\" \"" << _values[n] << "\"" << endl;
+  }
+}
+