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
|