• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Vladimir Prus 2002-2004.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt
4 // or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 // This example shows how a user-defined class can be parsed using
7 // specific mechanism -- not the iostream operations used by default.
8 //
9 // A new class 'magic_number' is defined and the 'validate' method is overloaded
10 // to validate the values of that class using Boost.Regex.
11 // To test, run
12 //
13 //    regex -m 123-456
14 //    regex -m 123-4567
15 //
16 // The first invocation should output:
17 //
18 //   The magic is "456"
19 //
20 // and the second invocation should issue an error message.
21 
22 #include <boost/program_options.hpp>
23 #include <boost/regex.hpp>
24 
25 using namespace boost;
26 using namespace boost::program_options;
27 
28 #include <iostream>
29 using namespace std;
30 
31 /* Define a completely non-sensical class. */
32 struct magic_number {
33 public:
magic_numbermagic_number34     magic_number(int n) : n(n) {}
35     int n;
36 };
37 
38 /* Overload the 'validate' function for the user-defined class.
39    It makes sure that value is of form XXX-XXX
40    where X are digits and converts the second group to an integer.
41    This has no practical meaning, meant only to show how
42    regex can be used to validate values.
43 */
validate(boost::any & v,const std::vector<std::string> & values,magic_number *,int)44 void validate(boost::any& v,
45               const std::vector<std::string>& values,
46               magic_number*, int)
47 {
48     static regex r("\\d\\d\\d-(\\d\\d\\d)");
49 
50     using namespace boost::program_options;
51 
52     // Make sure no previous assignment to 'a' was made.
53     validators::check_first_occurrence(v);
54     // Extract the first string from 'values'. If there is more than
55     // one string, it's an error, and exception will be thrown.
56     const string& s = validators::get_single_string(values);
57 
58     // Do regex match and convert the interesting part to
59     // int.
60     smatch match;
61     if (regex_match(s, match, r)) {
62         v = any(magic_number(lexical_cast<int>(match[1])));
63     } else {
64         throw validation_error(validation_error::invalid_option_value);
65     }
66 }
67 
68 
main(int ac,char * av[])69 int main(int ac, char* av[])
70 {
71     try {
72         options_description desc("Allowed options");
73         desc.add_options()
74             ("help", "produce a help screen")
75             ("version,v", "print the version number")
76             ("magic,m", value<magic_number>(),
77                  "magic value (in NNN-NNN format)")
78             ;
79 
80         variables_map vm;
81         store(parse_command_line(ac, av, desc), vm);
82 
83         if (vm.count("help")) {
84             cout << "Usage: regex [options]\n";
85             cout << desc;
86             return 0;
87         }
88         if (vm.count("version")) {
89             cout << "Version 1.\n";
90             return 0;
91         }
92         if (vm.count("magic")) {
93             cout << "The magic is \""
94                  << vm["magic"].as<magic_number>().n << "\"\n";
95         }
96     }
97     catch(std::exception& e)
98     {
99         cout << e.what() << "\n";
100     }
101 }
102