Boost logo

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