|
Boost Users : |
Subject: [Boost-users] program_options save config example
From: Neil Nelson (nnelson_at_[hidden])
Date: 2012-07-31 21:49:45
This post goes toward providing a config or log file output of the input
to Boost program_options. This was a requested capability but apparently
without further work. See the lines under 'config out:' at the end.
http://boost.2283326.n4.nabble.com/program-options-save-configuration-td2565566.html
The following Boost any page provides methods to convert the any values
upon iterating the vm map.
http://www.boost.org/doc/libs/1_50_0/doc/html/any/s02.html
// program_options_wrapper.hpp
// Latest boost program_options:
// See http://boost-sandbox.sourceforge.net/doc/html/program_options.html
// See http://svn.boost.org/svn/boost/trunk/libs/program_options/example/
#ifndef PROGRAM_OPTIONS_WRAPPER_HPP
#define PROGRAM_OPTIONS_WRAPPER_HPP
#include <boost/any.hpp>
#include <boost/program_options.hpp>
#include <string>
namespace po = boost::program_options;
class program_options_wrapper {
public:
po::variables_map vm;
po::options_description cmd_line;
po::options_description config;
po::options_description hidden;
po::options_description version;
po::options_description all;
// Singleton
static program_options_wrapper& instance() {
static program_options_wrapper instance_;
return instance_;
}
bool initialize(int argc, char **argv);
private:
std::string config_file;
// Singleton helpers
program_options_wrapper() {}
program_options_wrapper(program_options_wrapper const& copy);
program_options_wrapper& operator=(program_options_wrapper const&
copy);
bool is_empty(const boost::any & operand);
bool is_int(const boost::any & operand);
bool is_double(const boost::any & operand);
bool is_char_ptr(const boost::any & operand);
bool is_string(const boost::any & operand);
// void get_typeid(const boost::any & operand);
}; // class program_options_wrapper
#endif // #define PROGRAM_OPTIONS_WRAPPER_HPP
// program_options_wrapper.cpp
#include <boost/any.hpp>
#include <boost/program_options.hpp>
#include <string>
#include <vector>
#include <fstream>
#include "program_options_wrapper.hpp"
namespace po = boost::program_options;
bool program_options_wrapper::initialize(int argc, char **argv) {
version.add_options()
("version: program_options.cpp", "1.0")
("version: program_options.hpp", "1.0")
;
cmd_line.add_options()
("help,h", "produce help message")
("version,v", "list component versions")
("config,c", "configuration file name")
("report,r", "report run options")
("vector,x", boost::program_options::value<std::vector<std::string>
>(), "test string vector")
("double,d", boost::program_options::value<double>(), "test double")
;
all.add(cmd_line).add(config).add(hidden);
// po::store(po::parse_command_line(argc, argv, cmd_line), vm);
// po::notify(vm);
po::parsed_options parsed = po::command_line_parser(argc,
argv).options(cmd_line).allow_unregistered().run();
po::store(parsed, vm);
// po::store(po::command_line_parser(argc,
argv).options(cmd_line).allow_unregistered().run(), vm);
po::notify(vm);
if (vm.count("config")) {
std::ifstream ifs(config_file.c_str());
if (!ifs) {
std::cout << "can not open config file: " << config_file <<
std::endl;
return false;
}
else {
po::store(parse_config_file(ifs, config), vm);
po::notify(vm);
}
}
if (vm.count("help")) {
std::cout << all;
return false;
}
if (vm.count("version")) {
std::cout << version;
return false;
}
if (vm.count("report")) {
std::cout << all;
std::cout << version << std::endl;
std::cout << "command-line:";
for(int j=0;j<argc;j++) std::cout << " " << argv[j];
std::cout << std::endl << std::endl;
std::cout << "config out:" << std::endl;
for (po::variables_map::iterator it=vm.begin(); it != vm.end();
it++ ) {
if (is_empty(it->second.value()))
std::cout << "# " << it->first << "=is_empty" << std::endl;
if (vm[it->first].defaulted())
std::cout << "# " << it->first << "=is_defaulted" << std::endl;
if (is_int(it->second.value()))
std::cout << it->first << "=" << vm[it->first].as<int>() <<
std::endl;
else if (is_double(it->second.value()))
std::cout << it->first << "=" << vm[it->first].as<double>() <<
std::endl;
else if (is_char_ptr(it->second.value()))
std::cout << it->first << "=" << vm[it->first].as<const char
*>() << std::endl;
else if (is_string(it->second.value())) {
std::cout << it->first << "=";
std::string temp = vm[it->first].as<std::string>();
if (temp.size())
std::cout << temp << std::endl;
else
std::cout << "true" << std::endl;
}
else { // Assumes that the only remainder is vector<string>
std::vector<std::string> poVector =
vm[it->first].as<std::vector<std::string> >();
for (std::vector<std::string>::iterator vecIt=poVector.begin()
; vecIt != poVector.end(); vecIt++ )
std::cout << it->first << "=" << (*vecIt) << std::endl;
}
}
std::vector<std::string> unrecognized_options =
po::collect_unrecognized(parsed.options, po::include_positional);
if (unrecognized_options.size()) {
std::cout << std::endl << "unrecognized options:";
for (int j=0;j<unrecognized_options.size();j++)
std::cout << " " << unrecognized_options[j];
std::cout << std::endl;
}
std::cout << std::endl;
}
return true;
}
bool program_options_wrapper::is_empty(const boost::any & operand) {
return operand.empty();
}
bool program_options_wrapper::is_int(const boost::any & operand) {
return operand.type() == typeid(int);
}
bool program_options_wrapper::is_double(const boost::any & operand) {
return operand.type() == typeid(double);
}
bool program_options_wrapper::is_char_ptr(const boost::any & operand) {
try {
boost::any_cast<const char *>(operand);
return true;
}
catch(const boost::bad_any_cast &) {
return false;
}
}
bool program_options_wrapper::is_string(const boost::any & operand) {
return boost::any_cast<std::string>(&operand);
}
/*
void program_options_wrapper::get_typeid(const boost::any & operand) {
std::cout << operand.type().name() << std::endl;
}
*/
// test.cpp
/*
program_options.o: program_options_wrapper.hpp program_options_wrapper.cpp
g++-4.7 -g -c -Wall -std=c++11 program_options_wrapper.cpp -o \
program_options_wrapper.o
test: test.cpp program_options_wrapper.o
g++-4.7 -Wall -g -std=c++11 test.cpp -o test \
program_options_wrapper.o -lboost_program_options
*/
#include <boost/program_options.hpp>
#include <iostream>
#include "program_options_wrapper.hpp"
int main(int argc, char **argv) {
auto& po_wrap = program_options_wrapper::instance();
po_wrap.version.add_options()("version: build_state_tree.cpp", "1.0");
if (!po_wrap.initialize(argc, argv)) exit(0);
return 1;
}
// test output
-h [ --help ] produce help message
-v [ --version ] list component versions
-c [ --config ] configuration file name
-r [ --report ] report run options
-x [ --vector ] arg test string vector
-d [ --double ] arg test double
--version: build_state_tree.cpp 1.0
--version: program_options.cpp 1.0
--version: program_options.hpp 1.0
command-line: ./build_state_tree -r -x str1 -x str2 -d 345.67 -z testing
config out:
double=345.67
report=true
vector=str1
vector=str2
unrecognized options: -z testing
Neil Nelson
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net