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