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: |
---|
34 | 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 | */ |
---|
44 | void validate(boost::any& v, |
---|
45 | const std::vector<std::string>& values, |
---|
46 | magic_number* target_type, 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("invalid value"); |
---|
65 | } |
---|
66 | } |
---|
67 | |
---|
68 | |
---|
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(exception& e) |
---|
98 | { |
---|
99 | cout << e.what() << "\n"; |
---|
100 | } |
---|
101 | } |
---|