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 #include <string> 17 #include <vector> 18 #include <typeinfo> 19 #include <limits> 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 /** Returns true if value must be given. Non-optional value 48 49 */ 50 virtual bool is_required() const = 0; 51 52 /** Parses a group of tokens that specify a value of option. 53 Stores the result in 'value_store', using whatever representation 54 is desired. May be be called several times if value of the same 55 option is specified more than once. 56 */ 57 virtual void parse(boost::any& value_store, 58 const std::vector<std::string>& new_tokens, 59 bool utf8) const 60 = 0; 61 62 /** Called to assign default value to 'value_store'. Returns 63 true if default value is assigned, and false if no default 64 value exists. */ 65 virtual bool apply_default(boost::any& value_store) const = 0; 66 67 /** Called when final value of an option is determined. 68 */ 69 virtual void notify(const boost::any& value_store) const = 0; 70 ~value_semantic()71 virtual ~value_semantic() {} 72 }; 73 74 /** Helper class which perform necessary character conversions in the 75 'parse' method and forwards the data further. 76 */ 77 template<class charT> 78 class value_semantic_codecvt_helper { 79 // Nothing here. Specializations to follow. 80 }; 81 82 /** Helper conversion class for values that accept ascii 83 strings as input. 84 Overrides the 'parse' method and defines new 'xparse' 85 method taking std::string. Depending on whether input 86 to parse is ascii or UTF8, will pass it to xparse unmodified, 87 or with UTF8->ascii conversion. 88 */ 89 template<> 90 class BOOST_PROGRAM_OPTIONS_DECL 91 value_semantic_codecvt_helper<char> : public value_semantic { 92 private: // base overrides 93 void parse(boost::any& value_store, 94 const std::vector<std::string>& new_tokens, 95 bool utf8) const; 96 protected: // interface for derived classes. 97 virtual void xparse(boost::any& value_store, 98 const std::vector<std::string>& new_tokens) 99 const = 0; 100 }; 101 102 /** Helper conversion class for values that accept ascii 103 strings as input. 104 Overrides the 'parse' method and defines new 'xparse' 105 method taking std::wstring. Depending on whether input 106 to parse is ascii or UTF8, will recode input to Unicode, or 107 pass it unmodified. 108 */ 109 template<> 110 class BOOST_PROGRAM_OPTIONS_DECL 111 value_semantic_codecvt_helper<wchar_t> : public value_semantic { 112 private: // base overrides 113 void parse(boost::any& value_store, 114 const std::vector<std::string>& new_tokens, 115 bool utf8) const; 116 protected: // interface for derived classes. 117 #if !defined(BOOST_NO_STD_WSTRING) 118 virtual void xparse(boost::any& value_store, 119 const std::vector<std::wstring>& new_tokens) 120 const = 0; 121 #endif 122 }; 123 124 /** Class which specifies a simple handling of a value: the value will 125 have string type and only one token is allowed. */ 126 class BOOST_PROGRAM_OPTIONS_DECL 127 untyped_value : public value_semantic_codecvt_helper<char> { 128 public: untyped_value(bool zero_tokens=false)129 untyped_value(bool zero_tokens = false) 130 : m_zero_tokens(zero_tokens) 131 {} 132 133 std::string name() const; 134 135 unsigned min_tokens() const; 136 unsigned max_tokens() const; 137 is_composing() const138 bool is_composing() const { return false; } 139 is_required() const140 bool is_required() const { return false; } 141 142 /** If 'value_store' is already initialized, or new_tokens 143 has more than one elements, throws. Otherwise, assigns 144 the first string from 'new_tokens' to 'value_store', without 145 any modifications. 146 */ 147 void xparse(boost::any& value_store, 148 const std::vector<std::string>& new_tokens) const; 149 150 /** Does nothing. */ apply_default(boost::any &) const151 bool apply_default(boost::any&) const { return false; } 152 153 /** Does nothing. */ notify(const boost::any &) const154 void notify(const boost::any&) const {} 155 private: 156 bool m_zero_tokens; 157 }; 158 159 #ifndef BOOST_NO_RTTI 160 /** Base class for all option that have a fixed type, and are 161 willing to announce this type to the outside world. 162 Any 'value_semantics' for which you want to find out the 163 type can be dynamic_cast-ed to typed_value_base. If conversion 164 succeeds, the 'type' method can be called. 165 */ 166 class typed_value_base 167 { 168 public: 169 // Returns the type of the value described by this 170 // object. 171 virtual const std::type_info& value_type() const = 0; 172 // Not really needed, since deletion from this 173 // class is silly, but just in case. ~typed_value_base()174 virtual ~typed_value_base() {} 175 }; 176 #endif 177 178 179 /** Class which handles value of a specific type. */ 180 template<class T, class charT = char> 181 class typed_value : public value_semantic_codecvt_helper<charT> 182 #ifndef BOOST_NO_RTTI 183 , public typed_value_base 184 #endif 185 { 186 public: 187 /** Ctor. The 'store_to' parameter tells where to store 188 the value when it's known. The parameter can be NULL. */ typed_value(T * store_to)189 typed_value(T* store_to) 190 : m_store_to(store_to), m_composing(false), 191 m_implicit(false), m_multitoken(false), 192 m_zero_tokens(false), m_required(false) 193 {} 194 195 /** Specifies default value, which will be used 196 if none is explicitly specified. The type 'T' should 197 provide operator<< for ostream. 198 */ default_value(const T & v)199 typed_value* default_value(const T& v) 200 { 201 m_default_value = boost::any(v); 202 m_default_value_as_text = boost::lexical_cast<std::string>(v); 203 return this; 204 } 205 206 /** Specifies default value, which will be used 207 if none is explicitly specified. Unlike the above overload, 208 the type 'T' need not provide operator<< for ostream, 209 but textual representation of default value must be provided 210 by the user. 211 */ default_value(const T & v,const std::string & textual)212 typed_value* default_value(const T& v, const std::string& textual) 213 { 214 m_default_value = boost::any(v); 215 m_default_value_as_text = textual; 216 return this; 217 } 218 219 /** Specifies an implicit value, which will be used 220 if the option is given, but without an adjacent value. 221 Using this implies that an explicit value is optional, 222 */ implicit_value(const T & v)223 typed_value* implicit_value(const T &v) 224 { 225 m_implicit_value = boost::any(v); 226 m_implicit_value_as_text = 227 boost::lexical_cast<std::string>(v); 228 return this; 229 } 230 231 /** Specifies the name used to to the value in help message. */ value_name(const std::string & name)232 typed_value* value_name(const std::string& name) 233 { 234 m_value_name = name; 235 return this; 236 } 237 238 /** Specifies an implicit value, which will be used 239 if the option is given, but without an adjacent value. 240 Using this implies that an explicit value is optional, but if 241 given, must be strictly adjacent to the option, i.e.: '-ovalue' 242 or '--option=value'. Giving '-o' or '--option' will cause the 243 implicit value to be applied. 244 Unlike the above overload, the type 'T' need not provide 245 operator<< for ostream, but textual representation of default 246 value must be provided by the user. 247 */ implicit_value(const T & v,const std::string & textual)248 typed_value* implicit_value(const T &v, const std::string& textual) 249 { 250 m_implicit_value = boost::any(v); 251 m_implicit_value_as_text = textual; 252 return this; 253 } 254 255 /** Specifies a function to be called when the final value 256 is determined. */ notifier(function1<void,const T &> f)257 typed_value* notifier(function1<void, const T&> f) 258 { 259 m_notifier = f; 260 return this; 261 } 262 263 /** Specifies that the value is composing. See the 'is_composing' 264 method for explanation. 265 */ composing()266 typed_value* composing() 267 { 268 m_composing = true; 269 return this; 270 } 271 272 /** Specifies that the value can span multiple tokens. 273 */ multitoken()274 typed_value* multitoken() 275 { 276 m_multitoken = true; 277 return this; 278 } 279 280 /** Specifies that no tokens may be provided as the value of 281 this option, which means that only presense of the option 282 is significant. For such option to be useful, either the 283 'validate' function should be specialized, or the 284 'implicit_value' method should be also used. In most 285 cases, you can use the 'bool_switch' function instead of 286 using this method. */ zero_tokens()287 typed_value* zero_tokens() 288 { 289 m_zero_tokens = true; 290 return this; 291 } 292 293 /** Specifies that the value must occur. */ required()294 typed_value* required() 295 { 296 m_required = true; 297 return this; 298 } 299 300 public: // value semantic overrides 301 302 std::string name() const; 303 is_composing() const304 bool is_composing() const { return m_composing; } 305 min_tokens() const306 unsigned min_tokens() const 307 { 308 if (m_zero_tokens || !m_implicit_value.empty()) { 309 return 0; 310 } else { 311 return 1; 312 } 313 } 314 max_tokens() const315 unsigned max_tokens() const { 316 if (m_multitoken) { 317 return std::numeric_limits<unsigned>::max BOOST_PREVENT_MACRO_SUBSTITUTION(); 318 } else if (m_zero_tokens) { 319 return 0; 320 } else { 321 return 1; 322 } 323 } 324 is_required() const325 bool is_required() const { return m_required; } 326 327 /** Creates an instance of the 'validator' class and calls 328 its operator() to perform the actual conversion. */ 329 void xparse(boost::any& value_store, 330 const std::vector< std::basic_string<charT> >& new_tokens) 331 const; 332 333 /** If default value was specified via previous call to 334 'default_value', stores that value into 'value_store'. 335 Returns true if default value was stored. 336 */ apply_default(boost::any & value_store) const337 virtual bool apply_default(boost::any& value_store) const 338 { 339 if (m_default_value.empty()) { 340 return false; 341 } else { 342 value_store = m_default_value; 343 return true; 344 } 345 } 346 347 /** If an address of variable to store value was specified 348 when creating *this, stores the value there. Otherwise, 349 does nothing. */ 350 void notify(const boost::any& value_store) const; 351 352 public: // typed_value_base overrides 353 354 #ifndef BOOST_NO_RTTI value_type() const355 const std::type_info& value_type() const 356 { 357 return typeid(T); 358 } 359 #endif 360 361 362 private: 363 T* m_store_to; 364 365 // Default value is stored as boost::any and not 366 // as boost::optional to avoid unnecessary instantiations. 367 std::string m_value_name; 368 boost::any m_default_value; 369 std::string m_default_value_as_text; 370 boost::any m_implicit_value; 371 std::string m_implicit_value_as_text; 372 bool m_composing, m_implicit, m_multitoken, m_zero_tokens, m_required; 373 boost::function1<void, const T&> m_notifier; 374 }; 375 376 377 /** Creates a typed_value<T> instance. This function is the primary 378 method to create value_semantic instance for a specific type, which 379 can later be passed to 'option_description' constructor. 380 The second overload is used when it's additionally desired to store the 381 value of option into program variable. 382 */ 383 template<class T> 384 typed_value<T>* 385 value(); 386 387 /** @overload 388 */ 389 template<class T> 390 typed_value<T>* 391 value(T* v); 392 393 /** Creates a typed_value<T> instance. This function is the primary 394 method to create value_semantic instance for a specific type, which 395 can later be passed to 'option_description' constructor. 396 */ 397 template<class T> 398 typed_value<T, wchar_t>* 399 wvalue(); 400 401 /** @overload 402 */ 403 template<class T> 404 typed_value<T, wchar_t>* 405 wvalue(T* v); 406 407 /** Works the same way as the 'value<bool>' function, but the created 408 value_semantic won't accept any explicit value. So, if the option 409 is present on the command line, the value will be 'true'. 410 */ 411 BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* 412 bool_switch(); 413 414 /** @overload 415 */ 416 BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* 417 bool_switch(bool* v); 418 419 }} 420 421 #include "boost/program_options/detail/value_semantic.hpp" 422 423 #endif 424 425