File: value.h

package info (click to toggle)
gringo 4.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 8,260 kB
  • ctags: 10,755
  • sloc: cpp: 55,049; python: 629; yacc: 569; sh: 124; makefile: 23
file content (207 lines) | stat: -rw-r--r-- 7,238 bytes parent folder | download | duplicates (2)
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
//
//  Copyright (c) Benjamin Kaufmann 2004
//
//  This 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 2 of the License, or
//  (at your option) any later version. 
// 
//  This file 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
//
// NOTE: ProgramOptions is inspired by Boost.Program_options
//       see: www.boost.org/libs/program_options
//
#ifndef PROGRAM_OPTIONS_VALUE_H_INCLUDED
#define PROGRAM_OPTIONS_VALUE_H_INCLUDED
#ifdef _MSC_VER
#pragma warning (disable : 4786)
#pragma warning (disable : 4503)
#endif
#include <string>
#include <typeinfo>
#include <cstddef>
#if defined(_MSC_VER) && _MSC_VER <= 1200
namespace std { using ::size_t; }
#endif

namespace ProgramOptions {


enum DescriptionLevel {
	desc_level_default = 0, /**< Always shown in description */
	desc_level_e1      = 1,
	desc_level_e2      = 2,
	desc_level_e3      = 3,
	desc_level_all     = 4,
	desc_level_hidden  = 5 /**< Never shown in description */
};

//! Manages the value of an option and defines how it is parsed from a string.
/*!
 * The library maintains a 1:1-relationship between options and their values.
 * That is, an option has exactly one value and a value has exactly one
 * state w.r.t its option. 
 */
class Value {
public:
	//! Possible (tentative) states of an option value.
	enum State { 
		value_unassigned = 0, /**< no value assigned */
		value_defaulted  = 1, /**< a default value is assigned */
		value_fixed      = 2  /**< a parsed value is assigned */
	};
	//! Possible value descriptions.
	enum DescType {
		  desc_name    = 1
		, desc_default = 2
		, desc_implicit= 4
	};
	virtual ~Value();

	//! Returns the current state of this value.
	State state() const { return static_cast<State>(state_); }
	
	/*!
	 * Sets the (initial) state of this value to s.
	 */
	Value* state(Value::State s) {
		state(true, s);
		return this;
	}

	//! Returns the name of this value.
	/*!
	 * \note The default name is "<arg>" unless isFlag() is true in which
	 *       case the default is "".
	 */
	const char* arg()          const;
	Value*      arg(const char* n) { return desc(desc_name, n); }

	//! Sets an alias name for the corresponding option.
	Value* alias(char c) { optAlias_ = c; return this; }
	char   alias() const { return optAlias_; }
	//! Sets a description level for the corresponding option.
	/*!
	 * Description levels can be used to suppress
	 * certain options when generating option descriptions.
	 */
	Value* level(DescriptionLevel lev) {
		unsigned x = (lev * level_shift);
		flags_     = static_cast<byte_t>(x | (flags_&(level_shift-1)));
		return this;
	}
	//! Returns the description level of the corresponding option.
	DescriptionLevel level() const { return DescriptionLevel(flags_ / level_shift); }

	//! Returns true if this is the value of an negatable option.
	/*!
	 * If an option '--option' is negatable, passing '--no-option' 
	 * on the command-line will set the value of '--option' to 'no'.
	 */
	bool isNegatable() const { return hasProperty(property_negatable); }
	Value* negatable()       { setProperty(property_negatable); return this; }

	
	//! Returns true if value can be implicitly created from an empty string.
	/*!
	 * \note the implicit value comes into play if the corresponding 
	 *       option is present but without an adjacent value.
	 *
	 * \note an explicit value for an implicit value is only used if
	 *       it is unambiguously given. E.g. on the command-line one has
	 *       to use '--option=value' or '-ovalue' but *not* '--option value'
	 *       or '-o value'.
	 */
	bool   isImplicit() const { return hasProperty(property_implicit); }
	
	//! Returns true if this is the value of an option flag.
	/*!
	 * Similar to isImplicit but with the difference that
	 * no value is accepted on the command-line.
	 *
	 * Used for options like '--help' or '--version'.
	 */
	bool isFlag() const { return hasProperty(property_flag); }

	/*!
	 * Marks the value as flag. 
	 * \see bool Value::isFlag() const
	 */
	Value* flag() { setProperty(property_flag); return this; }

	
	//! Returns true if the value of this option can be composed from multiple source.
	bool isComposing() const { return hasProperty(property_composing); }
	/*!
	 * Marks the value as composing.
	 * \see Value::isComposing()
	 */
	Value* composing() { setProperty(property_composing); return this; }

	/*!
	 * Sets a default value for this value.
	 */
	Value* defaultsTo(const char* v){ return desc(desc_default, v); }
	//! Returns the default value of this or 0 none exists
	const char* defaultsTo()  const { return desc(desc_default); }	
	/*!
	 * Sets an implicit value, which will be used
	 * if option is given without an adjacent value,
	 * e.g. '--option' instead of '--option value'
	 * \see bool Value::isImplicit() const
	 */
	Value* implicit(const char* str) { return desc(desc_implicit, str); }
	//! Returns the implicit value of this or 0 if isImplicit() == false.
	const char* implicit() const;

	//! Parses the given string and updates the value's state.
	/*!
	 * \param name  The name of the option associated with this value.
	 * \param value The value to parse.
	 * \param st    The state to which the value should transition if parsing is succesful.
	 *   
	 * \return 
	 * - true if the given string contains a valid value
	 * - false otherwise
	 *
	 * \post if true is returned, state() is st
	 */
	bool parse(const std::string& name, const std::string& value, State st = value_fixed);
protected:
	typedef unsigned char byte_t;
	enum Property {
		  property_implicit    = 1 // implicit value?
		, property_flag        = 3 // implicit and type bool?
	  , property_composing   = 4 // multiple values allowed?
		, property_negatable   = 8 // negatable form allowed? 
		, property_location    =16 // fixed storage location?
		, not_a_property       =32
	};
	Value(byte_t flagSet, State initial = value_unassigned);
	void setProperty(Property f)     { flags_ |= byte_t(f); }
	void clearProperty(Property f)   { flags_ &= ~byte_t(f);}
	bool hasProperty(Property f)const{ return (flags_ & byte_t(f)) == f; }
	bool state(bool b, State s) { if (b) { state_ = static_cast<byte_t>(s); } return b; }
	virtual bool doParse(const std::string& name, const std::string& value) = 0;
	const char* desc(DescType t) const;
	Value*      desc(DescType t,  const char* d);
private:
	enum { desc_pack    = 8, level_shift = not_a_property, levels = 255/level_shift };
	byte_t state_;       // state: one of State
	byte_t flags_;       // flag set holding properties
	byte_t descFlag_;    // either desc_pack or one of DescType
	byte_t optAlias_;    // alias name of option
	union ValueDesc {    // optional value descriptions either
		const char*  value;// a single value or
		const char** pack; // a pointer to a full pack
	}      desc_;         
};
}
#endif