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 // This file defines template functions that are declared in 7 // ../value_semantic.hpp. 8 9 #include <boost/throw_exception.hpp> 10 11 // forward declaration 12 namespace boost { template<class T> class optional; } 13 14 namespace boost { namespace program_options { 15 16 extern BOOST_PROGRAM_OPTIONS_DECL std::string arg; 17 18 template<class T, class charT> 19 std::string 20 typed_value<T, charT>::name() const 21 { 22 std::string const& var = (m_value_name.empty() ? arg : m_value_name); 23 if (!m_implicit_value.empty() && !m_implicit_value_as_text.empty()) { 24 std::string msg = "[=" + var + "(=" + m_implicit_value_as_text + ")]"; 25 if (!m_default_value.empty() && !m_default_value_as_text.empty()) 26 msg += " (=" + m_default_value_as_text + ")"; dsa_decrypt_key(const unsigned char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen,dsa_key * key)27 return msg; 28 } 29 else if (!m_default_value.empty() && !m_default_value_as_text.empty()) { 30 return var + " (=" + m_default_value_as_text + ")"; 31 } else { 32 return var; 33 } 34 } 35 36 template<class T, class charT> 37 void 38 typed_value<T, charT>::notify(const boost::any& value_store) const 39 { 40 const T* value = boost::any_cast<T>(&value_store); 41 if (m_store_to) { 42 *m_store_to = *value; 43 } 44 if (m_notifier) { 45 m_notifier(*value); 46 } 47 } 48 49 namespace validators { 50 /* If v.size() > 1, throw validation_error. 51 If v.size() == 1, return v.front() 52 Otherwise, returns a reference to a statically allocated 53 empty string if 'allow_empty' and throws validation_error 54 otherwise. */ 55 template<class charT> 56 const std::basic_string<charT>& get_single_string( 57 const std::vector<std::basic_string<charT> >& v, 58 bool allow_empty = false) 59 { 60 static std::basic_string<charT> empty; 61 if (v.size() > 1) 62 boost::throw_exception(validation_error(validation_error::multiple_values_not_allowed)); 63 else if (v.size() == 1) 64 return v.front(); 65 else if (!allow_empty) 66 boost::throw_exception(validation_error(validation_error::at_least_one_value_required)); 67 return empty; 68 } 69 70 /* Throws multiple_occurrences if 'value' is not empty. */ 71 BOOST_PROGRAM_OPTIONS_DECL void 72 check_first_occurrence(const boost::any& value); 73 } 74 75 using namespace validators; 76 77 /** Validates 's' and updates 'v'. 78 @pre 'v' is either empty or in the state assigned by the previous 79 invocation of 'validate'. 80 The target type is specified via a parameter which has the type of 81 pointer to the desired type. This is workaround for compilers without 82 partial template ordering, just like the last 'long/int' parameter. 83 */ 84 template<class T, class charT> 85 void validate(boost::any& v, 86 const std::vector< std::basic_string<charT> >& xs, 87 T*, long) 88 { 89 validators::check_first_occurrence(v); 90 std::basic_string<charT> s(validators::get_single_string(xs)); 91 try { 92 v = any(lexical_cast<T>(s)); 93 } 94 catch(const bad_lexical_cast&) { 95 boost::throw_exception(invalid_option_value(s)); 96 } 97 } 98 99 BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, 100 const std::vector<std::string>& xs, 101 bool*, 102 int); 103 104 #if !defined(BOOST_NO_STD_WSTRING) 105 BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, 106 const std::vector<std::wstring>& xs, 107 bool*, 108 int); 109 #endif 110 // For some reason, this declaration, which is require by the standard, 111 // cause msvc 7.1 to not generate code to specialization defined in 112 // value_semantic.cpp 113 #if ! ( BOOST_WORKAROUND(BOOST_MSVC, == 1310) ) 114 BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, 115 const std::vector<std::string>& xs, 116 std::string*, 117 int); 118 119 #if !defined(BOOST_NO_STD_WSTRING) 120 BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, 121 const std::vector<std::wstring>& xs, 122 std::string*, 123 int); 124 #endif 125 #endif 126 127 /** Validates sequences. Allows multiple values per option occurrence 128 and multiple occurrences. */ 129 template<class T, class charT> 130 void validate(boost::any& v, 131 const std::vector<std::basic_string<charT> >& s, 132 std::vector<T>*, 133 int) 134 { 135 if (v.empty()) { 136 v = boost::any(std::vector<T>()); 137 } 138 std::vector<T>* tv = boost::any_cast< std::vector<T> >(&v); 139 assert(NULL != tv); 140 for (unsigned i = 0; i < s.size(); ++i) 141 { 142 try { 143 /* We call validate so that if user provided 144 a validator for class T, we use it even 145 when parsing vector<T>. */ 146 boost::any a; 147 std::vector<std::basic_string<charT> > cv; 148 cv.push_back(s[i]); 149 validate(a, cv, (T*)0, 0); 150 tv->push_back(boost::any_cast<T>(a)); 151 } 152 catch(const bad_lexical_cast& /*e*/) { 153 boost::throw_exception(invalid_option_value(s[i])); 154 } 155 } 156 } 157 158 /** Validates optional arguments. */ 159 template<class T, class charT> 160 void validate(boost::any& v, 161 const std::vector<std::basic_string<charT> >& s, 162 boost::optional<T>*, 163 int) 164 { 165 validators::check_first_occurrence(v); 166 validators::get_single_string(s); 167 boost::any a; 168 validate(a, s, (T*)0, 0); 169 v = boost::any(boost::optional<T>(boost::any_cast<T>(a))); 170 } 171 172 template<class T, class charT> 173 void 174 typed_value<T, charT>:: 175 xparse(boost::any& value_store, 176 const std::vector<std::basic_string<charT> >& new_tokens) const 177 { 178 // If no tokens were given, and the option accepts an implicit 179 // value, then assign the implicit value as the stored value; 180 // otherwise, validate the user-provided token(s). 181 if (new_tokens.empty() && !m_implicit_value.empty()) 182 value_store = m_implicit_value; 183 else 184 validate(value_store, new_tokens, (T*)0, 0); 185 } 186 187 template<class T> 188 typed_value<T>* 189 value() 190 { 191 // Explicit qualification is vc6 workaround. 192 return boost::program_options::value<T>(0); 193 } 194 195 template<class T> 196 typed_value<T>* 197 value(T* v) 198 { 199 typed_value<T>* r = new typed_value<T>(v); 200 201 return r; 202 } 203 204 template<class T> 205 typed_value<T, wchar_t>* 206 wvalue() 207 { 208 return wvalue<T>(0); 209 } 210 211 template<class T> 212 typed_value<T, wchar_t>* 213 wvalue(T* v) 214 { 215 typed_value<T, wchar_t>* r = new typed_value<T, wchar_t>(v); 216 217 return r; 218 } 219 220 221 222 }} 223