File: program_options.h

package info (click to toggle)
aspcud 1%3A1.9.1-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 69,268 kB
  • sloc: ansic: 5,078; cpp: 3,783; yacc: 182; sh: 114; makefile: 4
file content (318 lines) | stat: -rw-r--r-- 9,880 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
//
// Copyright (c) 2006-2007, Benjamin Kaufmann
//
// This file is part of aspcud.
//
// gringo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// gringo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with gringo.  If not, see <http://www.gnu.org/licenses/>.
//

#ifndef PROGRAM_OPTIONS_PROGRAM_OPTIONS_H_INCLUDED
#define PROGRAM_OPTIONS_PROGRAM_OPTIONS_H_INCLUDED
#include <string>
#ifdef _MSC_VER
#pragma warning (disable : 4786)
#pragma warning (disable : 4503)
namespace std {
	using ::size_t;
}
#endif
#include <iosfwd>
#include <map>
#include <vector>
#include <set>
#include <stdexcept>
#include <memory>
#include "value_base.h"
#include "detail/smartpointer.h"
namespace ProgramOptions {
	class ValueBase;
	//! represents one program option.
	/*!
	* An Option consists of a description (long name, short name, description) 
	* and a (typed) value.
	*/
	class Option
	{
	public:
		/*!
		* \pre longName != ""
		* \pre value != 0
		*/
		Option( const std::string& longName, const std::string& shortName,
			const std::string& description, const std::string& argDesc, ValueBase* value);

		~Option();

		const std::string& longName() const   {return longName_;}
		const std::string& shortName() const  {return shortName_;}
		const std::string& description() const  {return description_;}
		const std::string& argDescription() const { return argDesc_; }

		SharedPtr<ValueBase> getValue() const {return value_;}
	private:
		std::string longName_;
		std::string shortName_;
		std::string description_;
		std::string argDesc_;
		SharedPtr<ValueBase> value_;
	};

	class OptionGroupInitHelper;

	//! container of options
	class OptionGroup
	{
	public:
		/*!
		* \param description A string that describes this group. Primarily useful for output
		*/
		OptionGroup(const std::string& description = "");
		~OptionGroup();

		//! returns an object that can be used to add options
		/*!
		* \par usage \n
		* \code
		* OptionGroup g;
		* g.addOptions()
		*   ("opt1", value<int>(), "an int option")    // <- no semicolon
		*   ("opt2", value<double>())                  // <- no semicolon
		*   ("opt3", value<char>())                    // <- no semicolon
		* ;                                            // note the semicolon!
		* \endcode
		* \see OptionGroup::addOption
		*/
		OptionGroupInitHelper addOptions();

		std::string getDescription() const
		{
			return options_[0].first;
		}


		//! adds option to this group
		/*!
		* \throw DuplicateOption if an option with the same short or long name already exists
		* in this group
		*/
		void addOption(std::auto_ptr<Option> option);

		//! adds the options of other to this group
		/*!
		* \throw DuplicateOption if an option with the same short or long name already exists
		* in this group
		* \param mergeGroup if true and there is already some group G' such that G'.getDescription() == other.getDescription()
		*                   options of other are added to G'
		*/
		OptionGroup& addOptions(const OptionGroup& other, bool mergeGroup = false);

		//! returns the number of options in this group
		std::size_t size() const;
		//! returns the number of groups in this group
		std::size_t groups() const;

		//! returns size() == 0
		bool empty() const;

		//! returns > 0 if this group contains an option with the given name.
		/*!
		* \note name is treated as the long name of an option.
		* Prepend a '-' character if you want to search using the short name.
		*/
		std::size_t count(const char* name) const;

		//! returns the number of options whose names start with the given prefix
		std::size_t countPrefix(const char* name) const;


		//! returns the option with the given name
		/*!
		* \throw UnknownOption if count(name) == 0
		* \see OptionGroup::count
		*/
		const Option& find(const char* name) const;

		//! returns the option whose name starts with name
		/*!
		* \throw UnknownOption if countPrefix (name) == 0 and AmbiguousOption if countPrefix() > 1
		*/
		const Option& findPrefix(const char* name) const;

		//! returns the long names of the options in this group
		std::set<std::string> primaryKeys() const;

		typedef void (*FormatFunction)(std::ostream&, const Option& option);
		friend std::ostream& operator<<(std::ostream& os,  const OptionGroup& grp);


		void writeToStream(std::ostream&, FormatFunction f) const;
	private:
		typedef std::pair<std::string, std::vector<SharedPtr<Option> > > GroupOptions;
		typedef std::vector<GroupOptions> Options;
		typedef std::pair<size_t, size_t> OptionKey;

		typedef std::map<std::string, OptionKey> Name2OptionIndex;
		typedef std::pair<Name2OptionIndex::const_iterator, Name2OptionIndex::const_iterator> PrefixRange;
		OptionGroup& mergeOptions(std::size_t targetGroupKey, const OptionGroup& other);
		Options options_;
		Name2OptionIndex  name2Index_;
		Options::size_type size_;

		PrefixRange getPrefixRange(const char* name) const;
		void insertOption(const SharedPtr<Option>& o, Options::size_type g = 0);
	};

	class OptionGroupInitHelper
	{
	public:
		explicit OptionGroupInitHelper(OptionGroup* owner);
		OptionGroupInitHelper& operator()(  const std::string& name,
			ValueBase* val,
			const char* description = 0,
			const char* argDesc = 0);
	private:
		OptionGroup* owner_;
	};

	class ParsedOptions;

	//! stores the values of parsed options.
	class OptionValues
	{
	public:
		OptionValues();

		/*!
		* Stores the values of all options that are defined in opts
		* If *this already has a non-defaulted value of an option, that value
		* is not changed, even if opts specify some value.
		* 
		* For options having a default-value but which are not defined in opts
		* the default-value is stored.
		*/
		void store(const ParsedOptions& opts);

		//! returns the number of stored values
		std::size_t size() const;

		//! returns true if size() == 0
		bool empty() const;

		void clear();

		/*!
		* returns > 0 if *this contains a value for the option with the long-name name.
		*/
		std::size_t count(const char* name) const;

		/*!
		* returns the value for the option with the long-name name.
		* \pre count(name) > 0
		* \throw UnknownOption if precondition is not met.
		*/
		const ValueBase& operator[](const char* name) const {
			return const_cast<OptionValues*>(this)->operator[](name);
		}
		ValueBase& operator[](const char* name);
	private:
		typedef std::map<std::string, SharedPtr<ValueBase> > ValueMap;
		ValueMap values_;
	};

	/*!
	* container of key-value-pairs representing options found in
	* command-line/config-file.
	*/
	class ParsedOptions
	{
	public:
		/*!
		* \param grp The OptionGroup for which this object stores raw-values.
		*/
		explicit ParsedOptions(const OptionGroup& grp)
			: grp_(&grp)
		{}

		const OptionGroup* grp_;
		typedef std::pair<std::string, std::string> KeyValue;
		typedef std::vector<KeyValue> Options;
		Options options_;
	};

	//! base class for options parsers
	class OptionParser
	{
	public:
		enum OptionType {short_opt, long_opt, end_opt, no_opt};
		OptionParser(OptionGroup& o, bool allowUnreg);
		virtual ~OptionParser();
		ParsedOptions parse();
	protected:
		OptionType getOptionType(const char* o) const;
		const Option* getOption(const char* name, OptionType t);
		void addOptionValue(const std::string& name, const std::string& value);
	private:
		virtual void doParse() = 0;
		ParsedOptions po_;
		bool allowUnreg_; 
	};

	///////////////////////////////////////////////////////////////////////////////
	// parse functions
	///////////////////////////////////////////////////////////////////////////////
	typedef bool (*PosOption)(const std::string&, std::string&);
	
	/*!
	* parses the command line starting at index 1 and removes
	* all found options from argv.
	* \param argc nr of arguments in argv
	* \param argv the command line arguments
	* \param grp options to search in the command line.
	* \param allowUnregistered Allow arguments that match no option in grp
	* \param positionalOption An optional function that is called for
	         command line tokens that have no option name. The function must either 
					 return true and store tthe name of the option in grp that 
					 should receive the token as value in out 
					 or return false to signal an error.
	* \return A ParsedOptions-Object containing names and values for all options found.
	* 
	* \throw std::runtime_error if command line syntax is incorrect
	* \throw UnknownOption if allowUnregistered is false and an argument is found
	* that does not match any option.
	* \note Use the returned object to populate an OptionValues-Object.
	*/
	ParsedOptions parseCommandLine(int& argc, char** argv, OptionGroup& grp,
		bool allowUnregistered = true,
		PosOption positionalOption = 0);

	/*!
	* parses a config file having the format key = value.
	* \param is the stream representing the config file
	* \param o options to search in the config file
	* \param allowUnregistered Allow arguments that match no option in grp
	* 
	* \return A ParsedOptions-Object containing names and values for all options found.
	*
	* \throw std::runtime_error if config file has incorrect syntax.
	* \throw UnknownOption if allowUnregistered is false and an argument is found
	* \note keys are option's long names.
	* \note lines starting with # are treated as comments and are ignored.
	* \note Use the returned object to populate an OptionValues-Object.
	*/
	ParsedOptions parseCfgFile(std::istream& is, OptionGroup& o, bool allowUnregistered);


}

#endif