
Hi, I have made another change to the code, in config_file.cpp this time. I noticed that collect_unrecognized() didn't work on output of the config file parser as it doesnt set the original_tokens field. Its doens't error, just doesn't collect anything. I have thus written the parser such that the keyname is written to the original_tokens field if the keyname is unregistered, allowing collect_unrecognized to do its job as expected. diff below. Is this the right list for this kind of discussion by the way? Best, Diederick ------ Index: config_file.cpp =================================================================== --- config_file.cpp (revision 54915) +++ config_file.cpp (working copy) @@ -114,6 +114,15 @@ this->value().value.clear(); this->value().value.push_back(value); this->value().unregistered = !registered; + + // add name to original_tokens so we can run collect_unregi stered + // over po::parsed_options from po::parse_config_file too + this->value().original_tokens.clear(); + if (!registered) + { + this->value().original_tokens.push_back(name); + } + break; } else { On Tue, Jul 14, 2009 at 12:53 PM, Diederick C. Niehorster<dcnieho@gmail.com> wrote:
Hi Volodya,
Thank you for your reply. I have placed my code, improved, into the validate() function now (see below). Thats a good idea anyway, this way it works on input from any source. I am still stuck with the issue of how to test whether users specified a vector or not as return target in their options_description, that is: ("Tex.GaussSigma", po::value<float>(&fTexGaussSigma) , "Tex.GaussSigma") or ("Tex.Color" , po::value<vector<float>>(&vfTexColor), "Expt.Color")
Due to the very complicated flow (if you've just looked at the code for a few hours) I find it hard to figure out. I suppose i have to run typeid(*something*).name() to get the type of some variable and then check if its a vector or not. But what should be in the place of *something*?
As a general point, do you think this would be a good addition to the parser, that is, would you want to incorporate this kind of extention into the Boost release? It is a much easier way of specifying a vector, whether on the command line or from another source without having to resort to positional options, which are not a good solution for every source and situation. Compare (for command line) [--test "(1 2)"] with [--test 1 --test 2].
Lastly, in an old post (cant find it now, was 2005 or 2006) a user asked whether it was possible to do po::parse_config_file(InitFileName,poInit,true); instead of po::parse_config_file(ifs,poInit,true); as the documentation apparently reflected this at that point. You replied that you'd fix that at that time (I believe it was you, doesn't really matter), but when i just tried it didnt work. Have you decided against it?
Best, Diederick
----- Index: detail/value_semantic.hpp =================================================================== --- detail/value_semantic.hpp (revision 54915) +++ detail/value_semantic.hpp (working copy) @@ -8,6 +8,8 @@
#include <boost/throw_exception.hpp>
+#include <boost/algorithm/string.hpp> + namespace boost { namespace program_options {
extern BOOST_PROGRAM_OPTIONS_DECL std::string arg; @@ -142,11 +144,28 @@ /* We call validate so that if user provided a validator for class T, we use it even when parsing vector<T>. */ - boost::any a; - std::vector<std::basic_string<charT> > v; - v.push_back(s[i]); - validate(a, v, (T*)0, 0); - tv->push_back(boost::any_cast<T>(a)); + + vector<std::basic_string<charT>> value; + + // test if vector notation is used in input + if (*s[i].begin() == '(' && *s[i].rbegin() == ')') + { + // TODO: test if vector is expected by user, if not, no spl itting + // TODO: if vector expected, test if its vector of strings, that will need special treatment + split( value, s[i].substr(1, s[i].size()-2), is_any_of(" ") ); + } + else + value.push_back(s[i]); + + // validate option values + for (unsigned j = 0; j < value.size(); j++) + { + boost::any a; + std::vector<std::basic_string<charT> > v; + v.push_back(value[j]); + validate(a, v, (T*)0, 0); + tv->push_back(boost::any_cast<T>(a)); + } } catch(const bad_lexical_cast& /*e*/) { boost::throw_exception(invalid_option_value(s[i]));