1 // 2 // Copyright (c) 2004-2017 Benjamin Kaufmann 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to 6 // deal in the Software without restriction, including without limitation the 7 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 // sell copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 // IN THE SOFTWARE. 21 // 22 // 23 // NOTE: ProgramOptions is inspired by Boost.Program_options 24 // see: www.boost.org/libs/program_options 25 // 26 #ifndef PROGRAM_OPTIONS_VALUE_H_INCLUDED 27 #define PROGRAM_OPTIONS_VALUE_H_INCLUDED 28 #ifdef _MSC_VER 29 #pragma warning (disable : 4786) 30 #pragma warning (disable : 4503) 31 #endif 32 #include <string> 33 #include <typeinfo> 34 #include <cstddef> 35 #if defined(_MSC_VER) && _MSC_VER <= 1200 36 namespace std { using ::size_t; } 37 #endif 38 39 namespace Potassco { namespace ProgramOptions { namespace detail { 40 template <class T> 41 struct Owned { ~OwnedOwned42 ~Owned() { delete obj; } 43 T* obj; 44 }; 45 } // namespace detail 46 enum DescriptionLevel { 47 desc_level_default = 0, /**< Always shown in description */ 48 desc_level_e1 = 1, 49 desc_level_e2 = 2, 50 desc_level_e3 = 3, 51 desc_level_all = 4, 52 desc_level_hidden = 5 /**< Never shown in description */ 53 }; 54 55 //! Manages the value of an option and defines how it is parsed from a string. 56 /*! 57 * The library maintains a 1:1-relationship between options and their values. 58 * That is, an option has exactly one value and a value has exactly one 59 * state w.r.t its option. 60 */ 61 class Value { 62 public: 63 //! Possible (tentative) states of an option value. 64 enum State { 65 value_unassigned = 0, /**< no value assigned */ 66 value_defaulted = 1, /**< a default value is assigned */ 67 value_fixed = 2 /**< a parsed value is assigned */ 68 }; 69 //! Possible value descriptions. 70 enum DescType { 71 desc_name = 1 72 , desc_default = 2 73 , desc_implicit = 4 74 }; 75 virtual ~Value(); 76 77 //! Returns the current state of this value. state()78 State state() const { return static_cast<State>(state_); } 79 80 /*! 81 * Sets the (initial) state of this value to s. 82 */ state(Value::State s)83 Value* state(Value::State s) { 84 state(true, s); 85 return this; 86 } 87 88 //! Returns the name of this value. 89 /*! 90 * \note The default name is "<arg>" unless isFlag() is true in which 91 * case the default is "". 92 */ 93 const char* arg() const; arg(const char * n)94 Value* arg(const char* n) { return desc(desc_name, n); } 95 96 //! Sets an alias name for the corresponding option. alias(char c)97 Value* alias(char c) { optAlias_ = c; return this; } alias()98 char alias() const { return optAlias_; } 99 //! Sets a description level for the corresponding option. 100 /*! 101 * Description levels can be used to suppress 102 * certain options when generating option descriptions. 103 */ level(DescriptionLevel lev)104 Value* level(DescriptionLevel lev) { 105 unsigned x = (lev * level_shift); 106 flags_ = static_cast<byte_t>(x | (flags_&(level_shift-1))); 107 return this; 108 } 109 //! Returns the description level of the corresponding option. level()110 DescriptionLevel level() const { return DescriptionLevel(flags_ / level_shift); } 111 112 //! Returns true if this is the value of an negatable option. 113 /*! 114 * If an option '--option' is negatable, passing '--no-option' 115 * on the command-line will set the value of '--option' to 'no'. 116 */ isNegatable()117 bool isNegatable() const { return hasProperty(property_negatable); } negatable()118 Value* negatable() { setProperty(property_negatable); return this; } 119 120 121 //! Returns true if value can be implicitly created from an empty string. 122 /*! 123 * \note the implicit value comes into play if the corresponding 124 * option is present but without an adjacent value. 125 * 126 * \note an explicit value for an implicit value is only used if 127 * it is unambiguously given. E.g. on the command-line one has 128 * to use '--option=value' or '-ovalue' but *not* '--option value' 129 * or '-o value'. 130 */ isImplicit()131 bool isImplicit() const { return hasProperty(property_implicit); } 132 133 //! Returns true if this is the value of an option flag. 134 /*! 135 * Similar to isImplicit but with the difference that 136 * no value is accepted on the command-line. 137 * 138 * Used for options like '--help' or '--version'. 139 */ isFlag()140 bool isFlag() const { return hasProperty(property_flag); } 141 142 /*! 143 * Marks the value as flag. 144 * \see bool Value::isFlag() const 145 */ flag()146 Value* flag() { setProperty(property_flag); return this; } 147 148 149 //! Returns true if the value of this option can be composed from multiple source. isComposing()150 bool isComposing() const { return hasProperty(property_composing); } 151 /*! 152 * Marks the value as composing. 153 * \see Value::isComposing() 154 */ composing()155 Value* composing() { setProperty(property_composing); return this; } 156 157 /*! 158 * Sets a default value for this value. 159 */ defaultsTo(const char * v)160 Value* defaultsTo(const char* v) { return desc(desc_default, v); } 161 //! Returns the default value of this or 0 none exists defaultsTo()162 const char* defaultsTo() const { return desc(desc_default); } 163 /*! 164 * Sets an implicit value, which will be used 165 * if option is given without an adjacent value, 166 * e.g. '--option' instead of '--option value' 167 * \see bool Value::isImplicit() const 168 */ implicit(const char * str)169 Value* implicit(const char* str) { return desc(desc_implicit, str); } 170 //! Returns the implicit value of this or 0 if isImplicit() == false. 171 const char* implicit() const; 172 173 //! Parses the given string and updates the value's state. 174 /*! 175 * \param name The name of the option associated with this value. 176 * \param value The value to parse. 177 * \param st The state to which the value should transition if parsing is successful. 178 * 179 * \return 180 * - true if the given string contains a valid value 181 * - false otherwise 182 * 183 * \post if true is returned, state() is st 184 */ 185 bool parse(const std::string& name, const std::string& value, State st = value_fixed); 186 protected: 187 typedef unsigned char byte_t; 188 enum Property { 189 property_implicit = 1 // implicit value? 190 , property_flag = 3 // implicit and type bool? 191 , property_composing = 4 // multiple values allowed? 192 , property_negatable = 8 // negatable form allowed? 193 , property_location = 16 // fixed storage location? 194 , not_a_property = 32 195 }; 196 Value(byte_t flagSet, State initial = value_unassigned); setProperty(Property f)197 void setProperty(Property f) { flags_ |= byte_t(f); } clearProperty(Property f)198 void clearProperty(Property f) { flags_ &= ~byte_t(f); } hasProperty(Property f)199 bool hasProperty(Property f)const { return (flags_ & byte_t(f)) == f; } state(bool b,State s)200 bool state(bool b, State s) { if (b) { state_ = static_cast<byte_t>(s); } return b; } 201 virtual bool doParse(const std::string& name, const std::string& value) = 0; 202 const char* desc(DescType t) const; 203 Value* desc(DescType t, const char* d); 204 private: 205 enum { desc_pack = 8, level_shift = not_a_property, levels = 255/level_shift }; 206 byte_t state_; // state: one of State 207 byte_t flags_; // flag set holding properties 208 byte_t descFlag_; // either desc_pack or one of DescType 209 byte_t optAlias_; // alias name of option 210 union ValueDesc { // optional value descriptions either 211 const char* value;// a single value or 212 const char** pack; // a pointer to a full pack 213 } desc_; 214 }; 215 } // namespace ProgramOptions 216 } // namespace Potassco 217 #endif 218