Chris@16
|
1 // Copyright Vladimir Prus 2002-2004.
|
Chris@16
|
2 // Copyright Bertolt Mildner 2004.
|
Chris@16
|
3 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
4 // (See accompanying file LICENSE_1_0.txt
|
Chris@16
|
5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6
|
Chris@16
|
7
|
Chris@16
|
8 #ifndef BOOST_OPTION_DESCRIPTION_VP_2003_05_19
|
Chris@16
|
9 #define BOOST_OPTION_DESCRIPTION_VP_2003_05_19
|
Chris@16
|
10
|
Chris@16
|
11 #include <boost/program_options/config.hpp>
|
Chris@16
|
12 #include <boost/program_options/errors.hpp>
|
Chris@16
|
13 #include <boost/program_options/value_semantic.hpp>
|
Chris@16
|
14
|
Chris@16
|
15 #include <boost/function.hpp>
|
Chris@16
|
16 #include <boost/shared_ptr.hpp>
|
Chris@16
|
17 #include <boost/detail/workaround.hpp>
|
Chris@16
|
18 #include <boost/any.hpp>
|
Chris@16
|
19
|
Chris@16
|
20 #include <string>
|
Chris@16
|
21 #include <vector>
|
Chris@16
|
22 #include <set>
|
Chris@16
|
23 #include <map>
|
Chris@16
|
24 #include <stdexcept>
|
Chris@16
|
25
|
Chris@16
|
26 #include <iosfwd>
|
Chris@16
|
27
|
Chris@16
|
28 #if defined(BOOST_MSVC)
|
Chris@16
|
29 # pragma warning (push)
|
Chris@16
|
30 # pragma warning (disable:4251) // class 'boost::shared_ptr<T>' needs to have dll-interface to be used by clients of class 'boost::program_options::option_description'
|
Chris@16
|
31 #endif
|
Chris@16
|
32
|
Chris@16
|
33
|
Chris@16
|
34 /** Boost namespace */
|
Chris@16
|
35 namespace boost {
|
Chris@16
|
36 /** Namespace for the library. */
|
Chris@16
|
37 namespace program_options {
|
Chris@16
|
38
|
Chris@16
|
39 /** Describes one possible command line/config file option. There are two
|
Chris@16
|
40 kinds of properties of an option. First describe it syntactically and
|
Chris@16
|
41 are used only to validate input. Second affect interpretation of the
|
Chris@16
|
42 option, for example default value for it or function that should be
|
Chris@16
|
43 called when the value is finally known. Routines which perform parsing
|
Chris@16
|
44 never use second kind of properties -- they are side effect free.
|
Chris@16
|
45 @sa options_description
|
Chris@16
|
46 */
|
Chris@16
|
47 class BOOST_PROGRAM_OPTIONS_DECL option_description {
|
Chris@16
|
48 public:
|
Chris@16
|
49
|
Chris@16
|
50 option_description();
|
Chris@16
|
51
|
Chris@16
|
52 /** Initializes the object with the passed data.
|
Chris@16
|
53
|
Chris@16
|
54 Note: it would be nice to make the second parameter auto_ptr,
|
Chris@16
|
55 to explicitly pass ownership. Unfortunately, it's often needed to
|
Chris@16
|
56 create objects of types derived from 'value_semantic':
|
Chris@16
|
57 options_description d;
|
Chris@16
|
58 d.add_options()("a", parameter<int>("n")->default_value(1));
|
Chris@16
|
59 Here, the static type returned by 'parameter' should be derived
|
Chris@16
|
60 from value_semantic.
|
Chris@16
|
61
|
Chris@16
|
62 Alas, derived->base conversion for auto_ptr does not really work,
|
Chris@16
|
63 see
|
Chris@101
|
64 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2000/n1232.pdf
|
Chris@101
|
65 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#84
|
Chris@16
|
66
|
Chris@16
|
67 So, we have to use plain old pointers. Besides, users are not
|
Chris@16
|
68 expected to use the constructor directly.
|
Chris@16
|
69
|
Chris@16
|
70
|
Chris@16
|
71 The 'name' parameter is interpreted by the following rules:
|
Chris@16
|
72 - if there's no "," character in 'name', it specifies long name
|
Chris@16
|
73 - otherwise, the part before "," specifies long name and the part
|
Chris@16
|
74 after -- short name.
|
Chris@16
|
75 */
|
Chris@16
|
76 option_description(const char* name,
|
Chris@16
|
77 const value_semantic* s);
|
Chris@16
|
78
|
Chris@16
|
79 /** Initializes the class with the passed data.
|
Chris@16
|
80 */
|
Chris@16
|
81 option_description(const char* name,
|
Chris@16
|
82 const value_semantic* s,
|
Chris@16
|
83 const char* description);
|
Chris@16
|
84
|
Chris@16
|
85 virtual ~option_description();
|
Chris@16
|
86
|
Chris@16
|
87 enum match_result { no_match, full_match, approximate_match };
|
Chris@16
|
88
|
Chris@16
|
89 /** Given 'option', specified in the input source,
|
Chris@16
|
90 returns 'true' if 'option' specifies *this.
|
Chris@16
|
91 */
|
Chris@16
|
92 match_result match(const std::string& option, bool approx,
|
Chris@16
|
93 bool long_ignore_case, bool short_ignore_case) const;
|
Chris@16
|
94
|
Chris@16
|
95 /** Returns the key that should identify the option, in
|
Chris@16
|
96 particular in the variables_map class.
|
Chris@16
|
97 The 'option' parameter is the option spelling from the
|
Chris@16
|
98 input source.
|
Chris@16
|
99 If option name contains '*', returns 'option'.
|
Chris@16
|
100 If long name was specified, it's the long name, otherwise
|
Chris@16
|
101 it's a short name with prepended '-'.
|
Chris@16
|
102 */
|
Chris@16
|
103 const std::string& key(const std::string& option) const;
|
Chris@16
|
104
|
Chris@16
|
105
|
Chris@16
|
106 /** Returns the canonical name for the option description to enable the user to
|
Chris@16
|
107 recognised a matching option.
|
Chris@16
|
108 1) For short options ('-', '/'), returns the short name prefixed.
|
Chris@16
|
109 2) For long options ('--' / '-') returns the long name prefixed
|
Chris@16
|
110 3) All other cases, returns the long name (if present) or the short name,
|
Chris@16
|
111 unprefixed.
|
Chris@16
|
112 */
|
Chris@16
|
113 std::string canonical_display_name(int canonical_option_style = 0) const;
|
Chris@16
|
114
|
Chris@16
|
115 const std::string& long_name() const;
|
Chris@16
|
116
|
Chris@16
|
117 /// Explanation of this option
|
Chris@16
|
118 const std::string& description() const;
|
Chris@16
|
119
|
Chris@16
|
120 /// Semantic of option's value
|
Chris@16
|
121 shared_ptr<const value_semantic> semantic() const;
|
Chris@16
|
122
|
Chris@16
|
123 /// Returns the option name, formatted suitably for usage message.
|
Chris@16
|
124 std::string format_name() const;
|
Chris@16
|
125
|
Chris@16
|
126 /** Returns the parameter name and properties, formatted suitably for
|
Chris@16
|
127 usage message. */
|
Chris@16
|
128 std::string format_parameter() const;
|
Chris@16
|
129
|
Chris@16
|
130 private:
|
Chris@16
|
131
|
Chris@16
|
132 option_description& set_name(const char* name);
|
Chris@16
|
133
|
Chris@16
|
134 std::string m_short_name, m_long_name, m_description;
|
Chris@16
|
135 // shared_ptr is needed to simplify memory management in
|
Chris@16
|
136 // copy ctor and destructor.
|
Chris@16
|
137 shared_ptr<const value_semantic> m_value_semantic;
|
Chris@16
|
138 };
|
Chris@16
|
139
|
Chris@16
|
140 class options_description;
|
Chris@16
|
141
|
Chris@16
|
142 /** Class which provides convenient creation syntax to option_description.
|
Chris@16
|
143 */
|
Chris@16
|
144 class BOOST_PROGRAM_OPTIONS_DECL options_description_easy_init {
|
Chris@16
|
145 public:
|
Chris@16
|
146 options_description_easy_init(options_description* owner);
|
Chris@16
|
147
|
Chris@16
|
148 options_description_easy_init&
|
Chris@16
|
149 operator()(const char* name,
|
Chris@16
|
150 const char* description);
|
Chris@16
|
151
|
Chris@16
|
152 options_description_easy_init&
|
Chris@16
|
153 operator()(const char* name,
|
Chris@16
|
154 const value_semantic* s);
|
Chris@16
|
155
|
Chris@16
|
156 options_description_easy_init&
|
Chris@16
|
157 operator()(const char* name,
|
Chris@16
|
158 const value_semantic* s,
|
Chris@16
|
159 const char* description);
|
Chris@16
|
160
|
Chris@16
|
161 private:
|
Chris@16
|
162 options_description* owner;
|
Chris@16
|
163 };
|
Chris@16
|
164
|
Chris@16
|
165
|
Chris@16
|
166 /** A set of option descriptions. This provides convenient interface for
|
Chris@16
|
167 adding new option (the add_options) method, and facilities to search
|
Chris@16
|
168 for options by name.
|
Chris@16
|
169
|
Chris@16
|
170 See @ref a_adding_options "here" for option adding interface discussion.
|
Chris@16
|
171 @sa option_description
|
Chris@16
|
172 */
|
Chris@16
|
173 class BOOST_PROGRAM_OPTIONS_DECL options_description {
|
Chris@16
|
174 public:
|
Chris@16
|
175 static const unsigned m_default_line_length;
|
Chris@16
|
176
|
Chris@16
|
177 /** Creates the instance. */
|
Chris@16
|
178 options_description(unsigned line_length = m_default_line_length,
|
Chris@16
|
179 unsigned min_description_length = m_default_line_length / 2);
|
Chris@16
|
180 /** Creates the instance. The 'caption' parameter gives the name of
|
Chris@16
|
181 this 'options_description' instance. Primarily useful for output.
|
Chris@16
|
182 The 'description_length' specifies the number of columns that
|
Chris@16
|
183 should be reserved for the description text; if the option text
|
Chris@16
|
184 encroaches into this, then the description will start on the next
|
Chris@16
|
185 line.
|
Chris@16
|
186 */
|
Chris@16
|
187 options_description(const std::string& caption,
|
Chris@16
|
188 unsigned line_length = m_default_line_length,
|
Chris@16
|
189 unsigned min_description_length = m_default_line_length / 2);
|
Chris@16
|
190 /** Adds new variable description. Throws duplicate_variable_error if
|
Chris@16
|
191 either short or long name matches that of already present one.
|
Chris@16
|
192 */
|
Chris@16
|
193 void add(shared_ptr<option_description> desc);
|
Chris@16
|
194 /** Adds a group of option description. This has the same
|
Chris@16
|
195 effect as adding all option_descriptions in 'desc'
|
Chris@16
|
196 individually, except that output operator will show
|
Chris@16
|
197 a separate group.
|
Chris@16
|
198 Returns *this.
|
Chris@16
|
199 */
|
Chris@16
|
200 options_description& add(const options_description& desc);
|
Chris@16
|
201
|
Chris@101
|
202 /** Find the maximum width of the option column, including options
|
Chris@101
|
203 in groups. */
|
Chris@101
|
204 unsigned get_option_column_width() const;
|
Chris@101
|
205
|
Chris@16
|
206 public:
|
Chris@16
|
207 /** Returns an object of implementation-defined type suitable for adding
|
Chris@16
|
208 options to options_description. The returned object will
|
Chris@16
|
209 have overloaded operator() with parameter type matching
|
Chris@16
|
210 'option_description' constructors. Calling the operator will create
|
Chris@16
|
211 new option_description instance and add it.
|
Chris@16
|
212 */
|
Chris@16
|
213 options_description_easy_init add_options();
|
Chris@16
|
214
|
Chris@16
|
215 const option_description& find(const std::string& name,
|
Chris@16
|
216 bool approx,
|
Chris@16
|
217 bool long_ignore_case = false,
|
Chris@16
|
218 bool short_ignore_case = false) const;
|
Chris@16
|
219
|
Chris@16
|
220 const option_description* find_nothrow(const std::string& name,
|
Chris@16
|
221 bool approx,
|
Chris@16
|
222 bool long_ignore_case = false,
|
Chris@16
|
223 bool short_ignore_case = false) const;
|
Chris@16
|
224
|
Chris@16
|
225
|
Chris@16
|
226 const std::vector< shared_ptr<option_description> >& options() const;
|
Chris@16
|
227
|
Chris@16
|
228 /** Produces a human readable output of 'desc', listing options,
|
Chris@16
|
229 their descriptions and allowed parameters. Other options_description
|
Chris@16
|
230 instances previously passed to add will be output separately. */
|
Chris@16
|
231 friend BOOST_PROGRAM_OPTIONS_DECL std::ostream& operator<<(std::ostream& os,
|
Chris@16
|
232 const options_description& desc);
|
Chris@16
|
233
|
Chris@16
|
234 /** Outputs 'desc' to the specified stream, calling 'f' to output each
|
Chris@16
|
235 option_description element. */
|
Chris@101
|
236 void print(std::ostream& os, unsigned width = 0) const;
|
Chris@16
|
237
|
Chris@16
|
238 private:
|
Chris@16
|
239 typedef std::map<std::string, int>::const_iterator name2index_iterator;
|
Chris@16
|
240 typedef std::pair<name2index_iterator, name2index_iterator>
|
Chris@16
|
241 approximation_range;
|
Chris@16
|
242
|
Chris@16
|
243 //approximation_range find_approximation(const std::string& prefix) const;
|
Chris@16
|
244
|
Chris@16
|
245 std::string m_caption;
|
Chris@16
|
246 const unsigned m_line_length;
|
Chris@16
|
247 const unsigned m_min_description_length;
|
Chris@16
|
248
|
Chris@16
|
249 // Data organization is chosen because:
|
Chris@16
|
250 // - there could be two names for one option
|
Chris@16
|
251 // - option_add_proxy needs to know the last added option
|
Chris@16
|
252 std::vector< shared_ptr<option_description> > m_options;
|
Chris@16
|
253
|
Chris@16
|
254 // Whether the option comes from one of declared groups.
|
Chris@16
|
255 #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(313))
|
Chris@16
|
256 // vector<bool> is buggy there, see
|
Chris@16
|
257 // http://support.microsoft.com/default.aspx?scid=kb;en-us;837698
|
Chris@16
|
258 std::vector<char> belong_to_group;
|
Chris@16
|
259 #else
|
Chris@16
|
260 std::vector<bool> belong_to_group;
|
Chris@16
|
261 #endif
|
Chris@16
|
262
|
Chris@16
|
263 std::vector< shared_ptr<options_description> > groups;
|
Chris@16
|
264
|
Chris@16
|
265 };
|
Chris@16
|
266
|
Chris@16
|
267 /** Class thrown when duplicate option description is found. */
|
Chris@16
|
268 class BOOST_PROGRAM_OPTIONS_DECL duplicate_option_error : public error {
|
Chris@16
|
269 public:
|
Chris@16
|
270 duplicate_option_error(const std::string& xwhat) : error(xwhat) {}
|
Chris@16
|
271 };
|
Chris@16
|
272 }}
|
Chris@16
|
273
|
Chris@16
|
274 #if defined(BOOST_MSVC)
|
Chris@16
|
275 # pragma warning (pop)
|
Chris@16
|
276 #endif
|
Chris@16
|
277
|
Chris@16
|
278 #endif
|