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