blob: 42d7b7c3aa46830f2c2f77f27806e28c022273ae [file] [log] [blame]
#ifndef _param_utils_hpp_
#define _param_utils_hpp_
//@HEADER
// ************************************************************************
//
// MiniFE: Simple Finite Element Assembly and Solve
// Copyright (2006-2013) Sandia Corporation
//
// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
// license for use of this work by or on behalf of the U.S. Government.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
// ************************************************************************
//@HEADER
#include <string>
#include <sstream>
//Parameter-parsing Utilities:
//
//The functions declared below are intended to assist with parsing
//input-parameters which may be command-line arguments and/or lines in a
//text file.
//
// Scenario: You want your program to accept parameters that are specified
// as command-line arguments and/or as lines in a text file (such
// as a YAML output file). i.e., your program can be run like this:
// % program.exe foo=3.14159 bar: 42
// or
// % program.exe input_file=params.txt
// or
// % program.exe foo=3.14159 input_file = params.txt
//
//Example:
// Here is example code to obtain parameters using the 3 functions
// 'read_args_into_string', 'read_file_into_string' and 'parse_parameter':
//
// std::string arg_string;
//
// //put command-line-arguments into 'arg_string':
// read_args_into_string(argc, argv, arg_string);
//
// //do the command-line-arguments specify an 'input_file'?
// std::string filename =
// parse_parameter<std::string>(arg_string,"input_file","none-specified");
//
// if (filename != "none-specified") {
// std::string tmp;
// read_file_into_string(filename, tmp);
// arg_string += tmp;
// }
//
// //now parse the parameters:
// float foo = parse_parameter<float>(arg_string, "foo", -9.9);
// int bar = parse_parameter<int>(arg_string, "bar", -1);
//
//See the comments below for parse_parameter, for formatting requirements of
//named parameter-value pairs.
//
namespace Mantevo {
/**
* Concatenate command-line arguments into a single string.
*
* Note: this function is purely serial. If argc and argv have different
* values on different MPI processes, then you need to resolve that by
* broadcasting arg_string's contents.
*/
void read_args_into_string(int argc, char** argv, std::string& arg_string);
/**
* Read the contents of a text-file into a single string.
*
* Note: this function is purely serial. If you want file_contents on multiple
* MPI processes, you need to broadcast it (or call this function on each
* MPI process...).
*/
void read_file_into_string(const std::string& filename,
std::string& file_contents);
/**
* Parse a named parameter value from input 'arg_string'.
*
* Search 'arg_string' for an occurrence of param_name and attempt to parse
* a value into the return-type. If param_name is not found, then default_value
* is returned.
*
* Example:
* arg_string = "foo = 3.14159";
* float foo = parse_parameter<float>(arg_string, "foo", -999.9);
* //foo should now contain the value 3.14159; if 'foo' was not found in
* //arg_string, then -999.9 would have been returned.
*
* Other legal name-value separators are ':' and ' '. Extra spaces are also ok,
* e.g. "foo : 3.114159".
*
* Note that if a YAML file is read into a string, that would be a valid input
* string for this function.
*/
template<typename T>
T parse_parameter(const std::string& arg_string,
const std::string& param_name,
const T& default_value)
{
std::string::size_type pos = arg_string.find(param_name);
if (pos == std::string::npos) {
//if param_name is not found in arg_string, return default_value:
return default_value;
}
pos += param_name.size();
if (arg_string.size() <= pos) return default_value;
//skip past ' ', '=' or ':':
while(pos < arg_string.size() &&
(arg_string[pos] == ' ' ||
arg_string[pos] == '=' ||
arg_string[pos] == ':'))
{
++pos;
}
if (arg_string[pos] == '=' || arg_string[pos] == ':') ++pos;
std::string str = arg_string.substr(pos);
std::istringstream isstr(str);
T return_val = default_value;
//parse value into return_val:
isstr >> return_val;
//if parse failed, return default_value:
if (!isstr) return default_value;
return return_val;
}
}//namespace Mantevo
#endif