/*v 0.2
simple parameters parsing helper
Example of code usage:
double param1; add_double_param(param1); //add "param1" to be recognized as input parameter
int param2; add_int_param(param2);
string par3; add_string_param(par3);
...
assert(load_parameters("input_parameters.txt")); //read parameters from input file
assert(cmdline_parameters(argc,argv)); //can be overriden by commandline, eg. ./simul [any_pars_without_minus] -param1 value1 -param3 value3
print_parameters(); //dump table of parameters values
Configuration file example (input_parameters.txt):
------
#any comment starts with '#'
#any numbers of blanks around
param1 3.14
#what is the meaning of life?
param2 42
-----
*/
#ifndef PARAMSHELP
#define PARAMSHELP
#include <string>
#include <sstream>
#include <assert.h>
#include <stdio.h>
using std::string;
using std::stringstream;
#define MAX_PARAMS 500
//buffer for parameter names and pointers to
//variables used for them in the main program
double *double_pars[MAX_PARAMS];
string double_par_name[MAX_PARAMS];
int double_count=0;
#define add_double_param(par) \
assert(double_count!=MAX_PARAMS);\
double_pars[double_count]=∥\
/*(*double_pars[double_count])=0;*/\
double_par_name[double_count++]=#par;
int *int_pars[MAX_PARAMS];
string int_par_name[MAX_PARAMS];
int int_count=0;
#define add_int_param(par) \
assert(int_count!=MAX_PARAMS);\
int_pars[int_count]=∥\
/*(*int_pars[int_count])=0;*/\
int_par_name[int_count++]=#par;
string *string_pars[MAX_PARAMS];
string string_par_name[MAX_PARAMS];
int string_count=0;
#define add_string_param(par) \
assert(string_count!=MAX_PARAMS);\
string_pars[string_count]=∥\
/*(*int_pars[int_count])=0;*/\
string_par_name[string_count++]=#par;
//parse one parameter on the given config line; returns 1 if line format is recognized
//result is put directly into global parameter
int parse_param(string line){
if (line.empty()) return 1;
string par1,par2; //line should be pair of inputs
stringstream parser(line);
if (!(parser>>par1)) return 1; //whitespace line
if (par1[0]=='#') return 1; //just comment
if (par1[0]=='-') par1=par1.substr(1); //allow "-param" in commandline
if (!(parser>>par2)) return 0; //missing value
int i;
for (i=0; i<double_count; i++) //double parameters
if (par1==double_par_name[i]){
if (!(stringstream(par2)>>*(double_pars[i]))) return 0;
return 1;
}
for (i=0; i<int_count; i++) //integer parameters
if (par1==int_par_name[i]){
if (!(stringstream(par2)>>*(int_pars[i]))) return 0;
return 1;
}
for (i=0; i<string_count; i++) //string parameters, we do not allow blanks
if (par1==string_par_name[i]){
(*(string_pars[i]))=par2;
return 1;
}
fprintf(stderr, "Unknown input parameter found.\n");
return 0; //no recognized parameter found
}//parse
//load parameters from file, returns 0 on error
int load_parameters(char const *file){
FILE *f=fopen(file,"r");
if (f==NULL) { fprintf(stderr, "File with input parameters not found.\n"); return 0; }
char line[4096];
while ( fgets(line,sizeof(line),f) != NULL )
if (!parse_param(line)) return 0;
fclose(f);
return 1;
}//load_parameters
//load parameters from commandline ("-param value" vector)
//expecting standard argc, argv arguments
//we allow different parameters on cmdline when they don't use "-" (eg. ./simul input.txt -param val)
int cmdline_parameters(int argc, char *argv[]){
argc--;
int i=0;
while (argc>++i) {
string s(argv[i]);
if (s.empty()) continue;
if (s[0]!='-') continue;
if (!parse_param(s+" "+string(argv[i+1]))) return 0;
i++; //jump over the value (can be negative, ie "-")
}
return 1;
}//cmdline_parameters
void print_parameters(){
for (int i=0; i<int_count;i++)
fprintf(stderr,"%s:\t%d\n",int_par_name[i].c_str(),*(int_pars[i]));
for (int i=0; i<double_count;i++)
fprintf(stderr,"%s:\t%lf\n",double_par_name[i].c_str(),*(double_pars[i]));
for (int i=0; i<string_count;i++)
fprintf(stderr,"%s:\t%s\n",string_par_name[i].c_str(),string_pars[i]->c_str());
}//print_parameters
#endif