[program-options] Problem with paths that have spaces

Hi all, I'm trying to use program-options to specify a filesystem path object under Boost 1.35.0. The following code works fine when the path specified on the command line has no spaces in it. But when it does have spaces, I get an error. --snip-- #include <iostream> #include <sstream> #include <boost/program_options.hpp> #include <boost/filesystem/path.hpp> namespace po = boost::program_options; namespace fs = boost::filesystem; using namespace std; int main (int argc, char * argv[]) { int result = 0; try { fs::path inPath; po::options_description desc("Allowed options"); desc.add_options() ("in,i", po::value<fs::path>(&inPath), "Input file or directory <pathname>") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); if (0 ==vm.count("in")) { throw invalid_argument("What? No input path specifed!"); } cout << "Input path = \"" << inPath.file_string() << "\"\n"; } catch(const boost::filesystem::filesystem_error& e) { cerr << "\nFilessytem error: " << e.what() << endl; result = 3; } catch(const std::exception& e) { cerr << "\nException error: " << e.what() << endl; result = 2; } catch(...) { cerr << "\nError: Caught an unknown exception!" << endl; result = 1; } return result; } --snip-- If I call the above with the following parameters, it works: --in "my_file" Input path = "my_file" But if I call it with a path that has a space in it, I get an error: --in "my file" Exception error: in option 'in': invalid option value 'my file' I know that I can work around the problem by loading the path into an interim string first, then use the string to initialize a path object. But unless I'm missing something, I would have thought that iteroperability between boost.program-options and boost.filesystem should be more seamless. It seems very common to want to load options into path objects. Best, -- Allen Cronce

Allen Cronce wrote:
fs::path inPath;
po::options_description desc("Allowed options"); desc.add_options() ("in,i", po::value<fs::path>(&inPath), "Input file or directory <pathname>")
If I call the above with the following parameters, it works:
--in "my_file"
Input path = "my_file"
But if I call it with a path that has a space in it, I get an error:
--in "my file"
Exception error: in option 'in': invalid option value 'my file'
I know that I can work around the problem by loading the path into an interim string first, then use the string to initialize a path object. But unless I'm missing something, I would have thought that iteroperability between boost.program-options and boost.filesystem should be more seamless. It seems very common to want to load options into path objects.
I am not aware of boost.program_options has any special support for boost::filesystem::path, which suggests that processing of this option goes via generic path: template<class T, class charT> void validate(boost::any& v, const std::vector< std::basic_string<charT> >& xs, T*, long) { validators::check_first_occurrence(v); std::basic_string<charT> s(validators::get_single_string(xs)); try { v = any(lexical_cast<T>(s)); } catch(const bad_lexical_cast&) { boost::throw_exception(invalid_option_value(s)); } } and the error message you get is 'what()' of invalid_option_value. In other words, it appears that lexical_cast from a string with spaces into boost::filesystem::path does not work. And it clear why: template< class Path > std::basic_istream< typename Path::string_type::value_type, typename Path::string_type::traits_type > & operator>> ( std::basic_istream< typename Path::string_type::value_type, typename Path::string_type::traits_type >& is, Path & ph ) { typename Path::string_type str; is >> str; ph = str; return is; } Extractor operator for string stops on whitespace. The fix, IMO, is to special case conversion to boost::filesystem::path in lexical_cast, just like it's already done for conversion to string. Beman, what do you think? - Volodya
participants (2)
-
Allen Cronce
-
Vladimir Prus