206 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			206 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| // Copyright Vladimir Prus 2004.
 | |
| // Distributed under the Boost Software License, Version 1.0.
 | |
| // (See accompanying file LICENSE_1_0.txt
 | |
| // or copy at http://www.boost.org/LICENSE_1_0.txt)
 | |
| 
 | |
| // This file defines template functions that are declared in
 | |
| // ../value_semantic.hpp.
 | |
| 
 | |
| #include <boost/throw_exception.hpp>
 | |
| 
 | |
| namespace boost { namespace program_options { 
 | |
| 
 | |
|     extern BOOST_PROGRAM_OPTIONS_DECL std::string arg;
 | |
|     
 | |
|     template<class T, class charT>
 | |
|     std::string
 | |
|     typed_value<T, charT>::name() const
 | |
|     {
 | |
|         std::string const& var = (m_value_name.empty() ? arg : m_value_name);
 | |
|         if (!m_implicit_value.empty() && !m_implicit_value_as_text.empty()) {
 | |
|             std::string msg = "[=" + var + "(=" + m_implicit_value_as_text + ")]";
 | |
|             if (!m_default_value.empty() && !m_default_value_as_text.empty())
 | |
|                 msg += " (=" + m_default_value_as_text + ")";
 | |
|             return msg;
 | |
|         }
 | |
|         else if (!m_default_value.empty() && !m_default_value_as_text.empty()) {
 | |
|             return var + " (=" + m_default_value_as_text + ")";
 | |
|         } else {
 | |
|             return var;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     template<class T, class charT>
 | |
|     void 
 | |
|     typed_value<T, charT>::notify(const boost::any& value_store) const
 | |
|     {
 | |
|         const T* value = boost::any_cast<T>(&value_store);
 | |
|         if (m_store_to) {
 | |
|             *m_store_to = *value;
 | |
|         }
 | |
|         if (m_notifier) {
 | |
|             m_notifier(*value);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     namespace validators {
 | |
|         /* If v.size() > 1, throw validation_error. 
 | |
|            If v.size() == 1, return v.front()
 | |
|            Otherwise, returns a reference to a statically allocated
 | |
|            empty string if 'allow_empty' and throws validation_error
 | |
|            otherwise. */
 | |
|         template<class charT>
 | |
|         const std::basic_string<charT>& get_single_string(
 | |
|             const std::vector<std::basic_string<charT> >& v, 
 | |
|             bool allow_empty = false)
 | |
|         {
 | |
|             static std::basic_string<charT> empty;
 | |
|             if (v.size() > 1)
 | |
|                 boost::throw_exception(validation_error(validation_error::multiple_values_not_allowed));
 | |
|             else if (v.size() == 1)
 | |
|                 return v.front();
 | |
|             else if (!allow_empty)
 | |
|                 boost::throw_exception(validation_error(validation_error::at_least_one_value_required));
 | |
|             return empty;
 | |
|         }
 | |
| 
 | |
|         /* Throws multiple_occurrences if 'value' is not empty. */
 | |
|         BOOST_PROGRAM_OPTIONS_DECL void 
 | |
|         check_first_occurrence(const boost::any& value);
 | |
|     }
 | |
| 
 | |
|     using namespace validators;
 | |
| 
 | |
|     /** Validates 's' and updates 'v'.
 | |
|         @pre 'v' is either empty or in the state assigned by the previous
 | |
|         invocation of 'validate'.
 | |
|         The target type is specified via a parameter which has the type of 
 | |
|         pointer to the desired type. This is workaround for compilers without
 | |
|         partial template ordering, just like the last 'long/int' parameter.
 | |
|     */
 | |
|     template<class T, class charT>
 | |
|     void validate(boost::any& v, 
 | |
|                   const std::vector< std::basic_string<charT> >& xs, 
 | |
|                   T*, long)
 | |
|     {
 | |
|         validators::check_first_occurrence(v);
 | |
|         std::basic_string<charT> s(validators::get_single_string(xs));
 | |
|         try {
 | |
|             v = any(lexical_cast<T>(s));
 | |
|         }
 | |
|         catch(const bad_lexical_cast&) {
 | |
|             boost::throw_exception(invalid_option_value(s));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, 
 | |
|                        const std::vector<std::string>& xs, 
 | |
|                        bool*,
 | |
|                        int);
 | |
| 
 | |
| #if !defined(BOOST_NO_STD_WSTRING)
 | |
|     BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, 
 | |
|                        const std::vector<std::wstring>& xs, 
 | |
|                        bool*,
 | |
|                        int);
 | |
| #endif
 | |
|     // For some reason, this declaration, which is require by the standard,
 | |
|     // cause msvc 7.1 to not generate code to specialization defined in
 | |
|     // value_semantic.cpp
 | |
| #if ! ( BOOST_WORKAROUND(BOOST_MSVC, == 1310) )
 | |
|     BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, 
 | |
|                        const std::vector<std::string>& xs,
 | |
|                        std::string*,
 | |
|                        int);
 | |
| 
 | |
| #if !defined(BOOST_NO_STD_WSTRING)
 | |
|     BOOST_PROGRAM_OPTIONS_DECL void validate(boost::any& v, 
 | |
|                        const std::vector<std::wstring>& xs,
 | |
|                        std::string*,
 | |
|                        int);
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
|     /** Validates sequences. Allows multiple values per option occurrence
 | |
|        and multiple occurrences. */
 | |
|     template<class T, class charT>
 | |
|     void validate(boost::any& v, 
 | |
|                   const std::vector<std::basic_string<charT> >& s, 
 | |
|                   std::vector<T>*,
 | |
|                   int)
 | |
|     {
 | |
|         if (v.empty()) {
 | |
|             v = boost::any(std::vector<T>());
 | |
|         }
 | |
|         std::vector<T>* tv = boost::any_cast< std::vector<T> >(&v);
 | |
|         assert(NULL != tv);
 | |
|         for (unsigned i = 0; i < s.size(); ++i)
 | |
|         {
 | |
|             try {
 | |
|                 /* We call validate so that if user provided
 | |
|                    a validator for class T, we use it even
 | |
|                    when parsing vector<T>.  */
 | |
|                 boost::any a;
 | |
|                 std::vector<std::basic_string<charT> > cv;
 | |
|                 cv.push_back(s[i]);
 | |
|                 validate(a, cv, (T*)0, 0);                
 | |
|                 tv->push_back(boost::any_cast<T>(a));
 | |
|             }
 | |
|             catch(const bad_lexical_cast& /*e*/) {
 | |
|                 boost::throw_exception(invalid_option_value(s[i]));
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     template<class T, class charT>
 | |
|     void 
 | |
|     typed_value<T, charT>::
 | |
|     xparse(boost::any& value_store, 
 | |
|            const std::vector<std::basic_string<charT> >& new_tokens) const
 | |
|     {
 | |
|         // If no tokens were given, and the option accepts an implicit
 | |
|         // value, then assign the implicit value as the stored value;
 | |
|         // otherwise, validate the user-provided token(s).
 | |
|         if (new_tokens.empty() && !m_implicit_value.empty())
 | |
|             value_store = m_implicit_value;
 | |
|         else
 | |
|             validate(value_store, new_tokens, (T*)0, 0);
 | |
|     }
 | |
| 
 | |
|     template<class T>
 | |
|     typed_value<T>*
 | |
|     value()
 | |
|     {
 | |
|         // Explicit qualification is vc6 workaround.
 | |
|         return boost::program_options::value<T>(0);
 | |
|     }
 | |
| 
 | |
|     template<class T>
 | |
|     typed_value<T>*
 | |
|     value(T* v)
 | |
|     {
 | |
|         typed_value<T>* r = new typed_value<T>(v);
 | |
| 
 | |
|         return r;        
 | |
|     }
 | |
| 
 | |
|     template<class T>
 | |
|     typed_value<T, wchar_t>*
 | |
|     wvalue()
 | |
|     {
 | |
|         return wvalue<T>(0);
 | |
|     }
 | |
| 
 | |
|     template<class T>
 | |
|     typed_value<T, wchar_t>*
 | |
|     wvalue(T* v)
 | |
|     {
 | |
|         typed_value<T, wchar_t>* r = new typed_value<T, wchar_t>(v);
 | |
| 
 | |
|         return r;        
 | |
|     }
 | |
| 
 | |
| 
 | |
| 
 | |
| }}
 | 
