1 // Copyright Vladimir Prus 2004. 2 // Distributed under the Boost Software License, Version 1.0. 3 // (See accompanying file LICENSE_1_0.txt 4 // or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #ifndef BOOST_VALUE_SEMANTIC_HPP_VP_2004_02_24 7 #define BOOST_VALUE_SEMANTIC_HPP_VP_2004_02_24 8 9 #include <boost/program_options/config.hpp> 10 #include <boost/program_options/errors.hpp> 11 12 #include <boost/any.hpp> 13 #include <boost/function/function1.hpp> 14 #include <boost/lexical_cast.hpp> 15 16 17 18 #include <string> 19 #include <vector> 20 21 namespace boost { namespace program_options { 22 23 /** Class which specifies how the option's value is to be parsed 24 and converted into C++ types. 25 */ 26 class BOOST_PROGRAM_OPTIONS_DECL value_semantic { 27 public: 28 /** Returns the name of the option. The name is only meaningful 29 for automatic help message. 30 */ 31 virtual std::string name() const = 0; 32 33 /** The minimum number of tokens for this option that 34 should be present on the command line. */ 35 virtual unsigned min_tokens() const = 0; 36 37 /** The maximum number of tokens for this option that 38 should be present on the command line. */ 39 virtual unsigned max_tokens() const = 0; 40 41 /** Returns true if values from different sources should be composed. 42 Otherwise, value from the first source is used and values from 43 other sources are discarded. 44 */ 45 virtual bool is_composing() const = 0; 46 47 /** Parses a group of tokens that specify a value of option. 48 Stores the result in 'value_store', using whatever representation 49 is desired. May be be called several times if value of the same 50 option is specified more than once. 51 */ 52 virtual void parse(boost::any& value_store, 53 const std::vector<std::string>& new_tokens, 54 bool utf8) const 55 = 0; 56 57 /** Called to assign default value to 'value_store'. Returns 58 true if default value is assigned, and false if no default 59 value exists. */ 60 virtual bool apply_default(boost::any& value_store) const = 0; 61 62 /** Called when final value of an option is determined. 63 */ 64 virtual void notify(const boost::any& value_store) const = 0; 65 ~value_semantic()66 virtual ~value_semantic() {} 67 }; 68 69 /** Helper class which perform necessary character conversions in the 70 'parse' method and forwards the data further. 71 */ 72 template<class charT> 73 class value_semantic_codecvt_helper { 74 // Nothing here. Specializations to follow. 75 }; 76 77 template<> 78 class BOOST_PROGRAM_OPTIONS_DECL 79 value_semantic_codecvt_helper<char> : public value_semantic { 80 private: // base overrides 81 void parse(boost::any& value_store, 82 const std::vector<std::string>& new_tokens, 83 bool utf8) const; 84 protected: // interface for derived classes. 85 virtual void xparse(boost::any& value_store, 86 const std::vector<std::string>& new_tokens) 87 const = 0; 88 }; 89 90 template<> 91 class BOOST_PROGRAM_OPTIONS_DECL 92 value_semantic_codecvt_helper<wchar_t> : public value_semantic { 93 private: // base overrides 94 void parse(boost::any& value_store, 95 const std::vector<std::string>& new_tokens, 96 bool utf8) const; 97 protected: // interface for derived classes. 98 #if !defined(BOOST_NO_STD_WSTRING) 99 virtual void xparse(boost::any& value_store, 100 const std::vector<std::wstring>& new_tokens) 101 const = 0; 102 #endif 103 }; 104 /** Class which specifies a simple handling of a value: the value will 105 have string type and only one token is allowed. */ 106 class BOOST_PROGRAM_OPTIONS_DECL 107 untyped_value : public value_semantic_codecvt_helper<char> { 108 public: untyped_value(bool zero_tokens=false)109 untyped_value(bool zero_tokens = false) 110 : m_zero_tokens(zero_tokens) 111 {} 112 113 std::string name() const; 114 115 unsigned min_tokens() const; 116 unsigned max_tokens() const; 117 is_composing() const118 bool is_composing() const { return false; } 119 120 /** If 'value_store' is already initialized, or new_tokens 121 has more than one elements, throws. Otherwise, assigns 122 the first string from 'new_tokens' to 'value_store', without 123 any modifications. 124 */ 125 void xparse(boost::any& value_store, 126 const std::vector<std::string>& new_tokens) const; 127 128 /** Does nothing. */ apply_default(boost::any &) const129 bool apply_default(boost::any&) const { return false; } 130 131 /** Does nothing. */ notify(const boost::any &) const132 void notify(const boost::any&) const {} 133 private: 134 bool m_zero_tokens; 135 }; 136 137 /** Class which handles value of a specific type. */ 138 template<class T, class charT = char> 139 class typed_value : public value_semantic_codecvt_helper<charT> { 140 public: 141 /** Ctor. The 'store_to' parameter tells where to store 142 the value when it's known. The parameter can be NULL. */ typed_value(T * store_to)143 typed_value(T* store_to) 144 : m_store_to(store_to), m_composing(false), 145 m_multitoken(false), m_zero_tokens(false) 146 {} 147 148 /** Specifies default value, which will be used 149 if none is explicitly specified. The type 'T' should 150 provide operator<< for ostream. 151 */ default_value(const T & v)152 typed_value* default_value(const T& v) 153 { 154 m_default_value = boost::any(v); 155 m_default_value_as_text = boost::lexical_cast<std::string>(v); 156 return this; 157 } 158 159 /** Specifies default value, which will be used 160 if none is explicitly specified. Unlike the above overload, 161 the type 'T' need not provide operator<< for ostream, 162 but textual representation of default value must be provided 163 by the user. 164 */ default_value(const T & v,const std::string & textual)165 typed_value* default_value(const T& v, const std::string& textual) 166 { 167 m_default_value = boost::any(v); 168 m_default_value_as_text = textual; 169 return this; 170 } 171 172 /** Specifies a function to be called when the final value 173 is determined. */ notifier(function1<void,const T &> f)174 typed_value* notifier(function1<void, const T&> f) 175 { 176 m_notifier = f; 177 return this; 178 } 179 180 /** Specifies that the value is composing. See the 'is_composing' 181 method for explanation. 182 */ composing()183 typed_value* composing() 184 { 185 m_composing = true; 186 return this; 187 } 188 189 /** Specifies that the value can span multiple tokens. */ multitoken()190 typed_value* multitoken() 191 { 192 m_multitoken = true; 193 return this; 194 } 195 zero_tokens()196 typed_value* zero_tokens() 197 { 198 m_zero_tokens = true; 199 return this; 200 } 201 202 203 public: // value semantic overrides 204 205 std::string name() const; 206 is_composing() const207 bool is_composing() const { return m_composing; } 208 min_tokens() const209 unsigned min_tokens() const 210 { 211 if (m_zero_tokens) { 212 return 0; 213 } else { 214 return 1; 215 } 216 } 217 max_tokens() const218 unsigned max_tokens() const { 219 if (m_multitoken) { 220 return 32000; 221 } else if (m_zero_tokens) { 222 return 0; 223 } else { 224 return 1; 225 } 226 } 227 228 229 /** Creates an instance of the 'validator' class and calls 230 its operator() to perform athe ctual conversion. */ 231 void xparse(boost::any& value_store, 232 const std::vector< std::basic_string<charT> >& new_tokens) 233 const; 234 235 /** If default value was specified via previous call to 236 'default_value', stores that value into 'value_store'. 237 Returns true if default value was stored. 238 */ apply_default(boost::any & value_store) const239 virtual bool apply_default(boost::any& value_store) const 240 { 241 if (m_default_value.empty()) { 242 return false; 243 } else { 244 value_store = m_default_value; 245 return true; 246 } 247 } 248 249 /** If an address of variable to store value was specified 250 when creating *this, stores the value there. Otherwise, 251 does nothing. */ 252 void notify(const boost::any& value_store) const; 253 254 255 private: 256 T* m_store_to; 257 258 // Default value is stored as boost::any and not 259 // as boost::optional to avoid unnecessary instantiations. 260 boost::any m_default_value; 261 std::string m_default_value_as_text; 262 bool m_composing, m_implicit, m_multitoken, m_zero_tokens; 263 boost::function1<void, const T&> m_notifier; 264 }; 265 266 267 /** Creates a typed_value<T> instance. This function is the primary 268 method to create value_semantic instance for a specific type, which 269 can later be passed to 'option_description' constructor. 270 The second overload is used when it's additionally desired to store the 271 value of option into program variable. 272 */ 273 template<class T> 274 typed_value<T>* 275 value(); 276 277 /** @overload 278 */ 279 template<class T> 280 typed_value<T>* 281 value(T* v); 282 283 /** Creates a typed_value<T> instance. This function is the primary 284 method to create value_semantic instance for a specific type, which 285 can later be passed to 'option_description' constructor. 286 */ 287 template<class T> 288 typed_value<T, wchar_t>* 289 wvalue(); 290 291 /** @overload 292 */ 293 template<class T> 294 typed_value<T, wchar_t>* 295 wvalue(T* v); 296 297 /** Works the same way as the 'value<bool>' function, but the created 298 value_semantic won't accept any explicit value. So, if the option 299 is present on the command line, the value will be 'true'. 300 */ 301 BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* 302 bool_switch(); 303 304 /** @overload 305 */ 306 BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* 307 bool_switch(bool* v); 308 309 }} 310 311 #include "boost/program_options/detail/value_semantic.hpp" 312 313 #endif 314 315