diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
commit | 1a78a62555be32868418fe52f8e330c9d0f95d5a (patch) | |
tree | d3765a80e7d3b9640ec2e930743630cd6b9fce2b /boost/test/utils | |
download | boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2 boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip |
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'boost/test/utils')
74 files changed, 9533 insertions, 0 deletions
diff --git a/boost/test/utils/algorithm.hpp b/boost/test/utils/algorithm.hpp new file mode 100644 index 0000000000..d5c6d12c16 --- /dev/null +++ b/boost/test/utils/algorithm.hpp @@ -0,0 +1,228 @@ +// (C) Copyright Gennadiy Rozental 2004-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : addition to STL algorithms +// *************************************************************************** + +#ifndef BOOST_ALGORITHM_HPP_062304GER +#define BOOST_ALGORITHM_HPP_062304GER + +#include <utility> +#include <algorithm> // std::find +#include <functional> // std::bind1st + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +/// @brief this algorithm search through two collections for first mismatch position that get returned as a pair +/// of iterators, first pointing to the mismatch position in first collection, second iterator in second one + +/// @param first1 - first collection begin iterator +/// @param last1 - first collection end iterator +/// @param first2 - second collection begin iterator +/// @param last2 - second collection end iterator +template <class InputIter1, class InputIter2> +inline std::pair<InputIter1, InputIter2> +mismatch( InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2 ) +{ + while( first1 != last1 && first2 != last2 && *first1 == *first2 ) { + ++first1; + ++first2; + } + + return std::pair<InputIter1, InputIter2>(first1, first2); +} + +//____________________________________________________________________________// + +/// @brief this algorithm search through two collections for first mismatch position that get returned as a pair +/// of iterators, first pointing to the mismatch position in first collection, second iterator in second one. This algorithms +/// uses supplied predicate for collection elements comparison + +/// @param first1 - first collection begin iterator +/// @param last1 - first collection end iterator +/// @param first2 - second collection begin iterator +/// @param last2 - second collection end iterator +/// @param pred - predicate to be used for search +template <class InputIter1, class InputIter2, class Predicate> +inline std::pair<InputIter1, InputIter2> +mismatch( InputIter1 first1, InputIter1 last1, + InputIter2 first2, InputIter2 last2, + Predicate pred ) +{ + while( first1 != last1 && first2 != last2 && pred( *first1, *first2 ) ) { + ++first1; + ++first2; + } + + return std::pair<InputIter1, InputIter2>(first1, first2); +} + +//____________________________________________________________________________// + +/// @brief this algorithm search through first collection for first element that does not belong a second one + +/// @param first1 - first collection begin iterator +/// @param last1 - first collection end iterator +/// @param first2 - second collection begin iterator +/// @param last2 - second collection end iterator +template<class ForwardIterator1, class ForwardIterator2> +inline ForwardIterator1 +find_first_not_of( ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2 ) +{ + while( first1 != last1 ) { + if( std::find( first2, last2, *first1 ) == last2 ) + break; + ++first1; + } + + return first1; +} + +//____________________________________________________________________________// + +/// @brief this algorithm search through first collection for first element that does not satisfy binary +/// predicate in conjunction will any element in second collection + +/// @param first1 - first collection begin iterator +/// @param last1 - first collection end iterator +/// @param first2 - second collection begin iterator +/// @param last2 - second collection end iterator +/// @param pred - predicate to be used for search +template<class ForwardIterator1, class ForwardIterator2, class Predicate> +inline ForwardIterator1 +find_first_not_of( ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + Predicate pred ) +{ + while( first1 != last1 ) { + if( std::find_if( first2, last2, std::bind1st( pred, *first1 ) ) == last2 ) + break; + ++first1; + } + + return first1; +} + +//____________________________________________________________________________// + +/// @brief this algorithm search through first collection for last element that belongs to a second one + +/// @param first1 - first collection begin iterator +/// @param last1 - first collection end iterator +/// @param first2 - second collection begin iterator +/// @param last2 - second collection end iterator +template<class BidirectionalIterator1, class ForwardIterator2> +inline BidirectionalIterator1 +find_last_of( BidirectionalIterator1 first1, BidirectionalIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2 ) +{ + if( first1 == last1 || first2 == last2 ) + return last1; + + BidirectionalIterator1 it1 = last1; + while( --it1 != first1 && std::find( first2, last2, *it1 ) == last2 ) {} + + return it1 == first1 && std::find( first2, last2, *it1 ) == last2 ? last1 : it1; +} + +//____________________________________________________________________________// + +/// @brief this algorithm search through first collection for last element that satisfy binary +/// predicate in conjunction will at least one element in second collection + +/// @param first1 - first collection begin iterator +/// @param last1 - first collection end iterator +/// @param first2 - second collection begin iterator +/// @param last2 - second collection end iterator +/// @param pred - predicate to be used for search +template<class BidirectionalIterator1, class ForwardIterator2, class Predicate> +inline BidirectionalIterator1 +find_last_of( BidirectionalIterator1 first1, BidirectionalIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + Predicate pred ) +{ + if( first1 == last1 || first2 == last2 ) + return last1; + + BidirectionalIterator1 it1 = last1; + while( --it1 != first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) == last2 ) {} + + return it1 == first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) == last2 ? last1 : it1; +} + +//____________________________________________________________________________// + +/// @brief this algorithm search through first collection for last element that does not belong to a second one + +/// @param first1 - first collection begin iterator +/// @param last1 - first collection end iterator +/// @param first2 - second collection begin iterator +/// @param last2 - second collection end iterator +template<class BidirectionalIterator1, class ForwardIterator2> +inline BidirectionalIterator1 +find_last_not_of( BidirectionalIterator1 first1, BidirectionalIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2 ) +{ + if( first1 == last1 || first2 == last2 ) + return last1; + + BidirectionalIterator1 it1 = last1; + while( --it1 != first1 && std::find( first2, last2, *it1 ) != last2 ) {} + + return it1 == first1 && std::find( first2, last2, *it1 ) != last2 ? last1 : it1; +} + +//____________________________________________________________________________// + +/// @brief this algorithm search through first collection for last element that does not satisfy binary +/// predicate in conjunction will any element in second collection + +/// @param first1 - first collection begin iterator +/// @param last1 - first collection end iterator +/// @param first2 - second collection begin iterator +/// @param last2 - second collection end iterator +/// @param pred - predicate to be used for search +template<class BidirectionalIterator1, class ForwardIterator2, class Predicate> +inline BidirectionalIterator1 +find_last_not_of( BidirectionalIterator1 first1, BidirectionalIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + Predicate pred ) +{ + if( first1 == last1 || first2 == last2 ) + return last1; + + BidirectionalIterator1 it1 = last1; + while( --it1 != first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) != last2 ) {} + + return it1 == first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) == last2 ? last1 : it1; +} + +//____________________________________________________________________________// + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_ALGORITHM_HPP_062304GER + + diff --git a/boost/test/utils/assign_op.hpp b/boost/test/utils/assign_op.hpp new file mode 100644 index 0000000000..1ddcf7d172 --- /dev/null +++ b/boost/test/utils/assign_op.hpp @@ -0,0 +1,41 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : overloadable assignment +// *************************************************************************** + +#ifndef BOOST_TEST_ASSIGN_OP_033005GER +#define BOOST_TEST_ASSIGN_OP_033005GER + +namespace boost { + +namespace unit_test { + +// ************************************************************************** // +// ************** generic assign operator ************** // +// ************************************************************************** // + +// generic +template<typename T,typename S> +inline void +assign_op( T& t, S const& s, long ) +{ + t = s; +} + +//____________________________________________________________________________// + +} // namespace unit_test + +} // namespace boost + +#endif // BOOST_TEST_ASSIGN_OP_033005GER + diff --git a/boost/test/utils/basic_cstring/basic_cstring.hpp b/boost/test/utils/basic_cstring/basic_cstring.hpp new file mode 100644 index 0000000000..5589e61680 --- /dev/null +++ b/boost/test/utils/basic_cstring/basic_cstring.hpp @@ -0,0 +1,731 @@ +// (C) Copyright Gennadiy Rozental 2004-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 57992 $ +// +// Description : class basic_cstring wraps C string and provide std_string like +// interface +// *************************************************************************** + +#ifndef BOOST_TEST_BASIC_CSTRING_HPP_071894GER +#define BOOST_TEST_BASIC_CSTRING_HPP_071894GER + +// Boost.Test +#include <boost/test/utils/basic_cstring/basic_cstring_fwd.hpp> +#include <boost/test/utils/basic_cstring/bcs_char_traits.hpp> + +// STL +#include <string> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +// ************************************************************************** // +// ************** basic_cstring ************** // +// ************************************************************************** // + +template<typename CharT> +class basic_cstring { + typedef basic_cstring<CharT> self_type; +public: + // Subtypes + typedef ut_detail::bcs_char_traits<CharT> traits_type; + typedef typename ut_detail::bcs_char_traits<CharT>::std_string std_string; + + typedef CharT value_type; + typedef value_type* pointer; + typedef value_type const* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef value_type const* const_iterator; + typedef value_type* iterator; + + // !! should also present reverse_iterator, const_reverse_iterator + +#if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) + enum npos_type { npos = static_cast<size_type>(-1) }; +#else + // IBM/VisualAge version 6 is not able to handle enums larger than 4 bytes. + // But size_type is 8 bytes in 64bit mode. + static const size_type npos = -1 ; +#endif + + static pointer null_str(); + + // Constructors; default copy constructor is generated by compiler + basic_cstring(); + basic_cstring( std_string const& s ); + basic_cstring( pointer s ); + basic_cstring( pointer s, size_type arg_size ); + basic_cstring( pointer first, pointer last ); + + // data access methods + value_type operator[]( size_type index ) const; + value_type at( size_type index ) const; + + // size operators + size_type size() const; + bool is_empty() const; + void clear(); + void resize( size_type new_len ); + + // !! only for STL container conformance use is_empty instead + bool empty() const; + + // Trimming + self_type& trim_right( size_type trim_size ); + self_type& trim_left( size_type trim_size ); + self_type& trim_right( iterator it ); + self_type& trim_left( iterator it ); +#ifndef __IBMCPP__ + self_type& trim_left( self_type exclusions = self_type() ) ; + self_type& trim_right( self_type exclusions = self_type() ) ; + self_type& trim( self_type exclusions = self_type() ) ; +#else + // VisualAge version 6 has in this case a problem with the default arguments. + self_type& trim_left( self_type exclusions ) ; + self_type& trim_right( self_type exclusions ) ; + self_type& trim( self_type exclusions ) ; + self_type& trim_left() { trim_left( self_type() ) ; } + self_type& trim_right() { trim_right( self_type() ) ; } + self_type& trim() { trim( self_type() ) ; } +#endif + + // Assignment operators + basic_cstring& operator=( self_type const& s ); + basic_cstring& operator=( std_string const& s ); + basic_cstring& operator=( pointer s ); + + template<typename CharT2> + basic_cstring& assign( basic_cstring<CharT2> const& s ) { *this = basic_cstring<CharT>( s.begin(), s.end() ); return *this; } + basic_cstring& assign( self_type const& s, size_type pos, size_type len ); + basic_cstring& assign( std_string const& s ); + basic_cstring& assign( std_string const& s, size_type pos, size_type len ); + basic_cstring& assign( pointer s ); + basic_cstring& assign( pointer s, size_type len ); + basic_cstring& assign( pointer f, pointer l ); + + // swapping + void swap( self_type& s ); + + // Iterators + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; + + // !! should have rbegin, rend + + // substring search operation + size_type find( basic_cstring ) const; + size_type rfind( basic_cstring ) const; + self_type substr( size_type beg_index, size_type end_index = npos ) const; + +private: + static self_type default_trim_ex(); + + // Data members + iterator m_begin; + iterator m_end; +}; + +//____________________________________________________________________________// + +template<typename CharT> +inline typename basic_cstring<CharT>::pointer +basic_cstring<CharT>::null_str() +{ + static CharT null = 0; + return &null; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline +basic_cstring<CharT>::basic_cstring() +: m_begin( null_str() ) +, m_end( m_begin ) +{ +} + +//____________________________________________________________________________// + +template<typename CharT> +inline +basic_cstring<CharT>::basic_cstring( std_string const& s ) +: m_begin( s.c_str() ) +, m_end( m_begin + s.size() ) +{ +} + +//____________________________________________________________________________// + +template<typename CharT> +inline +basic_cstring<CharT>::basic_cstring( pointer s ) +: m_begin( s ? s : null_str() ) +, m_end ( m_begin + (s ? traits_type::length( s ) : 0 ) ) +{ +} + +//____________________________________________________________________________// + +template<typename CharT> +inline +basic_cstring<CharT>::basic_cstring( pointer s, size_type arg_size ) +: m_begin( s ), m_end( m_begin + arg_size ) +{ +} + +//____________________________________________________________________________// + +template<typename CharT> +inline +basic_cstring<CharT>::basic_cstring( pointer first, pointer last ) +: m_begin( first ) +, m_end( last ) +{ +} + +//____________________________________________________________________________// + +template<typename CharT> +inline typename basic_cstring<CharT>::value_type +basic_cstring<CharT>::operator[]( size_type index ) const +{ + return m_begin[index]; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline typename basic_cstring<CharT>::value_type +basic_cstring<CharT>::at( size_type index ) const +{ + if( m_begin + index >= m_end ) + return static_cast<value_type>(0); + + return m_begin[index]; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline typename basic_cstring<CharT>::size_type +basic_cstring<CharT>::size() const +{ + return m_end - m_begin; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline bool +basic_cstring<CharT>::is_empty() const +{ + return m_end == m_begin; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline bool +basic_cstring<CharT>::empty() const +{ + return is_empty(); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline void +basic_cstring<CharT>::clear() +{ + m_begin = m_end; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline void +basic_cstring<CharT>::resize( size_type new_len ) +{ + if( m_begin + new_len < m_end ) + m_end = m_begin + new_len; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::trim_left( size_type trim_size ) +{ + m_begin += trim_size; + if( m_end <= m_begin ) + clear(); + + return *this; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::trim_left( iterator it ) +{ + m_begin = it; + if( m_end <= m_begin ) + clear(); + + return *this; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::trim_left( basic_cstring exclusions ) +{ + if( exclusions.is_empty() ) + exclusions = default_trim_ex(); + + iterator it; + for( it = begin(); it != end(); ++it ) { + if( traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast<pointer>(0) ) + break; + } + + return trim_left( it ); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::trim_right( size_type trim_size ) +{ + m_end -= trim_size; + if( m_end <= m_begin ) + clear(); + + return *this; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::trim_right( iterator it ) +{ + m_end = it; + if( m_end <= m_begin ) + clear(); + + return *this; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::trim_right( basic_cstring exclusions ) +{ + if( exclusions.is_empty() ) + exclusions = default_trim_ex(); + + iterator it; + + for( it = end()-1; it != begin()-1; --it ) { + if( self_type::traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast<pointer>(0) ) + break; + } + + return trim_right( it+1 ); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::trim( basic_cstring exclusions ) +{ + trim_left( exclusions ); + trim_right( exclusions ); + + return *this; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::operator=( basic_cstring<CharT> const& s ) +{ + m_begin = s.m_begin; + m_end = s.m_end; + + return *this; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::operator=( std_string const& s ) +{ + return *this = self_type( s ); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::operator=( pointer s ) +{ + return *this = self_type( s ); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::assign( basic_cstring<CharT> const& s, size_type pos, size_type len ) +{ + return *this = self_type( s.m_begin + pos, len ); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::assign( std_string const& s ) +{ + return *this = self_type( s ); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::assign( std_string const& s, size_type pos, size_type len ) +{ + return *this = self_type( s.c_str() + pos, len ); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::assign( pointer s ) +{ + return *this = self_type( s ); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::assign( pointer s, size_type len ) +{ + return *this = self_type( s, len ); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT>& +basic_cstring<CharT>::assign( pointer f, pointer l ) +{ + return *this = self_type( f, l ); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline void +basic_cstring<CharT>::swap( basic_cstring<CharT>& s ) +{ + // do not want to include alogrithm + pointer tmp1 = m_begin; + pointer tmp2 = m_end; + + m_begin = s.m_begin; + m_end = s.m_end; + + s.m_begin = tmp1; + s.m_end = tmp2; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline typename basic_cstring<CharT>::iterator +basic_cstring<CharT>::begin() +{ + return m_begin; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline typename basic_cstring<CharT>::const_iterator +basic_cstring<CharT>::begin() const +{ + return m_begin; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline typename basic_cstring<CharT>::iterator +basic_cstring<CharT>::end() +{ + return m_end; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline typename basic_cstring<CharT>::const_iterator +basic_cstring<CharT>::end() const +{ + return m_end; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline typename basic_cstring<CharT>::size_type +basic_cstring<CharT>::find( basic_cstring<CharT> str ) const +{ + if( str.is_empty() || str.size() > size() ) + return static_cast<size_type>(npos); + + const_iterator it = begin(); + const_iterator last = end() - str.size() + 1; + + while( it != last ) { + if( traits_type::compare( it, str.begin(), str.size() ) == 0 ) + break; + + ++it; + } + + return it == last ? static_cast<size_type>(npos) : it - begin(); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline typename basic_cstring<CharT>::size_type +basic_cstring<CharT>::rfind( basic_cstring<CharT> str ) const +{ + if( str.is_empty() || str.size() > size() ) + return static_cast<size_type>(npos); + + const_iterator it = end() - str.size(); + const_iterator last = begin()-1; + + while( it != last ) { + if( traits_type::compare( it, str.begin(), str.size() ) == 0 ) + break; + + --it; + } + + return it == last ? static_cast<size_type>(npos) : static_cast<size_type>(it - begin()); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT> +basic_cstring<CharT>::substr( size_type beg_index, size_type end_index ) const +{ + return beg_index > size() + ? self_type() + : end_index > size() + ? self_type( m_begin + beg_index, m_end ) + : self_type( m_begin + beg_index, m_begin + end_index ); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline basic_cstring<CharT> +basic_cstring<CharT>::default_trim_ex() +{ + static CharT ws[3] = { CharT(' '), CharT('\t'), CharT('\n') }; // !! wide case + + return self_type( ws, 3 ); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** comparison operators ************** // +// ************************************************************************** // + +template<typename CharT1,typename CharT2> +inline bool +operator==( basic_cstring<CharT1> const& s1, basic_cstring<CharT2> const& s2 ) +{ + typedef typename basic_cstring<CharT1>::traits_type traits_type; + return s1.size() == s2.size() && + traits_type::compare( s1.begin(), s2.begin(), s1.size() ) == 0; +} + +//____________________________________________________________________________// + +template<typename CharT1,typename CharT2> +inline bool +operator==( basic_cstring<CharT1> const& s1, CharT2* s2 ) +{ +#if !defined(__DMC__) + return s1 == basic_cstring<CharT2>( s2 ); +#else + return s1 == basic_cstring<CharT2 const>( s2 ); +#endif +} + +//____________________________________________________________________________// + +template<typename CharT> +inline bool +operator==( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 ) +{ + return s1 == basic_cstring<CharT>( s2 ); +} + +//____________________________________________________________________________// + +template<typename CharT1,typename CharT2> +inline bool +operator==( CharT1* s2, basic_cstring<CharT2> const& s1 ) +{ + return s1 == s2; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline bool +operator==( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 ) +{ + return s1 == s2; +} + +//____________________________________________________________________________// + +template<typename CharT> +inline bool +operator!=( basic_cstring<CharT> const& s1, CharT* s2 ) +{ + return !(s1 == s2); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline bool +operator!=( CharT* s2, basic_cstring<CharT> const& s1 ) +{ + return !(s1 == s2); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline bool +operator!=( basic_cstring<CharT> const& s1, basic_cstring<CharT> const& s2 ) +{ + return !(s1 == s2); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline bool +operator!=( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 ) +{ + return !(s1 == s2); +} + +//____________________________________________________________________________// + +template<typename CharT> +inline bool +operator!=( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 ) +{ + return !(s1 == s2); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** first_char ************** // +// ************************************************************************** // + +template<typename CharT> +inline typename basic_cstring<CharT>::value_type +first_char( basic_cstring<CharT> source ) +{ + typedef typename basic_cstring<CharT>::value_type string_value_type; + + return source.is_empty() ? static_cast<string_value_type>(0) : *source.begin(); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** last_char ************** // +// ************************************************************************** // + +template<typename CharT> +inline typename basic_cstring<CharT>::value_type +last_char( basic_cstring<CharT> source ) +{ + typedef typename basic_cstring<CharT>::value_type string_value_type; + + return source.is_empty() ? static_cast<string_value_type>(0) : *(source.end()-1); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** assign_op ************** // +// ************************************************************************** // + +template<typename CharT1, typename CharT2> +inline void +assign_op( std::basic_string<CharT1>& target, basic_cstring<CharT2> src, int ) +{ + target.assign( src.begin(), src.size() ); +} + +//____________________________________________________________________________// + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_TEST_BASIC_CSTRING_HPP_071894GER diff --git a/boost/test/utils/basic_cstring/basic_cstring_fwd.hpp b/boost/test/utils/basic_cstring/basic_cstring_fwd.hpp new file mode 100644 index 0000000000..e89456c2e3 --- /dev/null +++ b/boost/test/utils/basic_cstring/basic_cstring_fwd.hpp @@ -0,0 +1,40 @@ +// (C) Copyright Gennadiy Rozental 2004-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : basic_cstring class wrap C string and provide std_string like +// interface +// *************************************************************************** + +#ifndef BOOST_TEST_BASIC_CSTRING_FWD_HPP_071894GER +#define BOOST_TEST_BASIC_CSTRING_FWD_HPP_071894GER + +#include <boost/detail/workaround.hpp> + +namespace boost { + +namespace unit_test { + +template<typename CharT> class basic_cstring; +typedef basic_cstring<char const> const_string; +#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590041)) +typedef const_string literal_string; +#else +typedef const_string const literal_string; +#endif + +typedef char const* const c_literal_string; + +} // namespace unit_test + +} // namespace boost + +#endif // BOOST_TEST_BASIC_CSTRING_FWD_HPP_071894GER + diff --git a/boost/test/utils/basic_cstring/bcs_char_traits.hpp b/boost/test/utils/basic_cstring/bcs_char_traits.hpp new file mode 100644 index 0000000000..f932d473b8 --- /dev/null +++ b/boost/test/utils/basic_cstring/bcs_char_traits.hpp @@ -0,0 +1,150 @@ +// (C) Copyright Gennadiy Rozental 2004-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : generic char traits class; wraps std::char_traits +// *************************************************************************** + +#ifndef BOOST_TEST_BCS_CHAR_TRAITS_HPP_071894GER +#define BOOST_TEST_BCS_CHAR_TRAITS_HPP_071894GER + +// Boost +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/test/detail/config.hpp> +#include <boost/type_traits/add_const.hpp> + +// STL +#include <string> // std::char_traits +#include <cstddef> // std::size_t + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +namespace ut_detail { + +template<typename CharT> struct bcs_base_char { typedef CharT type; }; + +template<> struct bcs_base_char<char const> { typedef char type; }; +template<> struct bcs_base_char<unsigned char> { typedef char type; }; +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +template<> struct bcs_base_char<unsigned char const> { typedef char type; }; +#endif + +template<> struct bcs_base_char<wchar_t const> { typedef wchar_t type; }; + +// ************************************************************************** // +// ************** bcs_char_traits ************** // +// ************************************************************************** // + +template<typename CharT> +struct bcs_char_traits_impl +{ +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + typedef CharT const const_char; +#else + typedef typename boost::add_const<CharT>::type const_char; +#endif + static bool eq( CharT c1, CharT c2 ) + { + return c1 == c2; + } + static bool lt( CharT c1, CharT c2 ) + { + return c1 < c2; + } + + static int compare( const_char* cstr1, const_char* cstr2, std::size_t n ) + { + while( n > 0 ) { + if( !eq( *cstr1, *cstr2 ) ) + return lt( *cstr1, *cstr2 ) ? -1 : 1; + ++cstr1; + ++cstr2; + --n; + } + + return 0; + } + + static std::size_t length( const_char* cstr ) + { + const_char null_char = CharT(); + + const_char* ptr = cstr; + while( !eq( *ptr, null_char ) ) + ++ptr; + + return ptr - cstr; + } + + static const_char* find( const_char* s, std::size_t n, CharT c ) + { + while( n > 0 ) { + if( eq( *s, c ) ) + return s; + + ++s; + --n; + } + return 0; + } +}; + +#ifdef BOOST_CLASSIC_IOSTREAMS +template<typename CharT> +struct char_traits_with_find : std::string_char_traits<CharT> { + static CharT const* find( CharT const* s, std::size_t n, CharT c ) + { + while( n > 0 ) { + if( eq( *s, c ) ) + return s; + + ++s; + --n; + } + return 0; + } +}; + +template<> struct bcs_char_traits_impl<char> : char_traits_with_find<char> {}; +template<> struct bcs_char_traits_impl<wchar_t> : char_traits_with_find<wchar_t> {}; +#else +template<> struct bcs_char_traits_impl<char> : std::char_traits<char> {}; +template<> struct bcs_char_traits_impl<wchar_t> : std::char_traits<wchar_t> {}; +#endif + +template<typename CharT> +class bcs_char_traits : public bcs_char_traits_impl<CharT> { + typedef typename ut_detail::bcs_base_char<CharT>::type the_base_char; +public: +#ifdef BOOST_CLASSIC_IOSTREAMS + typedef std::basic_string<the_base_char, std::string_char_traits<the_base_char> > std_string; +#else + typedef std::basic_string<the_base_char, std::char_traits<the_base_char> > std_string; +#endif +}; + +} // namespace ut_detail + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_TEST_BCS_CHAR_TRAITS_HPP_071894GER diff --git a/boost/test/utils/basic_cstring/compare.hpp b/boost/test/utils/basic_cstring/compare.hpp new file mode 100644 index 0000000000..8866c44c2c --- /dev/null +++ b/boost/test/utils/basic_cstring/compare.hpp @@ -0,0 +1,115 @@ +// (C) Copyright Gennadiy Rozental 2004-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : class basic_cstring comparisons implementation +// *************************************************************************** + +#ifndef BOOST_TEST_BASIC_CSTRING_COMPARE_HPP_071894GER +#define BOOST_TEST_BASIC_CSTRING_COMPARE_HPP_071894GER + +// Boost.Test +#include <boost/test/utils/basic_cstring/basic_cstring.hpp> + +// STL +#include <functional> +#include <cctype> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +# if defined(BOOST_NO_STDC_NAMESPACE) && !BOOST_WORKAROUND(__BORLANDC__, <= 0x570) +namespace std { using ::toupper; } +# endif + +namespace boost { + +namespace unit_test { + +// ************************************************************************** // +// ************** case_ins_compare ************** // +// ************************************************************************** // + +namespace ut_detail { + +template<class CharT> +struct case_ins +{ + static bool eq( CharT c1, CharT c2 ) { return (std::toupper)( c1 ) == (std::toupper)( c2 ); } + static bool lt( CharT c1, CharT c2 ) { return (std::toupper)( c1 ) < (std::toupper)( c2 ); } + + static int compare( CharT const* s1, CharT const* s2, std::size_t n ) + { + for( std::size_t i = 0; i < n; ++i ) { + if( !eq( s1[i], s2[i] ) ) + return lt( s1[i], s2[i] ) ? -1 : 1; + } + return 0; + } +}; + +} // namespace ut_detail + +// ************************************************************************** // +// ************** case_ins_eq ************** // +// ************************************************************************** // + +template<class CharT> +inline bool +case_ins_eq( basic_cstring<CharT> x, basic_cstring<CharT> y ) +{ + return x.size() == y.size() && ut_detail::case_ins<CharT>::compare( x.begin(), y.begin(), x.size() ) == 0; +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** case_ins_less ************** // +// ************************************************************************** // + +template<class CharT> +class case_ins_less : public std::binary_function<basic_cstring<CharT>,basic_cstring<CharT>,bool> +{ +public: + bool operator()( basic_cstring<CharT> x, basic_cstring<CharT> y ) const + { + return x.size() != y.size() + ? x.size() < y.size() + : ut_detail::case_ins<CharT>::compare( x.begin(), y.begin(), x.size() ) < 0; + } +}; + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** operator < ************** // +// ************************************************************************** // + +template<class CharT> +inline bool +operator <( boost::unit_test::basic_cstring<CharT> const& x, + boost::unit_test::basic_cstring<CharT> const& y ) +{ + typedef typename boost::unit_test::basic_cstring<CharT>::traits_type traits_type; + return x.size() != y.size() + ? x.size() < y.size() + : traits_type::compare( x.begin(), y.begin(), x.size() ) < 0; +} + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_TEST_BASIC_CSTRING_COMPARE_HPP_071894GER diff --git a/boost/test/utils/basic_cstring/io.hpp b/boost/test/utils/basic_cstring/io.hpp new file mode 100644 index 0000000000..04e4b4c23f --- /dev/null +++ b/boost/test/utils/basic_cstring/io.hpp @@ -0,0 +1,73 @@ +// (C) Copyright Gennadiy Rozental 2004-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : basic_cstring i/o implementation +// *************************************************************************** + +#ifndef BOOST_TEST_BASIC_CSTRING_IO_HPP_071894GER +#define BOOST_TEST_BASIC_CSTRING_IO_HPP_071894GER + +// Boost.Test +#include <boost/test/utils/basic_cstring/basic_cstring.hpp> + +// STL +#include <iosfwd> +#include <string> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +#ifdef BOOST_CLASSIC_IOSTREAMS + +template<typename CharT> +inline std::ostream& +operator<<( std::ostream& os, basic_cstring<CharT> const& str ) +{ + typedef typename ut_detail::bcs_base_char<CharT>::type char_type; + char_type const* const beg = reinterpret_cast<char_type const* const>( str.begin() ); + char_type const* const end = reinterpret_cast<char_type const* const>( str.end() ); + os << std::basic_string<char_type>( beg, end - beg ); + + return os; +} + +#else + +template<typename CharT1, typename Tr,typename CharT2> +inline std::basic_ostream<CharT1,Tr>& +operator<<( std::basic_ostream<CharT1,Tr>& os, basic_cstring<CharT2> const& str ) +{ + CharT1 const* const beg = reinterpret_cast<CharT1 const*>( str.begin() ); // !! + CharT1 const* const end = reinterpret_cast<CharT1 const*>( str.end() ); + os << std::basic_string<CharT1,Tr>( beg, end - beg ); + + return os; +} + +#endif + +//____________________________________________________________________________// + + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_TEST_BASIC_CSTRING_IO_HPP_071894GER diff --git a/boost/test/utils/callback.hpp b/boost/test/utils/callback.hpp new file mode 100644 index 0000000000..bd7d3e1241 --- /dev/null +++ b/boost/test/utils/callback.hpp @@ -0,0 +1,310 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : +// *************************************************************************** + +#ifndef BOOST_TEST_CALLBACK_020505GER +#define BOOST_TEST_CALLBACK_020505GER + +// Boost +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/shared_ptr.hpp> + +#include <boost/test/detail/suppress_warnings.hpp> + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) || BOOST_WORKAROUND(BOOST_INTEL, <= 700) +# define BOOST_CALLBACK_EXPLICIT_COPY_CONSTRUCTOR +#endif + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +namespace ut_detail { + +struct unused {}; + +template<typename R> +struct invoker { + template<typename Functor> + R invoke( Functor& f ) { return f(); } + template<typename Functor, typename T1> + R invoke( Functor& f, T1 t1 ) { return f( t1 ); } + template<typename Functor, typename T1, typename T2> + R invoke( Functor& f, T1 t1, T2 t2 ) { return f( t1, t2 ); } + template<typename Functor, typename T1, typename T2, typename T3> + R invoke( Functor& f, T1 t1, T2 t2, T3 t3 ) { return f( t1, t2, t3 ); } +}; + +//____________________________________________________________________________// + +template<> +struct invoker<unused> { + template<typename Functor> + unused invoke( Functor& f ) { f(); return unused(); } + template<typename Functor, typename T1> + unused invoke( Functor& f, T1 t1 ) { f( t1 ); return unused(); } + template<typename Functor, typename T1, typename T2> + unused invoke( Functor& f, T1 t1, T2 t2 ) { f( t1, t2 ); return unused(); } + template<typename Functor, typename T1, typename T2, typename T3> + unused invoke( Functor& f, T1 t1, T2 t2, T3 t3 ) { f( t1, t2, t3 ); return unused(); } +}; + +//____________________________________________________________________________// + +} // namespace ut_detail + +// ************************************************************************** // +// ************** unit_test::callback0 ************** // +// ************************************************************************** // + +namespace ut_detail { + +template<typename R> +struct callback0_impl { + virtual ~callback0_impl() {} + + virtual R invoke() = 0; +}; + +//____________________________________________________________________________// + +template<typename R, typename Functor> +struct callback0_impl_t : callback0_impl<R> { + // Constructor + explicit callback0_impl_t( Functor f ) : m_f( f ) {} + + virtual R invoke() { return invoker<R>().invoke( m_f ); } + +private: + // Data members + Functor m_f; +}; + +//____________________________________________________________________________// + +} // namespace ut_detail + +template<typename R = ut_detail::unused> +class callback0 { +public: + // Constructors + callback0() {} +#ifdef BOOST_CALLBACK_EXPLICIT_COPY_CONSTRUCTOR + callback0( callback0 const& rhs ) : m_impl( rhs.m_impl ) {} +#endif + + template<typename Functor> + callback0( Functor f ) + : m_impl( new ut_detail::callback0_impl_t<R,Functor>( f ) ) {} + + void operator=( callback0 const& rhs ) { m_impl = rhs.m_impl; } + + template<typename Functor> + void operator=( Functor f ) { m_impl.reset( new ut_detail::callback0_impl_t<R,Functor>( f ) ); } + + R operator()() const { return m_impl->invoke(); } + + bool operator!() const { return !m_impl; } + +private: + // Data members + boost::shared_ptr<ut_detail::callback0_impl<R> > m_impl; +}; + +// ************************************************************************** // +// ************** unit_test::callback1 ************** // +// ************************************************************************** // + +namespace ut_detail { + +template<typename R, typename T1> +struct callback1_impl { + virtual ~callback1_impl() {} + + virtual R invoke( T1 t1 ) = 0; +}; + +//____________________________________________________________________________// + +template<typename R, typename T1,typename Functor> +struct callback1_impl_t : callback1_impl<R,T1> { + // Constructor + explicit callback1_impl_t( Functor f ) : m_f( f ) {} + + virtual R invoke( T1 t1 ) { return invoker<R>().invoke( m_f, t1 ); } + +private: + // Data members + Functor m_f; +}; + +//____________________________________________________________________________// + +} // namespace ut_detail + +template<typename T1,typename R = ut_detail::unused> +class callback1 { +public: + // Constructors + callback1() {} +#ifdef BOOST_CALLBACK_EXPLICIT_COPY_CONSTRUCTOR + callback1( callback1 const& rhs ) : m_impl( rhs.m_impl ) {} +#endif + + template<typename Functor> + callback1( Functor f ) + : m_impl( new ut_detail::callback1_impl_t<R,T1,Functor>( f ) ) {} + + void operator=( callback1 const& rhs ) { m_impl = rhs.m_impl; } + + template<typename Functor> + void operator=( Functor f ) { m_impl.reset( new ut_detail::callback1_impl_t<R,T1,Functor>( f ) ); } + + R operator()( T1 t1 ) const { return m_impl->invoke( t1 ); } + + bool operator!() const { return !m_impl; } + +private: + // Data members + boost::shared_ptr<ut_detail::callback1_impl<R,T1> > m_impl; +}; + +// ************************************************************************** // +// ************** unit_test::callback2 ************** // +// ************************************************************************** // + +namespace ut_detail { + +template<typename R, typename T1,typename T2> +struct callback2_impl { + virtual ~callback2_impl() {} + + virtual R invoke( T1 t1, T2 t2 ) = 0; +}; + +//____________________________________________________________________________// + +template<typename R, typename T1, typename T2, typename Functor> +struct callback2_impl_t : callback2_impl<R,T1,T2> { + // Constructor + explicit callback2_impl_t( Functor f ) : m_f( f ) {} + + virtual R invoke( T1 t1, T2 t2 ) { return invoker<R>().template invoke<Functor,T1,T2>( m_f, t1, t2 ); } + +private: + // Data members + Functor m_f; +}; + +//____________________________________________________________________________// + +} // namespace ut_detail + +template<typename T1,typename T2, typename R = ut_detail::unused> +class callback2 { +public: + // Constructors + callback2() {} +#ifdef BOOST_CALLBACK_EXPLICIT_COPY_CONSTRUCTOR + callback2( callback2 const& rhs ) : m_impl( rhs.m_impl ) {} +#endif + + template<typename Functor> + callback2( Functor f ) : m_impl( new ut_detail::callback2_impl_t<R,T1,T2,Functor>( f ) ) {} + + void operator=( callback2 const& rhs ) { m_impl = rhs.m_impl; } + + template<typename Functor> + void operator=( Functor f ) { m_impl.reset( new ut_detail::callback2_impl_t<R,T1,T2,Functor>( f ) ); } + + R operator()( T1 t1, T2 t2 ) const { return m_impl->invoke( t1, t2 ); } + + bool operator!() const { return !m_impl; } + +private: + // Data members + boost::shared_ptr<ut_detail::callback2_impl<R,T1,T2> > m_impl; +}; + +// ************************************************************************** // +// ************** unit_test::callback3 ************** // +// ************************************************************************** // + +namespace ut_detail { + +template<typename R, typename T1, typename T2, typename T3> +struct callback3_impl { + virtual ~callback3_impl() {} + + virtual R invoke( T1 t1, T2 t2, T3 t3 ) = 0; +}; + +//____________________________________________________________________________// + +template<typename R, typename T1, typename T2, typename T3, typename Functor> +struct callback3_impl_t : callback3_impl<R,T1,T2,T3> { + // Constructor + explicit callback3_impl_t( Functor f ) : m_f( f ) {} + + virtual R invoke( T1 t1, T2 t2, T3 t3 ) { return invoker<R>().invoke( m_f, t1, t2, t3 ); } + +private: + // Data members + Functor m_f; +}; + +//____________________________________________________________________________// + +} // namespace ut_detail + +template<typename T1,typename T2, typename T3, typename R = ut_detail::unused> +class callback3 { +public: + // Constructors + callback3() {} +#ifdef BOOST_CALLBACK_EXPLICIT_COPY_CONSTRUCTOR + callback3( callback3 const& rhs ) : m_impl( rhs.m_impl ) {} +#endif + + template<typename Functor> + callback3( Functor f ) + : m_impl( new ut_detail::callback3_impl_t<R,T1,T2,T3,Functor>( f ) ) {} + + void operator=( callback3 const& rhs ) { m_impl = rhs.m_impl; } + + template<typename Functor> + void operator=( Functor f ) { m_impl.reset( new ut_detail::callback3_impl_t<R,T1,T2,T3,Functor>( f ) ); } + + R operator()( T1 t1, T2 t2, T3 t3 ) const { return m_impl->invoke( t1, t2, t3 ); } + + bool operator!() const { return !m_impl; } + +private: + // Data members + boost::shared_ptr<ut_detail::callback3_impl<R,T1,T2,T3> > m_impl; +}; + +} // namespace unit_test + +} // namespace boost + +#undef BOOST_CALLBACK_EXPLICIT_COPY_CONSTRUCTOR + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_TEST_CALLBACK_020505GER diff --git a/boost/test/utils/class_properties.hpp b/boost/test/utils/class_properties.hpp new file mode 100644 index 0000000000..a7842b5b58 --- /dev/null +++ b/boost/test/utils/class_properties.hpp @@ -0,0 +1,221 @@ +// (C) Copyright Gennadiy Rozental 2001-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : simple facility that mimmic notion of read-only read-write +// properties in C++ classes. Original idea by Henrik Ravn. +// *************************************************************************** + +#ifndef BOOST_TEST_CLASS_PROPERTIES_HPP_071894GER +#define BOOST_TEST_CLASS_PROPERTIES_HPP_071894GER + +// Boost.Test +#include <boost/test/detail/config.hpp> + +// Boost +#if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) +#include <boost/preprocessor/seq/for_each.hpp> +#endif +#include <boost/call_traits.hpp> +#include <boost/type_traits/add_pointer.hpp> +#include <boost/type_traits/add_const.hpp> +#include <boost/utility/addressof.hpp> + +// STL +#include <iosfwd> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +// ************************************************************************** // +// ************** class_property ************** // +// ************************************************************************** // + +template<class PropertyType> +class class_property { +protected: + typedef typename call_traits<PropertyType>::const_reference read_access_t; + typedef typename call_traits<PropertyType>::param_type write_param_t; + typedef typename add_pointer<typename add_const<PropertyType>::type>::type address_res_t; +public: + // Constructor + class_property() : value( PropertyType() ) {} + explicit class_property( write_param_t init_value ) + : value( init_value ) {} + + // Access methods + operator read_access_t() const { return value; } + read_access_t get() const { return value; } + bool operator!() const { return !value; } + address_res_t operator&() const { return &value; } + + // Data members +#ifndef BOOST_TEST_NO_PROTECTED_USING +protected: +#endif + PropertyType value; +}; + +//____________________________________________________________________________// + +#ifdef BOOST_CLASSIC_IOSTREAMS + +template<class PropertyType> +inline std::ostream& +operator<<( std::ostream& os, class_property<PropertyType> const& p ) + +#else + +template<typename CharT1, typename Tr,class PropertyType> +inline std::basic_ostream<CharT1,Tr>& +operator<<( std::basic_ostream<CharT1,Tr>& os, class_property<PropertyType> const& p ) + +#endif +{ + return os << p.get(); +} + +//____________________________________________________________________________// + +#define DEFINE_PROPERTY_FREE_BINARY_OPERATOR( op ) \ +template<class PropertyType> \ +inline bool \ +operator op( PropertyType const& lhs, class_property<PropertyType> const& rhs ) \ +{ \ + return lhs op rhs.get(); \ +} \ +template<class PropertyType> \ +inline bool \ +operator op( class_property<PropertyType> const& lhs, PropertyType const& rhs ) \ +{ \ + return lhs.get() op rhs; \ +} \ +template<class PropertyType> \ +inline bool \ +operator op( class_property<PropertyType> const& lhs, \ + class_property<PropertyType> const& rhs ) \ +{ \ + return lhs.get() op rhs.get(); \ +} \ +/**/ + +DEFINE_PROPERTY_FREE_BINARY_OPERATOR( == ) +DEFINE_PROPERTY_FREE_BINARY_OPERATOR( != ) + +#undef DEFINE_PROPERTY_FREE_BINARY_OPERATOR + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + +#define DEFINE_PROPERTY_LOGICAL_OPERATOR( op ) \ +template<class PropertyType> \ +inline bool \ +operator op( bool b, class_property<PropertyType> const& p ) \ +{ \ + return b op p.get(); \ +} \ +template<class PropertyType> \ +inline bool \ +operator op( class_property<PropertyType> const& p, bool b ) \ +{ \ + return b op p.get(); \ +} \ +/**/ + +DEFINE_PROPERTY_LOGICAL_OPERATOR( && ) +DEFINE_PROPERTY_LOGICAL_OPERATOR( || ) + +#endif + +// ************************************************************************** // +// ************** readonly_property ************** // +// ************************************************************************** // + +template<class PropertyType> +class readonly_property : public class_property<PropertyType> { + typedef class_property<PropertyType> base_prop; + typedef typename base_prop::address_res_t arrow_res_t; +protected: + typedef typename base_prop::write_param_t write_param_t; +public: + // Constructor + readonly_property() {} + explicit readonly_property( write_param_t init_value ) : base_prop( init_value ) {} + + // access methods + arrow_res_t operator->() const { return boost::addressof( base_prop::value ); } +}; + +//____________________________________________________________________________// + +#if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) + +#define BOOST_READONLY_PROPERTY( property_type, friends ) boost::unit_test::readwrite_property<property_type > + +#else + +#define BOOST_READONLY_PROPERTY_DECLARE_FRIEND(r, data, elem) friend class elem; + +#define BOOST_READONLY_PROPERTY( property_type, friends ) \ +class BOOST_JOIN( readonly_property, __LINE__ ) \ +: public boost::unit_test::readonly_property<property_type > { \ + typedef boost::unit_test::readonly_property<property_type > base_prop; \ + BOOST_PP_SEQ_FOR_EACH( BOOST_READONLY_PROPERTY_DECLARE_FRIEND, ' ', friends ) \ + typedef base_prop::write_param_t write_param_t; \ +public: \ + BOOST_JOIN( readonly_property, __LINE__ )() {} \ + explicit BOOST_JOIN( readonly_property, __LINE__ )( write_param_t init_v ) \ + : base_prop( init_v ) {} \ +} \ +/**/ + +#endif + +// ************************************************************************** // +// ************** readwrite_property ************** // +// ************************************************************************** // + +template<class PropertyType> +class readwrite_property : public class_property<PropertyType> { + typedef class_property<PropertyType> base_prop; + typedef typename add_pointer<PropertyType>::type arrow_res_t; + typedef typename base_prop::address_res_t const_arrow_res_t; + typedef typename base_prop::write_param_t write_param_t; +public: + readwrite_property() : base_prop() {} + explicit readwrite_property( write_param_t init_value ) : base_prop( init_value ) {} + + // access methods + void set( write_param_t v ) { base_prop::value = v; } + arrow_res_t operator->() { return boost::addressof( base_prop::value ); } + const_arrow_res_t operator->() const { return boost::addressof( base_prop::value ); } + +#ifndef BOOST_TEST_NO_PROTECTED_USING + using base_prop::value; +#endif +}; + +//____________________________________________________________________________// + +} // unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#undef BOOST_TEST_NO_PROTECTED_USING + +#endif // BOOST_TEST_CLASS_PROPERTIES_HPP_071894GER diff --git a/boost/test/utils/custom_manip.hpp b/boost/test/utils/custom_manip.hpp new file mode 100644 index 0000000000..8788ccbf93 --- /dev/null +++ b/boost/test/utils/custom_manip.hpp @@ -0,0 +1,63 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : simple helpers for creating cusom output manipulators +// *************************************************************************** + +#ifndef BOOST_TEST_CUSTOM_MANIP_HPP_071894GER +#define BOOST_TEST_CUSTOM_MANIP_HPP_071894GER + +// STL +#include <iosfwd> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +// ************************************************************************** // +// ************** custom manipulators helpers ************** // +// ************************************************************************** // + +template<typename Manip> +struct custom_printer { + explicit custom_printer( std::ostream& ostr ) : m_ostr( &ostr ) {} + + std::ostream& operator*() const { return *m_ostr; } + +private: + std::ostream* const m_ostr; +}; + +//____________________________________________________________________________// + +template<typename Uniq> struct custom_manip {}; + +//____________________________________________________________________________// + +template<typename Uniq> +inline custom_printer<custom_manip<Uniq> > +operator<<( std::ostream& ostr, custom_manip<Uniq> const& ) { return custom_printer<custom_manip<Uniq> >( ostr ); } + +//____________________________________________________________________________// + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_TEST_CUSTOM_MANIP_HPP_071894GER diff --git a/boost/test/utils/fixed_mapping.hpp b/boost/test/utils/fixed_mapping.hpp new file mode 100644 index 0000000000..b0ab3b8773 --- /dev/null +++ b/boost/test/utils/fixed_mapping.hpp @@ -0,0 +1,124 @@ +// (C) Copyright Gennadiy Rozental 2001-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : fixed sized mapping with specified invalid value +// *************************************************************************** + +#ifndef BOOST_TEST_FIXED_MAPPING_HPP_071894GER +#define BOOST_TEST_FIXED_MAPPING_HPP_071894GER + +// Boost +#include <boost/preprocessor/repetition/repeat.hpp> +#include <boost/preprocessor/arithmetic/add.hpp> +#include <boost/call_traits.hpp> +#include <boost/detail/binary_search.hpp> + +// STL +#include <vector> +#include <functional> +#include <algorithm> +#include <utility> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +// configurable maximum fixed sized mapping size supported by this header. +// You can redefine it before inclusion of this file. +#ifndef MAX_MAP_SIZE +#define MAX_MAP_SIZE 20 +#endif + +#define CONSTR_DECL_MID( z, i, dummy1 ) key_param_type key##i, value_param_type v##i, +#define CONSTR_BODY_MID( z, i, dummy1 ) add_pair( key##i, v##i ); + +#define CONSTR_DECL( z, n, dummy1 ) \ + fixed_mapping( BOOST_PP_REPEAT_ ## z( n, CONSTR_DECL_MID, "" ) \ + value_param_type invalid_value ) \ + : m_invalid_value( invalid_value ) \ + { \ + BOOST_PP_REPEAT_ ## z( n, CONSTR_BODY_MID, "" ) \ + init(); \ + } \ +/**/ + +#define CONTRUCTORS( n ) BOOST_PP_REPEAT( n, CONSTR_DECL, "" ) + +template<typename Key, typename Value, typename Compare = std::less<Key> > +class fixed_mapping +{ + typedef std::pair<Key,Value> elem_type; + typedef std::vector<elem_type> map_type; + typedef typename std::vector<elem_type>::const_iterator iterator; + + typedef typename call_traits<Key>::param_type key_param_type; + typedef typename call_traits<Value>::param_type value_param_type; + typedef typename call_traits<Value>::const_reference value_ref_type; + +#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) + struct p1; friend struct p1; + struct p2; friend struct p2; +#endif + + // bind( Compare(), bind(select1st<elem_type>(), _1), bind(identity<Key>(), _2) ) + struct p1 : public std::binary_function<elem_type,Key,bool> + { + bool operator()( elem_type const& x, Key const& y ) const { return Compare()( x.first, y ); } + }; + + // bind( Compare(), bind(select1st<elem_type>(), _1), bind(select1st<elem_type>(), _2) ) + struct p2 : public std::binary_function<elem_type,elem_type,bool> + { + bool operator()( elem_type const& x, elem_type const& y ) const { return Compare()( x.first, y.first ); } + }; + +public: + // Constructors + CONTRUCTORS( BOOST_PP_ADD( MAX_MAP_SIZE, 1 ) ) + + // key -> value access + value_ref_type operator[]( key_param_type key ) const + { + iterator it = boost::detail::lower_bound( m_map.begin(), m_map.end(), key, p1() ); + + return (it == m_map.end() || Compare()( key, it->first ) ) ? m_invalid_value : it->second; + } + +private: + // Implementation + void init() { std::sort( m_map.begin(), m_map.end(), p2() ); } + void add_pair( key_param_type key, value_param_type value ) { m_map.push_back( elem_type( key, value ) ); } + + // Data members + Value m_invalid_value; + map_type m_map; +}; + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#undef MAX_MAP_SIZE +#undef CONSTR_DECL_MID +#undef CONSTR_BODY_MID +#undef CONSTR_DECL +#undef CONTRUCTORS + +#endif // BOOST_TEST_FIXED_MAPPING_HPP_071894GER + diff --git a/boost/test/utils/foreach.hpp b/boost/test/utils/foreach.hpp new file mode 100644 index 0000000000..d12fa43024 --- /dev/null +++ b/boost/test/utils/foreach.hpp @@ -0,0 +1,281 @@ +// (C) Copyright Eric Niebler 2004-2005 +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : this is an abridged version of an excelent BOOST_FOREACH facility +// presented by Eric Niebler. I am so fond of it so I can't wait till it +// going to be accepted into Boost. Also I need version with less number of dependencies +// and more portable. This version doesn't support rvalues and will reeveluate it's +// parameters, but should be good enough for my purposes. +// *************************************************************************** + +#ifndef BOOST_TEST_FOREACH_HPP_021005GER +#define BOOST_TEST_FOREACH_HPP_021005GER + +// Boost.Test +#include <boost/test/detail/config.hpp> + +// Boost +#include <boost/type.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/test/detail/workaround.hpp> + +#include <boost/type_traits/is_const.hpp> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +namespace for_each { + +// ************************************************************************** // +// ************** static_any ************** // +// ************************************************************************** // + +struct static_any_base +{ + operator bool() const { return false; } +}; + +//____________________________________________________________________________// + +template<typename Iter> +struct static_any : static_any_base +{ + static_any( Iter const& t ) : m_it( t ) {} + + mutable Iter m_it; +}; + +//____________________________________________________________________________// + +typedef static_any_base const& static_any_t; + +//____________________________________________________________________________// + +template<typename Iter> +inline Iter& +static_any_cast( static_any_t a, Iter* = 0 ) +{ + return static_cast<Iter&>( static_cast<static_any<Iter> const&>( a ).m_it ); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** is_const ************** // +// ************************************************************************** // + +template<typename C> +inline is_const<C> +is_const_coll( C& ) +{ + return is_const<C>(); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** begin ************** // +// ************************************************************************** // + +template<typename C> +inline static_any<BOOST_DEDUCED_TYPENAME C::iterator> +begin( C& t, mpl::false_ ) +{ + return static_any<BOOST_DEDUCED_TYPENAME C::iterator>( t.begin() ); +} + +//____________________________________________________________________________// + +template<typename C> +inline static_any<BOOST_DEDUCED_TYPENAME C::const_iterator> +begin( C const& t, mpl::true_ ) +{ + return static_any<BOOST_DEDUCED_TYPENAME C::const_iterator>( t.begin() ); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** end ************** // +// ************************************************************************** // + +template<typename C> +inline static_any<BOOST_DEDUCED_TYPENAME C::iterator> +end( C& t, mpl::false_ ) +{ + return static_any<BOOST_DEDUCED_TYPENAME C::iterator>( t.end() ); +} + +//____________________________________________________________________________// + +template<typename C> +inline static_any<BOOST_DEDUCED_TYPENAME C::const_iterator> +end( C const& t, mpl::true_ ) +{ + return static_any<BOOST_DEDUCED_TYPENAME C::const_iterator>( t.end() ); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** done ************** // +// ************************************************************************** // + +template<typename C> +inline bool +done( static_any_t cur, static_any_t end, C&, mpl::false_ ) +{ + return static_any_cast<BOOST_DEDUCED_TYPENAME C::iterator>( cur ) == + static_any_cast<BOOST_DEDUCED_TYPENAME C::iterator>( end ); +} + +//____________________________________________________________________________// + +template<typename C> +inline bool +done( static_any_t cur, static_any_t end, C const&, mpl::true_ ) +{ + return static_any_cast<BOOST_DEDUCED_TYPENAME C::const_iterator>( cur ) == + static_any_cast<BOOST_DEDUCED_TYPENAME C::const_iterator>( end ); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** next ************** // +// ************************************************************************** // + +template<typename C> +inline void +next( static_any_t cur, C&, mpl::false_ ) +{ + ++static_any_cast<BOOST_DEDUCED_TYPENAME C::iterator>( cur ); +} + +//____________________________________________________________________________// + +template<typename C> +inline void +next( static_any_t cur, C const&, mpl::true_ ) +{ + ++static_any_cast<BOOST_DEDUCED_TYPENAME C::const_iterator>( cur ); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** deref ************** // +// ************************************************************************** // + +template<class RefType,typename C> +inline RefType +deref( static_any_t cur, C&, ::boost::type<RefType>, mpl::false_ ) +{ + return *static_any_cast<BOOST_DEDUCED_TYPENAME C::iterator>( cur ); +} + +//____________________________________________________________________________// + +template<class RefType,typename C> +inline RefType +deref( static_any_t cur, C const&, ::boost::type<RefType>, mpl::true_ ) +{ + return *static_any_cast<BOOST_DEDUCED_TYPENAME C::const_iterator>( cur ); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** BOOST_TEST_FOREACH ************** // +// ************************************************************************** // + +#define BOOST_TEST_FE_ANY ::boost::unit_test::for_each::static_any_t +#define BOOST_TEST_FE_IS_CONST( COL ) ::boost::unit_test::for_each::is_const_coll( COL ) + +#define BOOST_TEST_FE_BEG( COL ) \ + ::boost::unit_test::for_each::begin( \ + COL, \ + BOOST_TEST_FE_IS_CONST( COL ) ) \ +/**/ + +#define BOOST_TEST_FE_END( COL ) \ + ::boost::unit_test::for_each::end( \ + COL, \ + BOOST_TEST_FE_IS_CONST( COL ) ) \ +/**/ + +#define BOOST_TEST_FE_DONE( COL ) \ + ::boost::unit_test::for_each::done( \ + BOOST_TEST_FE_CUR_VAR, \ + BOOST_TEST_FE_END_VAR, \ + COL, \ + BOOST_TEST_FE_IS_CONST( COL ) ) \ +/**/ + +#define BOOST_TEST_FE_NEXT( COL ) \ + ::boost::unit_test::for_each::next( \ + BOOST_TEST_FE_CUR_VAR, \ + COL, \ + BOOST_TEST_FE_IS_CONST( COL ) ) \ +/**/ + +#define BOOST_FOREACH_NOOP(COL) \ + ((void)&(COL)) + +#define BOOST_TEST_FE_DEREF( COL, RefType ) \ + ::boost::unit_test::for_each::deref( \ + BOOST_TEST_FE_CUR_VAR, \ + COL, \ + ::boost::type<RefType >(), \ + BOOST_TEST_FE_IS_CONST( COL ) ) \ +/**/ + +#if BOOST_WORKAROUND( BOOST_MSVC, == 1310 ) +#define BOOST_TEST_LINE_NUM +#else +#define BOOST_TEST_LINE_NUM __LINE__ +#endif + +#define BOOST_TEST_FE_CUR_VAR BOOST_JOIN( _fe_cur_, BOOST_TEST_LINE_NUM ) +#define BOOST_TEST_FE_END_VAR BOOST_JOIN( _fe_end_, BOOST_TEST_LINE_NUM ) +#define BOOST_TEST_FE_CON_VAR BOOST_JOIN( _fe_con_, BOOST_TEST_LINE_NUM ) + +#define BOOST_TEST_FOREACH( RefType, var, COL ) \ +if( BOOST_TEST_FE_ANY BOOST_TEST_FE_CUR_VAR = BOOST_TEST_FE_BEG( COL ) ) {} else \ +if( BOOST_TEST_FE_ANY BOOST_TEST_FE_END_VAR = BOOST_TEST_FE_END( COL ) ) {} else \ +for( bool BOOST_TEST_FE_CON_VAR = true; \ + BOOST_TEST_FE_CON_VAR && !BOOST_TEST_FE_DONE( COL ); \ + BOOST_TEST_FE_CON_VAR ? BOOST_TEST_FE_NEXT( COL ) : BOOST_FOREACH_NOOP( COL )) \ + \ + if( (BOOST_TEST_FE_CON_VAR = false, false) ) {} else \ + for( RefType var = BOOST_TEST_FE_DEREF( COL, RefType ); \ + !BOOST_TEST_FE_CON_VAR; BOOST_TEST_FE_CON_VAR = true ) \ +/**/ + +//____________________________________________________________________________// + +} // namespace for_each + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_TEST_FOREACH_HPP_021005GER diff --git a/boost/test/utils/iterator/ifstream_line_iterator.hpp b/boost/test/utils/iterator/ifstream_line_iterator.hpp new file mode 100644 index 0000000000..3005ef14c1 --- /dev/null +++ b/boost/test/utils/iterator/ifstream_line_iterator.hpp @@ -0,0 +1,104 @@ +// (C) Copyright Gennadiy Rozental 2004-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : +// *************************************************************************** + +#ifndef BOOST_IFSTREAM_LINE_ITERATOR_HPP_071894GER +#define BOOST_IFSTREAM_LINE_ITERATOR_HPP_071894GER + +// Boost +#include <boost/test/utils/iterator/istream_line_iterator.hpp> + +// STL +#include <fstream> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +namespace ut_detail { + +// ************************************************************************** // +// ************** ifstream_holder ************** // +// ************************************************************************** // + +template<typename CharT> +class ifstream_holder { +public: + // Constructor + explicit ifstream_holder( basic_cstring<CharT const> file_name ) + { + if( file_name.is_empty() ) + return; + + m_stream.open( file_name.begin(), std::ios::in ); + } + + bool is_valid() + { + return m_stream.is_open(); + } + +protected: +#ifdef BOOST_CLASSIC_IOSTREAMS + typedef std::ifstream stream_t; +#else + typedef std::basic_ifstream<CharT,std::char_traits<CharT> > stream_t; +#endif + + // Data members + stream_t m_stream; +}; + +} // namespace ut_detail + +// ************************************************************************** // +// ************** basic_ifstream_line_iterator ************** // +// ************************************************************************** // + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable: 4355) // 'this' : used in base member initializer list +#endif + +template<typename CharT> +class basic_ifstream_line_iterator : ut_detail::ifstream_holder<CharT>, public basic_istream_line_iterator<CharT> +{ +public: + basic_ifstream_line_iterator( basic_cstring<CharT const> file_name, CharT delimeter ) + : ut_detail::ifstream_holder<CharT>( file_name ), basic_istream_line_iterator<CharT>( this->m_stream, delimeter ) {} + + explicit basic_ifstream_line_iterator( basic_cstring<CharT const> file_name = basic_cstring<CharT const>() ) + : ut_detail::ifstream_holder<CharT>( file_name ), basic_istream_line_iterator<CharT>( this->m_stream ) {} +}; + +#ifdef BOOST_MSVC +# pragma warning(default: 4355) +#endif + +typedef basic_ifstream_line_iterator<char> ifstream_line_iterator; +typedef basic_ifstream_line_iterator<wchar_t> wifstream_line_iterator; + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_IFSTREAM_LINE_ITERATOR_HPP_071894GER + diff --git a/boost/test/utils/iterator/input_iterator_facade.hpp b/boost/test/utils/iterator/input_iterator_facade.hpp new file mode 100644 index 0000000000..ec29e21a63 --- /dev/null +++ b/boost/test/utils/iterator/input_iterator_facade.hpp @@ -0,0 +1,109 @@ +// (C) Copyright Gennadiy Rozental 2004-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : Input iterator facade +// *************************************************************************** + +#ifndef BOOST_INPUT_ITERATOR_FACADE_HPP_071894GER +#define BOOST_INPUT_ITERATOR_FACADE_HPP_071894GER + +// Boost +#include <boost/iterator/iterator_facade.hpp> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +// ************************************************************************** // +// ************** input_iterator_core_access ************** // +// ************************************************************************** // + +class input_iterator_core_access +{ +#if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +public: +#else + template <class I, class V, class R, class TC> friend class input_iterator_facade; +#endif + + template <class Facade> + static bool get( Facade& f ) + { + return f.get(); + } + +private: + // objects of this class are useless + input_iterator_core_access(); //undefined +}; + +// ************************************************************************** // +// ************** input_iterator_facade ************** // +// ************************************************************************** // + +template<typename Derived, + typename ValueType, + typename Reference = ValueType const&, + typename Traversal = single_pass_traversal_tag> +class input_iterator_facade : public iterator_facade<Derived,ValueType,Traversal,Reference> +{ +public: + // Constructor + input_iterator_facade() : m_valid( false ), m_value() {} + +protected: // provide access to the Derived + void init() + { + m_valid = true; + increment(); + } + + // Data members + mutable bool m_valid; + ValueType m_value; + +private: + friend class boost::iterator_core_access; + + // iterator facade interface implementation + void increment() + { + // we make post-end incrementation indefinetly safe + if( m_valid ) + m_valid = input_iterator_core_access::get( *static_cast<Derived*>(this) ); + } + Reference dereference() const + { + return m_value; + } + + // iterator facade interface implementation + bool equal( input_iterator_facade const& rhs ) const + { + // two invalid iterator equals, inequal otherwise + return !m_valid && !rhs.m_valid; + } +}; + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_INPUT_ITERATOR_FACADE_HPP_071894GER + diff --git a/boost/test/utils/iterator/istream_line_iterator.hpp b/boost/test/utils/iterator/istream_line_iterator.hpp new file mode 100644 index 0000000000..d58a2cebbb --- /dev/null +++ b/boost/test/utils/iterator/istream_line_iterator.hpp @@ -0,0 +1,93 @@ +// (C) Copyright Gennadiy Rozental 2004-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : +// *************************************************************************** + +#ifndef BOOST_ISTREAM_LINE_ITERATOR_HPP_071894GER +#define BOOST_ISTREAM_LINE_ITERATOR_HPP_071894GER + +// Boost +#include <boost/test/utils/basic_cstring/basic_cstring.hpp> +#include <boost/test/utils/iterator/input_iterator_facade.hpp> + +// STL +#include <iosfwd> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +// ************************************************************************** // +// ************** basic_istream_line_iterator ************** // +// ************************************************************************** // + +// !! Should we support policy based delimitation + +template<typename CharT> +class basic_istream_line_iterator +: public input_iterator_facade<basic_istream_line_iterator<CharT>, + std::basic_string<CharT>, + basic_cstring<CharT const> > { + typedef input_iterator_facade<basic_istream_line_iterator<CharT>, + std::basic_string<CharT>, + basic_cstring<CharT const> > base; +#ifdef BOOST_CLASSIC_IOSTREAMS + typedef std::istream istream_type; +#else + typedef std::basic_istream<CharT> istream_type; +#endif +public: + // Constructors + basic_istream_line_iterator() {} + basic_istream_line_iterator( istream_type& input, CharT delimeter ) + : m_input_stream( &input ), m_delimeter( delimeter ) + { + this->init(); + } + explicit basic_istream_line_iterator( istream_type& input ) + : m_input_stream( &input ) + , m_delimeter( input.widen( '\n' ) ) + { + this->init(); + } + +private: + friend class input_iterator_core_access; + + // increment implementation + bool get() + { + return !!std::getline( *m_input_stream, this->m_value, m_delimeter ); + } + + // Data members + istream_type* m_input_stream; + CharT m_delimeter; +}; + +typedef basic_istream_line_iterator<char> istream_line_iterator; +typedef basic_istream_line_iterator<wchar_t> wistream_line_iterator; + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_ISTREAM_LINE_ITERATOR_HPP_071894GER + diff --git a/boost/test/utils/iterator/token_iterator.hpp b/boost/test/utils/iterator/token_iterator.hpp new file mode 100644 index 0000000000..c303ab7e71 --- /dev/null +++ b/boost/test/utils/iterator/token_iterator.hpp @@ -0,0 +1,418 @@ +// (C) Copyright Gennadiy Rozental 2004-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : token iterator for string and range tokenization +// *************************************************************************** + +#ifndef BOOST_TOKEN_ITERATOR_HPP_071894GER +#define BOOST_TOKEN_ITERATOR_HPP_071894GER + +// Boost +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> + +#include <boost/iterator/iterator_categories.hpp> +#include <boost/iterator/iterator_traits.hpp> + +#include <boost/test/utils/iterator/input_iterator_facade.hpp> +#include <boost/test/utils/basic_cstring/basic_cstring.hpp> +#include <boost/test/utils/named_params.hpp> +#include <boost/test/utils/foreach.hpp> + +// STL +#include <iosfwd> +#include <cctype> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ using ::ispunct; using ::isspace; } +#endif + +namespace boost { + +namespace unit_test { + +// ************************************************************************** // +// ************** ti_delimeter_type ************** // +// ************************************************************************** // + +enum ti_delimeter_type { + dt_char, // character is delimeter if it among explicit list of some characters + dt_ispunct, // character is delimeter if it satisfies ispunct functor + dt_isspace, // character is delimeter if it satisfies isspace functor + dt_none // no character is delimeter +}; + +namespace ut_detail { + +// ************************************************************************** // +// ************** default_char_compare ************** // +// ************************************************************************** // + +template<typename CharT> +class default_char_compare { +public: + bool operator()( CharT c1, CharT c2 ) + { +#ifdef BOOST_CLASSIC_IOSTREAMS + return std::string_char_traits<CharT>::eq( c1, c2 ); +#else + return std::char_traits<CharT>::eq( c1, c2 ); +#endif + } +}; + +// ************************************************************************** // +// ************** delim_policy ************** // +// ************************************************************************** // + +template<typename CharT,typename CharCompare> +class delim_policy { + typedef basic_cstring<CharT const> cstring; +public: + // Constructor + explicit delim_policy( ti_delimeter_type t = dt_char, cstring d = cstring() ) + : m_type( t ) + { + set_delimeters( d ); + } + + void set_delimeters( ti_delimeter_type t ) { m_type = t; } + template<typename Src> + void set_delimeters( Src d ) + { + nfp::optionally_assign( m_delimeters, d ); + + if( !m_delimeters.is_empty() ) + m_type = dt_char; + } + + bool operator()( CharT c ) + { + switch( m_type ) { + case dt_char: { + BOOST_TEST_FOREACH( CharT, delim, m_delimeters ) + if( CharCompare()( delim, c ) ) + return true; + + return false; + } + case dt_ispunct: + return (std::ispunct)( c ) != 0; + case dt_isspace: + return (std::isspace)( c ) != 0; + case dt_none: + return false; + } + + return false; + } + +private: + // Data members + cstring m_delimeters; + ti_delimeter_type m_type; +}; + +// ************************************************************************** // +// ************** token_assigner ************** // +// ************************************************************************** // + +template<typename TraversalTag> +struct token_assigner { +#if BOOST_WORKAROUND( BOOST_DINKUMWARE_STDLIB, < 306 ) + template<typename Iterator, typename C, typename T> + static void assign( Iterator b, Iterator e, std::basic_string<C,T>& t ) + { for( ; b != e; ++b ) t += *b; } + + template<typename Iterator, typename C> + static void assign( Iterator b, Iterator e, basic_cstring<C>& t ) { t.assign( b, e ); } +#else + template<typename Iterator, typename Token> + static void assign( Iterator b, Iterator e, Token& t ) { t.assign( b, e ); } +#endif + template<typename Iterator, typename Token> + static void append_move( Iterator& b, Token& ) { ++b; } +}; + +//____________________________________________________________________________// + +template<> +struct token_assigner<single_pass_traversal_tag> { + template<typename Iterator, typename Token> + static void assign( Iterator b, Iterator e, Token& t ) {} + + template<typename Iterator, typename Token> + static void append_move( Iterator& b, Token& t ) { t += *b; ++b; } +}; + +} // namespace ut_detail + +// ************************************************************************** // +// ************** modifiers ************** // +// ************************************************************************** // + +namespace { +nfp::keyword<struct dropped_delimeters_t > dropped_delimeters; +nfp::keyword<struct kept_delimeters_t > kept_delimeters; +nfp::typed_keyword<bool,struct keep_empty_tokens_t > keep_empty_tokens; +nfp::typed_keyword<std::size_t,struct max_tokens_t > max_tokens; +} + +// ************************************************************************** // +// ************** token_iterator_base ************** // +// ************************************************************************** // + +template<typename Derived, + typename CharT, + typename CharCompare = ut_detail::default_char_compare<CharT>, + typename ValueType = basic_cstring<CharT const>, + typename Reference = basic_cstring<CharT const>, + typename Traversal = forward_traversal_tag> +class token_iterator_base +: public input_iterator_facade<Derived,ValueType,Reference,Traversal> { + typedef basic_cstring<CharT const> cstring; + typedef ut_detail::delim_policy<CharT,CharCompare> delim_policy; + typedef input_iterator_facade<Derived,ValueType,Reference,Traversal> base; + +protected: + // Constructor + explicit token_iterator_base() + : m_is_dropped( dt_isspace ) + , m_is_kept( dt_ispunct ) + , m_keep_empty_tokens( false ) + , m_tokens_left( static_cast<std::size_t>(-1) ) + , m_token_produced( false ) + { + } + + template<typename Modifier> + void + apply_modifier( Modifier const& m ) + { + if( m.has( dropped_delimeters ) ) + m_is_dropped.set_delimeters( m[dropped_delimeters] ); + + if( m.has( kept_delimeters ) ) + m_is_kept.set_delimeters( m[kept_delimeters] ); + + if( m.has( keep_empty_tokens ) ) + m_keep_empty_tokens = true; + + nfp::optionally_assign( m_tokens_left, m, max_tokens ); + } + + template<typename Iter> + bool get( Iter& begin, Iter end ) + { + typedef ut_detail::token_assigner<BOOST_DEDUCED_TYPENAME iterator_traversal<Iter>::type> Assigner; + Iter check_point; + + this->m_value.clear(); + + if( !m_keep_empty_tokens ) { + while( begin != end && m_is_dropped( *begin ) ) + ++begin; + + if( begin == end ) + return false; + + check_point = begin; + + if( m_tokens_left == 1 ) + while( begin != end ) + Assigner::append_move( begin, this->m_value ); + else if( m_is_kept( *begin ) ) + Assigner::append_move( begin, this->m_value ); + else + while( begin != end && !m_is_dropped( *begin ) && !m_is_kept( *begin ) ) + Assigner::append_move( begin, this->m_value ); + + --m_tokens_left; + } + else { // m_keep_empty_tokens is true + check_point = begin; + + if( begin == end ) { + if( m_token_produced ) + return false; + + m_token_produced = true; + } + if( m_is_kept( *begin ) ) { + if( m_token_produced ) + Assigner::append_move( begin, this->m_value ); + + m_token_produced = !m_token_produced; + } + else if( !m_token_produced && m_is_dropped( *begin ) ) + m_token_produced = true; + else { + if( m_is_dropped( *begin ) ) + check_point = ++begin; + + while( begin != end && !m_is_dropped( *begin ) && !m_is_kept( *begin ) ) + Assigner::append_move( begin, this->m_value ); + + m_token_produced = true; + } + } + + Assigner::assign( check_point, begin, this->m_value ); + + return true; + } + +private: + // Data members + delim_policy m_is_dropped; + delim_policy m_is_kept; + bool m_keep_empty_tokens; + std::size_t m_tokens_left; + bool m_token_produced; +}; + +// ************************************************************************** // +// ************** basic_string_token_iterator ************** // +// ************************************************************************** // + +template<typename CharT, + typename CharCompare = ut_detail::default_char_compare<CharT> > +class basic_string_token_iterator +: public token_iterator_base<basic_string_token_iterator<CharT,CharCompare>,CharT,CharCompare> { + typedef basic_cstring<CharT const> cstring; + typedef token_iterator_base<basic_string_token_iterator<CharT,CharCompare>,CharT,CharCompare> base; +public: + explicit basic_string_token_iterator() {} + explicit basic_string_token_iterator( cstring src ) + : m_src( src ) + { + this->init(); + } + + template<typename Src, typename Modifier> + basic_string_token_iterator( Src src, Modifier const& m ) + : m_src( src ) + { + this->apply_modifier( m ); + + this->init(); + } + +private: + friend class input_iterator_core_access; + + // input iterator implementation + bool get() + { + typename cstring::iterator begin = m_src.begin(); + bool res = base::get( begin, m_src.end() ); + + m_src.assign( begin, m_src.end() ); + + return res; + } + + // Data members + cstring m_src; +}; + +typedef basic_string_token_iterator<char> string_token_iterator; +typedef basic_string_token_iterator<wchar_t> wstring_token_iterator; + +// ************************************************************************** // +// ************** range_token_iterator ************** // +// ************************************************************************** // + +template<typename Iter, + typename CharCompare = ut_detail::default_char_compare<BOOST_DEDUCED_TYPENAME iterator_value<Iter>::type>, + typename ValueType = std::basic_string<BOOST_DEDUCED_TYPENAME iterator_value<Iter>::type>, + typename Reference = ValueType const&> +class range_token_iterator +: public token_iterator_base<range_token_iterator<Iter,CharCompare,ValueType,Reference>, + typename iterator_value<Iter>::type,CharCompare,ValueType,Reference> { + typedef basic_cstring<typename ValueType::value_type> cstring; + typedef token_iterator_base<range_token_iterator<Iter,CharCompare,ValueType,Reference>, + typename iterator_value<Iter>::type,CharCompare,ValueType,Reference> base; +public: + explicit range_token_iterator() {} + explicit range_token_iterator( Iter begin, Iter end = Iter() ) + : m_begin( begin ), m_end( end ) + { + this->init(); + } + range_token_iterator( range_token_iterator const& rhs ) + : base( rhs ) + { + if( this->m_valid ) { + m_begin = rhs.m_begin; + m_end = rhs.m_end; + } + } + + template<typename Modifier> + range_token_iterator( Iter begin, Iter end, Modifier const& m ) + : m_begin( begin ), m_end( end ) + { + this->apply_modifier( m ); + + this->init(); + } + +private: + friend class input_iterator_core_access; + + // input iterator implementation + bool get() + { + return base::get( m_begin, m_end ); + } + + // Data members + Iter m_begin; + Iter m_end; +}; + +// ************************************************************************** // +// ************** make_range_token_iterator ************** // +// ************************************************************************** // + +template<typename Iter> +inline range_token_iterator<Iter> +make_range_token_iterator( Iter begin, Iter end = Iter() ) +{ + return range_token_iterator<Iter>( begin, end ); +} + +//____________________________________________________________________________// + +template<typename Iter,typename Modifier> +inline range_token_iterator<Iter> +make_range_token_iterator( Iter begin, Iter end, Modifier const& m ) +{ + return range_token_iterator<Iter>( begin, end, m ); +} + +//____________________________________________________________________________// + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_TOKEN_ITERATOR_HPP_071894GER + diff --git a/boost/test/utils/lazy_ostream.hpp b/boost/test/utils/lazy_ostream.hpp new file mode 100644 index 0000000000..d7d7d6cb10 --- /dev/null +++ b/boost/test/utils/lazy_ostream.hpp @@ -0,0 +1,114 @@ +// (C) Copyright Gennadiy Rozental 2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : contains definition for all test tools in test toolbox +// *************************************************************************** + +#ifndef BOOST_TEST_LAZY_OSTREAM_HPP_070708GER +#define BOOST_TEST_LAZY_OSTREAM_HPP_070708GER + +// Boost.Test +#include <boost/test/detail/config.hpp> + +// STL +#include <iosfwd> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** lazy_ostream ************** // +// ************************************************************************** // + +namespace boost { + +namespace unit_test { + +class lazy_ostream { +public: + static lazy_ostream& instance() { static lazy_ostream inst; return inst; } + + friend std::ostream& operator<<( std::ostream& ostr, lazy_ostream const& o ) { return o( ostr ); } + + // access method + bool empty() const { return m_empty; } + + // actual printing interface; to be accessed only by this class and children + virtual std::ostream& operator()( std::ostream& ostr ) const { return ostr; } +protected: + explicit lazy_ostream( bool empty = true ) : m_empty( empty ) {} + + // protected destructor to make sure right one is called +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) +public: +#endif + BOOST_TEST_PROTECTED_VIRTUAL ~lazy_ostream() {} + +private: + // Data members + bool m_empty; +}; + +//____________________________________________________________________________// + +template<typename T> +class lazy_ostream_impl : public lazy_ostream { +public: + lazy_ostream_impl( lazy_ostream const& prev, T value ) + : lazy_ostream( false ) + , m_prev( prev ) + , m_value( value ) + {} +private: + virtual std::ostream& operator()( std::ostream& ostr ) const + { + return m_prev(ostr) << m_value; + } + + // Data members + lazy_ostream const& m_prev; + T m_value; +}; + +//____________________________________________________________________________// + +template<typename T> +inline lazy_ostream_impl<T const&> +operator<<( lazy_ostream const& prev, T const& v ) +{ + return lazy_ostream_impl<T const&>( prev, v ); +} + +//____________________________________________________________________________// + +#if BOOST_TEST_USE_STD_LOCALE + +template<typename R,typename S> +inline lazy_ostream_impl<R& (BOOST_TEST_CALL_DECL *)(S&)> +operator<<( lazy_ostream const& prev, R& (BOOST_TEST_CALL_DECL *man)(S&) ) +{ + return lazy_ostream_impl<R& (BOOST_TEST_CALL_DECL *)(S&)>( prev, man ); +} + +//____________________________________________________________________________// + +#endif + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_TEST_LAZY_OSTREAM_HPP_070708GER diff --git a/boost/test/utils/named_params.hpp b/boost/test/utils/named_params.hpp new file mode 100644 index 0000000000..f7f8e68d3a --- /dev/null +++ b/boost/test/utils/named_params.hpp @@ -0,0 +1,329 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : facilities for named function parameters support +// *************************************************************************** + +#ifndef BOOST_TEST_NAMED_PARAM_022505GER +#define BOOST_TEST_NAMED_PARAM_022505GER + +// Boost +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> + +// Boost.Test +#include <boost/test/utils/rtti.hpp> +#include <boost/test/utils/assign_op.hpp> + +#include <boost/type_traits/remove_reference.hpp> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace nfp { // named function parameters + +// ************************************************************************** // +// ************** forward declarations ************** // +// ************************************************************************** // + +template<typename T, typename unique_id,typename RefType> struct named_parameter; +template<typename unique_id,bool required> struct keyword; + +namespace nfp_detail { + +template<typename NP1,typename NP2> struct named_parameter_combine; + +// ************************************************************************** // +// ************** access_to_invalid_parameter ************** // +// ************************************************************************** // + +struct access_to_invalid_parameter {}; + +//____________________________________________________________________________// + +inline void +report_access_to_invalid_parameter() +{ + throw access_to_invalid_parameter(); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** nil ************** // +// ************************************************************************** // + +struct nil { + template<typename T> +#if defined(__GNUC__) || defined(__HP_aCC) || defined(__EDG__) || defined(__SUNPRO_CC) + operator T() const +#else + operator T const&() const +#endif + { report_access_to_invalid_parameter(); static T* v = 0; return *v; } + + template<typename T> + T any_cast() const + { report_access_to_invalid_parameter(); static typename remove_reference<T>::type* v = 0; return *v; } + + template<typename Arg1> + nil operator()( Arg1 const& ) + { report_access_to_invalid_parameter(); return nil(); } + + template<typename Arg1,typename Arg2> + nil operator()( Arg1 const&, Arg2 const& ) + { report_access_to_invalid_parameter(); return nil(); } + + template<typename Arg1,typename Arg2,typename Arg3> + nil operator()( Arg1 const&, Arg2 const&, Arg3 const& ) + { report_access_to_invalid_parameter(); return nil(); } + + // Visitation support + template<typename Visitor> + void apply_to( Visitor& V ) const {} + + static nil& inst() { static nil s_inst; return s_inst; } +private: + nil() {} +}; + +// ************************************************************************** // +// ************** named_parameter_base ************** // +// ************************************************************************** // + +template<typename Derived> +struct named_parameter_base { + template<typename NP> + named_parameter_combine<NP,Derived> + operator,( NP const& np ) const { return named_parameter_combine<NP,Derived>( np, *static_cast<Derived const*>(this) ); } +}; + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** named_parameter_combine ************** // +// ************************************************************************** // + +template<typename NP, typename Rest = nil> +struct named_parameter_combine +: Rest +, named_parameter_base<named_parameter_combine<NP,Rest> > { + typedef typename NP::ref_type res_type; + typedef named_parameter_combine<NP,Rest> self_type; + + // Constructor + named_parameter_combine( NP const& np, Rest const& r ) + : Rest( r ) + , m_param( np ) + {} + + // Access methods + res_type operator[]( keyword<typename NP::id,true> kw ) const { return m_param[kw]; } + res_type operator[]( keyword<typename NP::id,false> kw ) const { return m_param[kw]; } + using Rest::operator[]; + + bool has( keyword<typename NP::id,false> kw ) const { return m_param.has( kw ); } + using Rest::has; + + void erase( keyword<typename NP::id,false> kw ) const { m_param.erase( kw ); } + using Rest::erase; + +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) || \ + BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0610)) + template<typename NP> + named_parameter_combine<NP,self_type> operator,( NP const& np ) const + { return named_parameter_combine<NP,self_type>( np, *this ); } +#else + using named_parameter_base<named_parameter_combine<NP,Rest> >::operator,; +#endif + + // Visitation support + template<typename Visitor> + void apply_to( Visitor& V ) const + { + m_param.apply_to( V ); + + Rest::apply_to( V ); + } +private: + // Data members + NP m_param; +}; + +} // namespace nfp_detail + +// ************************************************************************** // +// ************** named_parameter ************** // +// ************************************************************************** // + +template<typename T, typename unique_id,typename ReferenceType=T&> +struct named_parameter +: nfp_detail::named_parameter_base<named_parameter<T, unique_id,ReferenceType> > +{ + typedef nfp_detail::nil nil_t; + typedef T data_type; + typedef ReferenceType ref_type; + typedef unique_id id; + + // Constructor + explicit named_parameter( ref_type v ) + : m_value( v ) + , m_erased( false ) + {} + named_parameter( named_parameter const& np ) + : m_value( np.m_value ) + , m_erased( np.m_erased ) + {} + + // Access methods + ref_type operator[]( keyword<unique_id,true> ) const { return m_erased ? nil_t::inst().template any_cast<ref_type>() : m_value; } + ref_type operator[]( keyword<unique_id,false> ) const { return m_erased ? nil_t::inst().template any_cast<ref_type>() : m_value; } + template<typename UnknownId> + nil_t operator[]( keyword<UnknownId,false> ) const { return nil_t::inst(); } + + bool has( keyword<unique_id,false> ) const { return !m_erased; } + template<typename UnknownId> + bool has( keyword<UnknownId,false> ) const { return false; } + + void erase( keyword<unique_id,false> ) const { m_erased = true; } + template<typename UnknownId> + void erase( keyword<UnknownId,false> ) const {} + + // Visitation support + template<typename Visitor> + void apply_to( Visitor& V ) const + { + V.set_parameter( rtti::type_id<unique_id>(), m_value ); + } + +private: + // Data members + ref_type m_value; + mutable bool m_erased; +}; + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** no_params ************** // +// ************************************************************************** // + +namespace nfp_detail { +typedef named_parameter<char, struct no_params_type_t,char> no_params_type; +} // namespace nfp_detail + +namespace { +nfp_detail::no_params_type no_params( '\0' ); +} // local namespace + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** keyword ************** // +// ************************************************************************** // + +template<typename unique_id, bool required = false> +struct keyword { + typedef unique_id id; + + template<typename T> + named_parameter<T const,unique_id> + operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); } + + template<typename T> + named_parameter<T,unique_id> + operator=( T& t ) const { return named_parameter<T,unique_id>( t ); } + + named_parameter<char const*,unique_id,char const*> + operator=( char const* t ) const { return named_parameter<char const*,unique_id,char const*>( t ); } +}; + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** typed_keyword ************** // +// ************************************************************************** // + +template<typename T, typename unique_id, bool required = false> +struct typed_keyword : keyword<unique_id,required> { + named_parameter<T const,unique_id> + operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); } + + named_parameter<T,unique_id> + operator=( T& t ) const { return named_parameter<T,unique_id>( t ); } +}; + +//____________________________________________________________________________// + +template<typename unique_id> +struct typed_keyword<bool,unique_id,false> +: keyword<unique_id,false> +, named_parameter<bool,unique_id,bool> { + typedef unique_id id; + + typed_keyword() : named_parameter<bool,unique_id,bool>( true ) {} + + named_parameter<bool,unique_id,bool> + operator!() const { return named_parameter<bool,unique_id,bool>( false ); } +}; + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** optionally_assign ************** // +// ************************************************************************** // + +template<typename T> +inline void +optionally_assign( T&, nfp_detail::nil ) +{ + nfp_detail::report_access_to_invalid_parameter(); +} + +//____________________________________________________________________________// + +template<typename T, typename Source> +inline void +#if BOOST_WORKAROUND( __MWERKS__, BOOST_TESTED_AT( 0x3003 ) ) \ + || BOOST_WORKAROUND( __DECCXX_VER, BOOST_TESTED_AT(60590042) ) +optionally_assign( T& target, Source src ) +#else +optionally_assign( T& target, Source const& src ) +#endif +{ + using namespace unit_test; + + assign_op( target, src, static_cast<int>(0) ); +} + +//____________________________________________________________________________// + +template<typename T, typename Params, typename Keyword> +inline void +optionally_assign( T& target, Params const& p, Keyword k ) +{ + if( p.has(k) ) + optionally_assign( target, p[k] ); +} + +//____________________________________________________________________________// + +} // namespace nfp + +} // namespace boost + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_TEST_NAMED_PARAM_022505GER + diff --git a/boost/test/utils/nullstream.hpp b/boost/test/utils/nullstream.hpp new file mode 100644 index 0000000000..6bec51bedc --- /dev/null +++ b/boost/test/utils/nullstream.hpp @@ -0,0 +1,100 @@ +// (C) Copyright Gennadiy Rozental 2002-2008. +// (C) Copyright Daryle Walker 2000-2001. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : simulate /dev/null stream +// *************************************************************************** + +#ifndef BOOST_NULLSTREAM_HPP_071894GER +#define BOOST_NULLSTREAM_HPP_071894GER + +#include <ostream> // for std::basic_ostream +#include <streambuf> // for std::basic_streambuf +#include <string> // for std::char_traits + +#include <boost/utility/base_from_member.hpp> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +// ************************************************************************** // +// ************** basic_nullbuf ************** // +// ************************************************************************** // +// Class for a buffer that reads nothing and writes to nothing. +// Idea from an Usenet post by Tom <the_wid@my-deja.com> at +// 27 Oct 2000 14:06:21 GMT on comp.lang.c++. + +template<typename CharType, class CharTraits = ::std::char_traits<CharType> > +class basic_nullbuf : public ::std::basic_streambuf<CharType, CharTraits> { + typedef ::std::basic_streambuf<CharType, CharTraits> base_type; +public: + // Types + typedef typename base_type::char_type char_type; + typedef typename base_type::traits_type traits_type; + typedef typename base_type::int_type int_type; + typedef typename base_type::pos_type pos_type; + typedef typename base_type::off_type off_type; + + // Use automatic default constructor and destructor + +protected: + // The default implementations of the miscellaneous virtual + // member functions are sufficient. + + // The default implementations of the input & putback virtual + // member functions, being nowhere but EOF, are sufficient. + + // The output virtual member functions need to be changed to + // accept anything without any problems, instead of being at EOF. + virtual ::std::streamsize xsputn( char_type const* /*s*/, ::std::streamsize n ) { return n; } // "s" is unused + virtual int_type overflow( int_type c = traits_type::eof() ) { return traits_type::not_eof( c ); } +}; + +typedef basic_nullbuf<char> nullbuf; +typedef basic_nullbuf<wchar_t> wnullbuf; + +// ************************************************************************** // +// ************** basic_onullstream ************** // +// ************************************************************************** // +// Output streams based on basic_nullbuf. + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable: 4355) // 'this' : used in base member initializer list +#endif + +template< typename CharType, class CharTraits = ::std::char_traits<CharType> > +class basic_onullstream : private boost::base_from_member<basic_nullbuf<CharType, CharTraits> > + , public ::std::basic_ostream<CharType, CharTraits> { + typedef boost::base_from_member<basic_nullbuf<CharType, CharTraits> > pbase_type; + typedef ::std::basic_ostream<CharType, CharTraits> base_type; +public: + // Constructor + basic_onullstream() : pbase_type(), base_type( &this->pbase_type::member ) {} +}; + +#ifdef BOOST_MSVC +# pragma warning(default: 4355) +#endif + +typedef basic_onullstream<char> onullstream; +typedef basic_onullstream<wchar_t> wonullstream; + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_NULLSTREAM_HPP_071894GER diff --git a/boost/test/utils/rtti.hpp b/boost/test/utils/rtti.hpp new file mode 100644 index 0000000000..655222de79 --- /dev/null +++ b/boost/test/utils/rtti.hpp @@ -0,0 +1,64 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : simple facilities for accessing type information at runtime +// *************************************************************************** + +#ifndef BOOST_TEST_RTTI_HPP_062604GER +#define BOOST_TEST_RTTI_HPP_062604GER + +#include <cstddef> + +namespace boost { + +namespace rtti { + +// ************************************************************************** // +// ************** rtti::type_id ************** // +// ************************************************************************** // + +typedef std::ptrdiff_t id_t; + +namespace rtti_detail { + +template<typename T> +struct rttid_holder { + static id_t id() { return reinterpret_cast<id_t>( &inst() ); } + +private: + struct rttid {}; + + static rttid const& inst() { static rttid s_inst; return s_inst; } +}; + +} // namespace rtti_detail + +//____________________________________________________________________________// + +template<typename T> +inline id_t +type_id() +{ + return rtti_detail::rttid_holder<T>::id(); +} + +//____________________________________________________________________________// + +#define BOOST_RTTI_SWITCH( type_id_ ) if( ::boost::rtti::id_t switch_by_id = type_id_ ) +#define BOOST_RTTI_CASE( type ) if( switch_by_id == ::boost::rtti::type_id<type>() ) + +//____________________________________________________________________________// + +} // namespace rtti + +} // namespace boost + +#endif // BOOST_RT_RTTI_HPP_062604GER diff --git a/boost/test/utils/runtime/argument.hpp b/boost/test/utils/runtime/argument.hpp new file mode 100644 index 0000000000..d22745cb65 --- /dev/null +++ b/boost/test/utils/runtime/argument.hpp @@ -0,0 +1,112 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 57992 $ +// +// Description : model of actual argument (both typed and abstract interface) +// *************************************************************************** + +#ifndef BOOST_RT_ARGUMENT_HPP_062604GER +#define BOOST_RT_ARGUMENT_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> +#include <boost/test/utils/runtime/fwd.hpp> +#include <boost/test/utils/runtime/validation.hpp> + +// Boost.Test +#include <boost/test/utils/class_properties.hpp> +#include <boost/test/utils/rtti.hpp> + +// STL +#include <cassert> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +// ************************************************************************** // +// ************** runtime::argument ************** // +// ************************************************************************** // + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4244) +#endif + +class argument { +public: + // Constructor + argument( parameter const& p, rtti::id_t value_type ) + : p_formal_parameter( p ) + , p_value_type( value_type ) + {} + + // Destructor + virtual ~argument() {} + + // Public properties + unit_test::readonly_property<parameter const&> p_formal_parameter; + unit_test::readonly_property<rtti::id_t> p_value_type; +}; + +// ************************************************************************** // +// ************** runtime::typed_argument ************** // +// ************************************************************************** // + +template<typename T> +class typed_argument : public argument { +public: + // Constructor + explicit typed_argument( parameter const& p ) + : argument( p, rtti::type_id<T>() ) + {} + typed_argument( parameter const& p, T const& t ) + : argument( p, rtti::type_id<T>() ) + , p_value( t ) + {} + + unit_test::readwrite_property<T> p_value; +}; + +// ************************************************************************** // +// ************** runtime::arg_value ************** // +// ************************************************************************** // + +template<typename T> +inline T const& +arg_value( argument const& arg_ ) +{ + assert( arg_.p_value_type == rtti::type_id<T>() ); // detect logic error + + return static_cast<typed_argument<T> const&>( arg_ ).p_value.value; +} + +//____________________________________________________________________________// + +template<typename T> +inline T& +arg_value( argument& arg_ ) +{ + assert( arg_.p_value_type == rtti::type_id<T>() ); // detect logic error + + return static_cast<typed_argument<T>&>( arg_ ).p_value.value; +} + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +//____________________________________________________________________________// + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_ARGUMENT_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/argument_factory.hpp b/boost/test/utils/runtime/cla/argument_factory.hpp new file mode 100644 index 0000000000..1117066993 --- /dev/null +++ b/boost/test/utils/runtime/cla/argument_factory.hpp @@ -0,0 +1,218 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 57992 $ +// +// Description : generic typed_argument_factory implementation +// *************************************************************************** + +#ifndef BOOST_RT_CLA_ARGUMENT_FACTORY_HPP_062604GER +#define BOOST_RT_CLA_ARGUMENT_FACTORY_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/fwd.hpp> +#include <boost/test/utils/runtime/validation.hpp> +#include <boost/test/utils/runtime/argument.hpp> +#include <boost/test/utils/runtime/trace.hpp> +#include <boost/test/utils/runtime/interpret_argument_value.hpp> + +#include <boost/test/utils/runtime/cla/fwd.hpp> +#include <boost/test/utils/runtime/cla/value_generator.hpp> +#include <boost/test/utils/runtime/cla/value_handler.hpp> +#include <boost/test/utils/runtime/cla/validation.hpp> +#include <boost/test/utils/runtime/cla/argv_traverser.hpp> +#include <boost/test/utils/runtime/cla/detail/argument_value_usage.hpp> + +#include <boost/test/utils/runtime/cla/iface/argument_factory.hpp> + +// Boost.Test +#include <boost/test/utils/callback.hpp> + +// Boost +#include <boost/optional.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** default_value_interpreter ************** // +// ************************************************************************** // + +namespace rt_cla_detail { + +struct default_value_interpreter { + template<typename T> + void operator()( argv_traverser& tr, boost::optional<T>& value ) + { + if( interpret_argument_value( tr.token(), value, 0 ) ) + tr.next_token(); + } +}; + +} // namespace rt_cla_detail + +// ************************************************************************** // +// ************** typed_argument_factory ************** // +// ************************************************************************** // + +template<typename T> +struct typed_argument_factory : public argument_factory { + // Constructor + typed_argument_factory() + : m_value_interpreter( rt_cla_detail::default_value_interpreter() ) + {} + BOOST_RT_PARAM_UNNEEDED_VIRTUAL ~typed_argument_factory() {} + + // properties modification + template<typename Modifier> + void accept_modifier( Modifier const& m ) + { + optionally_assign( m_value_handler, m, handler ); + optionally_assign( m_value_interpreter, m, interpreter ); + + if( m.has( default_value ) ) { + BOOST_RT_PARAM_VALIDATE_LOGIC( !m_value_generator, + BOOST_RT_PARAM_LITERAL( "multiple value generators for parameter" ) ); + + T const& dv_ref = m[default_value]; + m_value_generator = rt_cla_detail::const_generator<T>( dv_ref ); + } + + if( m.has( default_refer_to ) ) { + BOOST_RT_PARAM_VALIDATE_LOGIC( !m_value_generator, + BOOST_RT_PARAM_LITERAL( "multiple value generators for parameter" ) ); + + cstring ref_id = m[default_refer_to]; + m_value_generator = rt_cla_detail::ref_generator<T>( ref_id ); + } + + if( m.has( assign_to ) ) { + BOOST_RT_PARAM_VALIDATE_LOGIC( !m_value_handler, + BOOST_RT_PARAM_LITERAL( "multiple value handlers for parameter" ) ); + + m_value_handler = rt_cla_detail::assigner<T>( m[assign_to] ); + } + } + + // Argument factory implementation + virtual argument_ptr produce_using( parameter& p, argv_traverser& tr ); + virtual argument_ptr produce_using( parameter& p, parser const& ); + virtual void argument_usage_info( format_stream& fs ); + +// !! private? + // Data members + unit_test::callback2<parameter const&,T&> m_value_handler; + unit_test::callback2<parser const&,boost::optional<T>&> m_value_generator; + unit_test::callback2<argv_traverser&,boost::optional<T>&> m_value_interpreter; +}; + +//____________________________________________________________________________// + +template<typename T> +inline argument_ptr +typed_argument_factory<T>::produce_using( parameter& p, argv_traverser& tr ) +{ + boost::optional<T> value; + + try { + m_value_interpreter( tr, value ); + } + catch( ... ) { // !! should we do that? + BOOST_RT_PARAM_TRACE( "Fail to parse argument value" ); + + if( !p.p_optional_value ) + throw; + } + + argument_ptr actual_arg = p.actual_argument(); + + BOOST_RT_CLA_VALIDATE_INPUT( !!value || p.p_optional_value, tr, + BOOST_RT_PARAM_LITERAL( "Argument value missing for parameter " ) << p.id_2_report() ); + + BOOST_RT_CLA_VALIDATE_INPUT( !actual_arg || p.p_multiplicable, tr, + BOOST_RT_PARAM_LITERAL( "Unexpected repetition of the parameter " ) << p.id_2_report() ); + + if( !!value && !!m_value_handler ) + m_value_handler( p, *value ); + + if( !p.p_multiplicable ) + actual_arg.reset( p.p_optional_value && (rtti::type_id<T>() != rtti::type_id<bool>()) + ? static_cast<argument*>(new typed_argument<boost::optional<T> >( p, value )) + : static_cast<argument*>(new typed_argument<T>( p, *value )) ); + else { + typedef std::list<boost::optional<T> > optional_list; + + if( !actual_arg ) + actual_arg.reset( p.p_optional_value + ? static_cast<argument*>(new typed_argument<optional_list>( p )) + : static_cast<argument*>(new typed_argument<std::list<T> >( p )) ); + + if( p.p_optional_value ) { + optional_list& values = arg_value<optional_list>( *actual_arg ); + + values.push_back( value ); + } + else { + std::list<T>& values = arg_value<std::list<T> >( *actual_arg ); + + values.push_back( *value ); + } + } + + return actual_arg; +} + +//____________________________________________________________________________// + +template<typename T> +inline argument_ptr +typed_argument_factory<T>::produce_using( parameter& p, parser const& pa ) +{ + argument_ptr actual_arg; + + if( !m_value_generator ) + return actual_arg; + + boost::optional<T> value; + m_value_generator( pa, value ); + + if( !value ) + return actual_arg; + + if( !!m_value_handler ) + m_value_handler( p, *value ); + + actual_arg.reset( new typed_argument<T>( p, *value ) ); + + return actual_arg; +} + +//____________________________________________________________________________// + +template<typename T> +inline void +typed_argument_factory<T>::argument_usage_info( format_stream& fs ) +{ + rt_cla_detail::argument_value_usage( fs, 0, reinterpret_cast<T*>(0) ); +} + +//____________________________________________________________________________// + +} // namespace boost + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace cla + +#endif // BOOST_RT_CLA_ARGUMENT_FACTORY_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/argv_traverser.cpp b/boost/test/utils/runtime/cla/argv_traverser.cpp new file mode 100644 index 0000000000..f64305dc59 --- /dev/null +++ b/boost/test/utils/runtime/cla/argv_traverser.cpp @@ -0,0 +1,16 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : offline implementation for argc/argv traverser +// *************************************************************************** + +#define BOOST_RT_PARAM_INLINE +#include <boost/test/utils/runtime/cla/argv_traverser.ipp> diff --git a/boost/test/utils/runtime/cla/argv_traverser.hpp b/boost/test/utils/runtime/cla/argv_traverser.hpp new file mode 100644 index 0000000000..c1fb95ef20 --- /dev/null +++ b/boost/test/utils/runtime/cla/argv_traverser.hpp @@ -0,0 +1,98 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 57992 $ +// +// Description : defines facility to hide input traversing details +// *************************************************************************** + +#ifndef BOOST_RT_CLA_ARGV_TRAVERSER_HPP_062604GER +#define BOOST_RT_CLA_ARGV_TRAVERSER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +// Boost.Test +#include <boost/test/utils/class_properties.hpp> + +// Boost +#include <boost/noncopyable.hpp> +#include <boost/shared_array.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** runtime::cla::argv_traverser ************** // +// ************************************************************************** // + +class argv_traverser : noncopyable { + class parser; +public: + // Constructor + argv_traverser(); + + // public_properties + unit_test::readwrite_property<bool> p_ignore_mismatch; + unit_test::readwrite_property<char_type> p_separator; + + // argc+argv <-> internal buffer exchange + void init( int argc, char_type** argv ); + void remainder( int& argc, char_type** argv ); + + // token based parsing + cstring token() const; + void next_token(); + + // whole input parsing + cstring input() const; + void trim( std::size_t size ); + bool match_front( cstring ); + bool match_front( char_type c ); + bool eoi() const; + + // transaction logic support + void commit(); + void rollback(); + + // current position access; used to save some reference points in input + std::size_t input_pos() const; + + // returns true if mismatch detected during input parsing handled successfully + bool handle_mismatch(); + +private: + // Data members + dstring m_buffer; + cstring m_work_buffer; + + cstring m_token; + cstring::iterator m_commited_end; + + shared_array<char_type> m_remainder; + std::size_t m_remainder_size; +}; + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#ifndef BOOST_RT_PARAM_OFFLINE + +# define BOOST_RT_PARAM_INLINE inline +# include <boost/test/utils/runtime/cla/argv_traverser.ipp> + +#endif + +#endif // BOOST_RT_CLA_ARGV_TRAVERSER_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/argv_traverser.ipp b/boost/test/utils/runtime/cla/argv_traverser.ipp new file mode 100644 index 0000000000..d7bd6c0ecc --- /dev/null +++ b/boost/test/utils/runtime/cla/argv_traverser.ipp @@ -0,0 +1,209 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : implements facility to hide input traversing details +// *************************************************************************** + +#ifndef BOOST_RT_CLA_ARGV_TRAVERSER_IPP_070604GER +#define BOOST_RT_CLA_ARGV_TRAVERSER_IPP_070604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/trace.hpp> + +#include <boost/test/utils/runtime/cla/argv_traverser.hpp> + +// STL +#include <memory> +#include <cstring> + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::memcpy; } +#endif + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** runtime::cla::argv_traverser ************** // +// ************************************************************************** // + +BOOST_RT_PARAM_INLINE +argv_traverser::argv_traverser() +: p_ignore_mismatch( false ), p_separator( BOOST_RT_PARAM_LITERAL( ' ' ) ) +{ +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE void +argv_traverser::init( int argc, char_type** argv ) +{ + for( int index = 1; index < argc; ++index ) { + m_buffer += argv[index]; + if( index != argc-1 ) + m_buffer += BOOST_RT_PARAM_LITERAL( ' ' ); + } + + m_remainder.reset( new char_type[m_buffer.size()+1] ); + m_remainder_size = 0; + m_work_buffer = m_buffer; + m_commited_end = m_work_buffer.begin(); + + BOOST_RT_PARAM_TRACE( "Input buffer: " << m_buffer ); + + next_token(); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE void +argv_traverser::remainder( int& argc, char_type** argv ) +{ + argc = 1; + std::size_t pos = 0; + while(pos < m_remainder_size ) { + argv[argc++] = m_remainder.get() + pos; + + pos = std::find( m_remainder.get() + pos, m_remainder.get() + m_remainder_size, + BOOST_RT_PARAM_LITERAL( ' ' ) ) - m_remainder.get(); + m_remainder[pos++] = BOOST_RT_PARAM_LITERAL( '\0' ); + } +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE cstring +argv_traverser::token() const +{ + return m_token; +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE void +argv_traverser::next_token() +{ + if( m_work_buffer.is_empty() ) + return; + + m_work_buffer.trim_left( m_token.size() ); // skip remainder of current token + + if( m_work_buffer.size() != m_buffer.size() ) // !! is there a better way to identify first token + m_work_buffer.trim_left( 1 ); // skip separator if not first token; + + m_token.assign( m_work_buffer.begin(), + std::find( m_work_buffer.begin(), m_work_buffer.end(), p_separator ) ); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE cstring +argv_traverser::input() const +{ + return m_work_buffer; +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE void +argv_traverser::trim( std::size_t size ) +{ + m_work_buffer.trim_left( size ); + + if( size <= m_token.size() ) + m_token.trim_left( size ); + else { + m_token.assign( m_work_buffer.begin(), + std::find( m_work_buffer.begin(), m_work_buffer.end(), p_separator ) ); + } +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE bool +argv_traverser::match_front( cstring str ) +{ + return m_work_buffer.size() < str.size() ? false : m_work_buffer.substr( 0, str.size() ) == str; +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE bool +argv_traverser::match_front( char_type c ) +{ + return first_char( m_work_buffer ) == c; +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE bool +argv_traverser::eoi() const +{ + return m_work_buffer.is_empty(); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE void +argv_traverser::commit() +{ + m_commited_end = m_work_buffer.begin(); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE void +argv_traverser::rollback() +{ + m_work_buffer.assign( m_commited_end, m_work_buffer.end() ); + m_token.assign( m_work_buffer.begin(), + std::find( m_work_buffer.begin(), m_work_buffer.end(), p_separator ) ); + +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE std::size_t +argv_traverser::input_pos() const +{ + return m_work_buffer.begin() - m_commited_end; +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE bool +argv_traverser::handle_mismatch() +{ + if( !p_ignore_mismatch ) + return false; + + std::memcpy( m_remainder.get() + m_remainder_size, token().begin(), token().size() ); + m_remainder_size += token().size(); + m_remainder[m_remainder_size++] = p_separator; + + next_token(); + commit(); + + return true; +} + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_ARGV_TRAVERSER_IPP_070604GER diff --git a/boost/test/utils/runtime/cla/basic_parameter.hpp b/boost/test/utils/runtime/cla/basic_parameter.hpp new file mode 100644 index 0000000000..e7e084cd26 --- /dev/null +++ b/boost/test/utils/runtime/cla/basic_parameter.hpp @@ -0,0 +1,85 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : generic custom parameter generator +// *************************************************************************** + +#ifndef BOOST_RT_CLA_BASIC_PARAMETER_HPP_062604GER +#define BOOST_RT_CLA_BASIC_PARAMETER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/typed_parameter.hpp> + +// Boost.Test +#include <boost/test/utils/rtti.hpp> + +// Boost +#include <boost/utility/base_from_member.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** runtime::cla::basic_parameter ************** // +// ************************************************************************** // + +template<typename T, typename IdPolicy> +class basic_parameter : private base_from_member<IdPolicy>, public typed_parameter<T> { +public: + // Constructors + explicit basic_parameter( cstring n ) + : base_from_member<IdPolicy>() + , typed_parameter<T>( base_from_member<IdPolicy>::member ) + { + this->accept_modifier( name = n ); + } + + // parameter properties modification + template<typename Modifier> + void accept_modifier( Modifier const& m ) + { + typed_parameter<T>::accept_modifier( m ); + + base_from_member<IdPolicy>::member.accept_modifier( m ); + } +}; + +//____________________________________________________________________________// + +#define BOOST_RT_CLA_NAMED_PARAM_GENERATORS( param_type ) \ +template<typename T> \ +inline shared_ptr<param_type ## _t<T> > \ +param_type( cstring name = cstring() ) \ +{ \ + return shared_ptr<param_type ## _t<T> >( new param_type ## _t<T>( name ) ); \ +} \ + \ +inline shared_ptr<param_type ## _t<cstring> > \ +param_type( cstring name = cstring() ) \ +{ \ + return shared_ptr<param_type ## _t<cstring> >( new param_type ## _t<cstring>( name ) ); \ +} \ +/**/ + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_BASIC_PARAMETER_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/char_parameter.cpp b/boost/test/utils/runtime/cla/char_parameter.cpp new file mode 100644 index 0000000000..abffa72b84 --- /dev/null +++ b/boost/test/utils/runtime/cla/char_parameter.cpp @@ -0,0 +1,16 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : offline implementation of char parameter +// *************************************************************************** + +#define BOOST_RT_PARAM_INLINE +#include <boost/test/utils/runtime/cla/char_parameter.ipp> diff --git a/boost/test/utils/runtime/cla/char_parameter.hpp b/boost/test/utils/runtime/cla/char_parameter.hpp new file mode 100644 index 0000000000..3e9b2d8427 --- /dev/null +++ b/boost/test/utils/runtime/cla/char_parameter.hpp @@ -0,0 +1,98 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : defines model of parameter with single char name +// *************************************************************************** + +#ifndef BOOST_RT_CLA_CHAR_PARAMETER_HPP_062604GER +#define BOOST_RT_CLA_CHAR_PARAMETER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> +#include <boost/test/utils/runtime/validation.hpp> + +#include <boost/test/utils/runtime/cla/basic_parameter.hpp> +#include <boost/test/utils/runtime/cla/id_policy.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** char_name_policy ************** // +// ************************************************************************** // + +class char_name_policy : public basic_naming_policy { +public: + // Constructor + char_name_policy(); + BOOST_RT_PARAM_UNNEEDED_VIRTUAL ~char_name_policy() {} + + // policy interface + virtual bool conflict_with( identification_policy const& ) const; + + // Accept modifier + template<typename Modifier> + void accept_modifier( Modifier const& m ) + { + basic_naming_policy::accept_modifier( m ); + + BOOST_RT_PARAM_VALIDATE_LOGIC( p_name->size() <= 1, "Invalid parameter name " << p_name ); + } +}; + +// ************************************************************************** // +// ************** runtime::cla::char_parameter ************** // +// ************************************************************************** // + +template<typename T> +class char_parameter_t : public basic_parameter<T,char_name_policy> { + typedef basic_parameter<T,char_name_policy> base; +public: + // Constructors + explicit char_parameter_t( char_type name ) : base( cstring( &name, 1 ) ) {} +}; + +//____________________________________________________________________________// + +template<typename T> +inline shared_ptr<char_parameter_t<T> > +char_parameter( char_type name ) +{ + return shared_ptr<char_parameter_t<T> >( new char_parameter_t<T>( name ) ); +} + +//____________________________________________________________________________// + +inline shared_ptr<char_parameter_t<cstring> > +char_parameter( char_type name ) +{ + return shared_ptr<char_parameter_t<cstring> >( new char_parameter_t<cstring>( name ) ); +} + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#ifndef BOOST_RT_PARAM_OFFLINE + +# define BOOST_RT_PARAM_INLINE inline +# include <boost/test/utils/runtime/cla/char_parameter.ipp> + +#endif + +#endif // BOOST_RT_CLA_CHAR_PARAMETER_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/char_parameter.ipp b/boost/test/utils/runtime/cla/char_parameter.ipp new file mode 100644 index 0000000000..cc9e923a53 --- /dev/null +++ b/boost/test/utils/runtime/cla/char_parameter.ipp @@ -0,0 +1,57 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : implements model of parameter with single char name +// *************************************************************************** + +#ifndef BOOST_RT_CLA_CHAR_PARAMETER_IPP_062904GER +#define BOOST_RT_CLA_CHAR_PARAMETER_IPP_062904GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/char_parameter.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** char_name_policy ************** // +// ************************************************************************** // + +BOOST_RT_PARAM_INLINE +char_name_policy::char_name_policy() +: basic_naming_policy( rtti::type_id<char_name_policy>() ) +{ + assign_op( p_prefix.value, BOOST_RT_PARAM_CSTRING_LITERAL( "-" ), 0 ); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE bool +char_name_policy::conflict_with( identification_policy const& id ) const +{ + return id.p_type_id == p_type_id && + p_name == static_cast<char_name_policy const&>( id ).p_name; +} + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_CHAR_PARAMETER_IPP_062904GER diff --git a/boost/test/utils/runtime/cla/detail/argument_value_usage.hpp b/boost/test/utils/runtime/cla/detail/argument_value_usage.hpp new file mode 100644 index 0000000000..1986b6d25d --- /dev/null +++ b/boost/test/utils/runtime/cla/detail/argument_value_usage.hpp @@ -0,0 +1,82 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied warranty, +// and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for updates, documentation, and revision history. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : argument usage printing helpers +// *************************************************************************** + +#ifndef BOOST_RT_CLA_ARGUMENT_VALUE_USAGE_HPP_062604GER +#define BOOST_RT_CLA_ARGUMENT_VALUE_USAGE_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> +#include <boost/test/utils/runtime/cla/argv_traverser.hpp> + +// Boost.Test +#include <boost/test/utils/basic_cstring/io.hpp> +#include <boost/test/utils/basic_cstring/compare.hpp> + +#include <boost/lexical_cast.hpp> + +// STL +// !! can we eliminate these includes? +#include <list> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +namespace rt_cla_detail { + +// ************************************************************************** // +// ************** argument_value_usage ************** // +// ************************************************************************** // + +// generic case +template<typename T> +inline void +argument_value_usage( format_stream& fs, long, T* = 0 ) +{ + fs << BOOST_RT_PARAM_CSTRING_LITERAL( "<value>" ); +} + +//____________________________________________________________________________// + +// specialization for list of values +template<typename T> +inline void +argument_value_usage( format_stream& fs, int, std::list<T>* = 0 ) +{ + fs << BOOST_RT_PARAM_CSTRING_LITERAL( "(<value1>, ..., <valueN>)" ); +} + +//____________________________________________________________________________// + +// specialization for type bool +inline void +argument_value_usage( format_stream& fs, int, bool* = 0 ) +{ + fs << BOOST_RT_PARAM_CSTRING_LITERAL( "yes|y|no|n" ); +} + +//____________________________________________________________________________// + +} // namespace rt_cla_detail + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_ARGUMENT_VALUE_USAGE_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/dual_name_parameter.cpp b/boost/test/utils/runtime/cla/dual_name_parameter.cpp new file mode 100644 index 0000000000..d594fc3d45 --- /dev/null +++ b/boost/test/utils/runtime/cla/dual_name_parameter.cpp @@ -0,0 +1,16 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : offline implementation of generic parameter with dual naming +// *************************************************************************** + +#define BOOST_RT_PARAM_INLINE +#include <boost/test/utils/runtime/cla/dual_name_parameter.ipp> diff --git a/boost/test/utils/runtime/cla/dual_name_parameter.hpp b/boost/test/utils/runtime/cla/dual_name_parameter.hpp new file mode 100644 index 0000000000..233f63221e --- /dev/null +++ b/boost/test/utils/runtime/cla/dual_name_parameter.hpp @@ -0,0 +1,96 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : defines model of generic parameter with dual naming +// *************************************************************************** + +#ifndef BOOST_RT_CLA_DUAL_NAME_PARAMETER_HPP_062604GER +#define BOOST_RT_CLA_DUAL_NAME_PARAMETER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/named_parameter.hpp> +#include <boost/test/utils/runtime/cla/char_parameter.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** dual_name_policy ************** // +// ************************************************************************** // + +class dual_name_policy : public dual_id_policy<dual_name_policy,string_name_policy,char_name_policy> { +public: + dual_name_policy(); + + // Accept modifier + template<typename Modifier> + void accept_modifier( Modifier const& m ) + { + if( m.has( prefix ) ) { + set_prefix( m[prefix] ); + m.erase( prefix ); + } + + if( m.has( name ) ) { + set_name( m[name] ); + m.erase( name ); + } + + if( m.has( separator ) ) { + set_separator( m[separator] ); + m.erase( separator ); + } + + dual_id_policy<dual_name_policy,string_name_policy,char_name_policy>::accept_modifier( m ); + } +private: + void set_prefix( cstring ); + void set_name( cstring ); + void set_separator( cstring ); +}; + +// ************************************************************************** // +// ************** runtime::cla::dual_name_parameter ************** // +// ************************************************************************** // + +template<typename T> +class dual_name_parameter_t : public basic_parameter<T,dual_name_policy> { + typedef basic_parameter<T,dual_name_policy> base; +public: + // Constructors + explicit dual_name_parameter_t( cstring name ) : base( name ) {} +}; + +//____________________________________________________________________________// + +BOOST_RT_CLA_NAMED_PARAM_GENERATORS( dual_name_parameter ) + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#ifndef BOOST_RT_PARAM_OFFLINE + +# define BOOST_RT_PARAM_INLINE inline +# include <boost/test/utils/runtime/cla/dual_name_parameter.ipp> + +#endif + +#endif // BOOST_RT_CLA_DUAL_NAME_PARAMETER_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/dual_name_parameter.ipp b/boost/test/utils/runtime/cla/dual_name_parameter.ipp new file mode 100644 index 0000000000..f9356bdf80 --- /dev/null +++ b/boost/test/utils/runtime/cla/dual_name_parameter.ipp @@ -0,0 +1,90 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : implements model of generic parameter with dual naming +// *************************************************************************** + +#ifndef BOOST_RT_CLA_DUAL_NAME_PARAMETER_IPP_062904GER +#define BOOST_RT_CLA_DUAL_NAME_PARAMETER_IPP_062904GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> +#include <boost/test/utils/runtime/validation.hpp> + +#include <boost/test/utils/runtime/cla/dual_name_parameter.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** dual_name_policy ************** // +// ************************************************************************** // + +BOOST_RT_PARAM_INLINE +dual_name_policy::dual_name_policy() +{ + m_primary.accept_modifier( prefix = BOOST_RT_PARAM_CSTRING_LITERAL( "--" ) ); + m_secondary.accept_modifier( prefix = BOOST_RT_PARAM_CSTRING_LITERAL( "-" ) ); +} + +//____________________________________________________________________________// + +namespace { + +template<typename K> +inline void +split( string_name_policy& snp, char_name_policy& cnp, cstring src, K const& k ) +{ + cstring::iterator sep = std::find( src.begin(), src.end(), BOOST_RT_PARAM_LITERAL( '|' ) ); + + if( sep != src.begin() ) + snp.accept_modifier( k = cstring( src.begin(), sep ) ); + + if( sep != src.end() ) + cnp.accept_modifier( k = cstring( sep+1, src.end() ) ); +} + +} // local namespace + +BOOST_RT_PARAM_INLINE void +dual_name_policy::set_prefix( cstring src ) +{ + split( m_primary, m_secondary, src, prefix ); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE void +dual_name_policy::set_name( cstring src ) +{ + split( m_primary, m_secondary, src, name ); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE void +dual_name_policy::set_separator( cstring src ) +{ + split( m_primary, m_secondary, src, separator ); +} + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_DUAL_NAME_PARAMETER_IPP_062904GER diff --git a/boost/test/utils/runtime/cla/fwd.hpp b/boost/test/utils/runtime/cla/fwd.hpp new file mode 100644 index 0000000000..66d6efc13b --- /dev/null +++ b/boost/test/utils/runtime/cla/fwd.hpp @@ -0,0 +1,55 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : cla subsystem forward declarations +// *************************************************************************** + +#ifndef BOOST_RT_CLA_FWD_HPP_062604GER +#define BOOST_RT_CLA_FWD_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +// Boost +#include <boost/shared_ptr.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +class parser; +class parameter; +typedef shared_ptr<parameter> parameter_ptr; +class naming_policy; +typedef shared_ptr<naming_policy> naming_policy_ptr; +class argv_traverser; + +namespace rt_cla_detail { + +template<typename T> class const_generator; +template<typename T> class ref_generator; + +template<typename T> class assigner; + +class named_parameter_base; +class positional_parameter_base; + +} // namespace rt_cla_detail + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_FWD_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/id_policy.cpp b/boost/test/utils/runtime/cla/id_policy.cpp new file mode 100644 index 0000000000..517c9c57a5 --- /dev/null +++ b/boost/test/utils/runtime/cla/id_policy.cpp @@ -0,0 +1,16 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : some generic identification policies offline implementation +// *************************************************************************** + +#define BOOST_RT_PARAM_INLINE +#include <boost/test/utils/runtime/cla/id_policy.ipp> diff --git a/boost/test/utils/runtime/cla/id_policy.hpp b/boost/test/utils/runtime/cla/id_policy.hpp new file mode 100644 index 0000000000..0784979912 --- /dev/null +++ b/boost/test/utils/runtime/cla/id_policy.hpp @@ -0,0 +1,145 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 57992 $ +// +// Description : some generic identification policies definition +// *************************************************************************** + +#ifndef BOOST_RT_CLA_ID_POLICY_HPP_062604GER +#define BOOST_RT_CLA_ID_POLICY_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/fwd.hpp> +#include <boost/test/utils/runtime/cla/modifier.hpp> +#include <boost/test/utils/runtime/cla/argv_traverser.hpp> + +#include <boost/test/utils/runtime/cla/iface/id_policy.hpp> + +// Boost.Test +#include <boost/test/utils/class_properties.hpp> +#include <boost/test/utils/rtti.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** naming_policy_base ************** // +// ************************************************************************** // +// model: <prefix> <name> <separtor> + +class basic_naming_policy : public identification_policy { +public: + // Public properties + unit_test::readwrite_property<dstring> p_prefix; + unit_test::readwrite_property<dstring> p_name; + unit_test::readwrite_property<dstring> p_separator; + + // Policy interface + virtual bool responds_to( cstring name ) const { return p_name == name; } + virtual cstring id_2_report() const { return p_name.get(); } + virtual void usage_info( format_stream& fs ) const; + virtual bool matching( parameter const& p, argv_traverser& tr, bool primary ) const; + + // Accept modifier + template<typename Modifier> + void accept_modifier( Modifier const& m ) + { + nfp::optionally_assign( p_prefix.value, m, prefix ); + nfp::optionally_assign( p_name.value, m, name ); + nfp::optionally_assign( p_separator.value, m, separator ); + } + +protected: + explicit basic_naming_policy( rtti::id_t dyn_type ) + : identification_policy( dyn_type ) + {} + BOOST_RT_PARAM_UNNEEDED_VIRTUAL ~basic_naming_policy() {} + + // Naming policy interface + virtual bool match_prefix( argv_traverser& tr ) const; + virtual bool match_name( argv_traverser& tr ) const; + virtual bool match_separator( argv_traverser& tr, bool optional_value ) const; +}; + +// ************************************************************************** // +// ************** dual_id_policy ************** // +// ************************************************************************** // + +template<typename MostDerived,typename PrimaryId,typename SecondId> +class dual_id_policy : public identification_policy { +public: + // Constructor + dual_id_policy() + : identification_policy( rtti::type_id<MostDerived>() ) + , m_primary() + , m_secondary() + {} + + // Policy interface + virtual bool responds_to( cstring name ) const + { + return m_primary.responds_to( name ) || m_secondary.responds_to( name ); + } + virtual bool conflict_with( identification_policy const& id_p ) const + { + return id_p.conflict_with( m_primary ) || id_p.conflict_with( m_secondary ); + } + virtual cstring id_2_report() const + { + return m_primary.id_2_report(); + } + virtual void usage_info( format_stream& fs ) const + { + fs << BOOST_RT_PARAM_LITERAL( '{' ); + m_primary.usage_info( fs ); + fs << BOOST_RT_PARAM_LITERAL( '|' ); + m_secondary.usage_info( fs ); + fs << BOOST_RT_PARAM_LITERAL( '}' ); + } + virtual bool matching( parameter const& p, argv_traverser& tr, bool primary ) const + { + return m_primary.matching( p, tr, primary ) || m_secondary.matching( p, tr, primary ); + } + + // Accept modifier + template<typename Modifier> + void accept_modifier( Modifier const& m ) + { + m_primary.accept_modifier( m ); + m_secondary.accept_modifier( m ); + } + +protected: + BOOST_RT_PARAM_UNNEEDED_VIRTUAL ~dual_id_policy() {} + + // Data members + PrimaryId m_primary; + SecondId m_secondary; +}; + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#ifndef BOOST_RT_PARAM_OFFLINE + +# define BOOST_RT_PARAM_INLINE inline +# include <boost/test/utils/runtime/cla/id_policy.ipp> + +#endif + +#endif // BOOST_RT_CLA_ID_POLICY_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/id_policy.ipp b/boost/test/utils/runtime/cla/id_policy.ipp new file mode 100644 index 0000000000..0de8d85d1a --- /dev/null +++ b/boost/test/utils/runtime/cla/id_policy.ipp @@ -0,0 +1,118 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : some generic identification policies implementation +// *************************************************************************** + +#ifndef BOOST_RT_CLA_ID_POLICY_IPP_062904GER +#define BOOST_RT_CLA_ID_POLICY_IPP_062904GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/id_policy.hpp> +#include <boost/test/utils/runtime/cla/parameter.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** basic_naming_policy ************** // +// ************************************************************************** // + +BOOST_RT_PARAM_INLINE void +basic_naming_policy::usage_info( format_stream& fs ) const +{ + fs << p_prefix << p_name << p_separator; + + if( p_separator->empty() ) + fs << BOOST_RT_PARAM_LITERAL( ' ' ); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE bool +basic_naming_policy::match_prefix( argv_traverser& tr ) const +{ + if( !tr.match_front( p_prefix.get() ) ) + return false; + + tr.trim( p_prefix->size() ); + return true; +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE bool +basic_naming_policy::match_name( argv_traverser& tr ) const +{ + if( !tr.match_front( p_name.get() ) ) + return false; + + tr.trim( p_name->size() ); + return true; +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE bool +basic_naming_policy::match_separator( argv_traverser& tr, bool optional_value ) const +{ + if( p_separator->empty() ) { + if( !tr.token().is_empty() ) + return false; + + tr.trim( 1 ); + } + else { + if( !tr.match_front( p_separator.get() ) ) { + // if parameter has optional value separator is optional as well + if( optional_value && ( tr.eoi() || tr.match_front( ' ' ) ) ) { + return true; + } + return false; + } + + tr.trim( p_separator->size() ); + } + + return true; +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE bool +basic_naming_policy::matching( parameter const& p, argv_traverser& tr, bool ) const +{ + if( !match_prefix( tr ) ) + return false; + + if( !match_name( tr ) ) + return false; + + if( !match_separator( tr, p.p_optional_value ) ) + return false; + + return true; +} + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_ID_POLICY_IPP_062904GER diff --git a/boost/test/utils/runtime/cla/iface/argument_factory.hpp b/boost/test/utils/runtime/cla/iface/argument_factory.hpp new file mode 100644 index 0000000000..6f549653a2 --- /dev/null +++ b/boost/test/utils/runtime/cla/iface/argument_factory.hpp @@ -0,0 +1,51 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : defines interface for argument_factory +// *************************************************************************** + +#ifndef BOOST_RT_CLA_IFACE_ARGUMENT_FACTORY_HPP_062604GER +#define BOOST_RT_CLA_IFACE_ARGUMENT_FACTORY_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> +#include <boost/test/utils/runtime/fwd.hpp> + +#include <boost/test/utils/runtime/cla/fwd.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** argument_factory ************** // +// ************************************************************************** // +// another name can be argument production policy + +class argument_factory { +public: + // Argument factory interface + virtual argument_ptr produce_using( parameter& p, argv_traverser& tr ) = 0; /// produce argument based on input + virtual argument_ptr produce_using( parameter& p, parser const& ) = 0; /// produce argument based on internal generator and/or values of other parameters + virtual void argument_usage_info( format_stream& fs ) = 0; /// argument value format information +protected: + BOOST_TEST_PROTECTED_VIRTUAL ~argument_factory() {} +}; + +} // namespace boost + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace cla + +#endif // BOOST_RT_CLA_IFACE_ARGUMENT_FACTORY_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/iface/id_policy.hpp b/boost/test/utils/runtime/cla/iface/id_policy.hpp new file mode 100644 index 0000000000..c69a09458e --- /dev/null +++ b/boost/test/utils/runtime/cla/iface/id_policy.hpp @@ -0,0 +1,73 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 57992 $ +// +// Description : defines interface for identification_policy +// *************************************************************************** + +#ifndef BOOST_RT_CLA_IFACE_ID_POLICY_HPP_062604GER +#define BOOST_RT_CLA_IFACE_ID_POLICY_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/fwd.hpp> + +// Boost.Test +#include <boost/test/utils/class_properties.hpp> +#include <boost/test/utils/rtti.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** identification_policy ************** // +// ************************************************************************** // + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4244) +#endif + +class identification_policy { +public: + // Public properties + unit_test::readwrite_property<rtti::id_t> p_type_id; + + // Policy interface + virtual bool responds_to( cstring name ) const = 0; + virtual cstring id_2_report() const = 0; + virtual void usage_info( format_stream& fs ) const = 0; + virtual bool matching( parameter const& p, argv_traverser& tr, bool primary ) const = 0; + + virtual bool conflict_with( identification_policy const& ) const = 0; + +protected: + // Constructor + explicit identification_policy( rtti::id_t dyn_type ) + : p_type_id( dyn_type ) + {} + BOOST_TEST_PROTECTED_VIRTUAL ~identification_policy() {} +}; + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_IFACE_ID_POLICY_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/modifier.hpp b/boost/test/utils/runtime/cla/modifier.hpp new file mode 100644 index 0000000000..bc6a7eb9eb --- /dev/null +++ b/boost/test/utils/runtime/cla/modifier.hpp @@ -0,0 +1,69 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : parameter modifiers +// *************************************************************************** + +#ifndef BOOST_RT_CLA_MODIFIER_HPP_062604GER +#define BOOST_RT_CLA_MODIFIER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +// Boost.Test +#include <boost/test/utils/named_params.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** environment variable modifiers ************** // +// ************************************************************************** // + +namespace { + +nfp::typed_keyword<bool,struct optional_t> optional_m; +nfp::named_parameter<bool,optional_t,bool> optional( true ); +nfp::typed_keyword<bool,struct required_t> required_m; +nfp::named_parameter<bool,required_t,bool> required( true ); +nfp::typed_keyword<bool,struct multiplicable_t> multiplicable_m; +nfp::named_parameter<bool,multiplicable_t,bool> multiplicable( true ); +nfp::typed_keyword<bool,struct guess_name_t> guess_name_m; +nfp::named_parameter<bool,guess_name_t,bool> guess_name( true ); +nfp::typed_keyword<bool,struct ignore_mismatch_t> ignore_mismatch_m; +nfp::named_parameter<bool,ignore_mismatch_t,bool> ignore_mismatch( true ); +nfp::typed_keyword<bool,struct optional_value_t> optional_value_m; +nfp::named_parameter<bool,optional_value_t,bool> optional_value( true ); + +nfp::typed_keyword<char_type,struct input_separator_t> input_separator; +nfp::typed_keyword<cstring,struct prefix_t> prefix; +nfp::typed_keyword<cstring,struct name_t> name; +nfp::typed_keyword<cstring,struct separator_t> separator; +nfp::typed_keyword<cstring,struct description_t> description; +nfp::typed_keyword<cstring,struct refer_to_t> default_refer_to; + +nfp::keyword<struct default_value_t> default_value; +nfp::keyword<struct handler_t> handler; +nfp::keyword<struct interpreter_t> interpreter; +nfp::keyword<struct assign_to_t> assign_to; + +} // local namespace + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_MODIFIER_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/named_parameter.cpp b/boost/test/utils/runtime/cla/named_parameter.cpp new file mode 100644 index 0000000000..ff8d105cd4 --- /dev/null +++ b/boost/test/utils/runtime/cla/named_parameter.cpp @@ -0,0 +1,16 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : offline implementation of named parameter +// *************************************************************************** + +#define BOOST_RT_PARAM_INLINE +#include <boost/test/utils/runtime/cla/named_parameter.ipp> diff --git a/boost/test/utils/runtime/cla/named_parameter.hpp b/boost/test/utils/runtime/cla/named_parameter.hpp new file mode 100644 index 0000000000..51ef1da16c --- /dev/null +++ b/boost/test/utils/runtime/cla/named_parameter.hpp @@ -0,0 +1,93 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : defines model of named parameter +// *************************************************************************** + +#ifndef BOOST_RT_CLA_NAMED_PARAMETER_HPP_062604GER +#define BOOST_RT_CLA_NAMED_PARAMETER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/basic_parameter.hpp> +#include <boost/test/utils/runtime/cla/id_policy.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** string_name_policy ************** // +// ************************************************************************** // + +class string_name_policy : public basic_naming_policy { +public: + // Constructor + string_name_policy(); + BOOST_RT_PARAM_UNNEEDED_VIRTUAL ~string_name_policy() {} + + // policy interface + virtual bool responds_to( cstring name ) const; + virtual bool conflict_with( identification_policy const& ) const; + + // Accept modifier + template<typename Modifier> + void accept_modifier( Modifier const& m ) + { + basic_naming_policy::accept_modifier( m ); + + if( m.has( guess_name_m ) ) + m_guess_name = true; + } + +private: + // Naming policy interface + virtual bool match_name( argv_traverser& tr ) const; + + // Data members + bool m_guess_name; +}; + +// ************************************************************************** // +// ************** runtime::cla::named_parameter ************** // +// ************************************************************************** // + +template<typename T> +class named_parameter_t : public basic_parameter<T,string_name_policy> { + typedef basic_parameter<T,string_name_policy> base; +public: + // Constructors + explicit named_parameter_t( cstring name ) : base( name ) {} +}; + +//____________________________________________________________________________// + +BOOST_RT_CLA_NAMED_PARAM_GENERATORS( named_parameter ) + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#ifndef BOOST_RT_PARAM_OFFLINE + +# define BOOST_RT_PARAM_INLINE inline +# include <boost/test/utils/runtime/cla/named_parameter.ipp> + +#endif + +#endif // BOOST_RT_CLA_NAMED_PARAMETER_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/named_parameter.ipp b/boost/test/utils/runtime/cla/named_parameter.ipp new file mode 100644 index 0000000000..77f69aaee9 --- /dev/null +++ b/boost/test/utils/runtime/cla/named_parameter.ipp @@ -0,0 +1,129 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : implements model of named parameter +// *************************************************************************** + +#ifndef BOOST_RT_CLA_NAMED_PARAMETER_IPP_062904GER +#define BOOST_RT_CLA_NAMED_PARAMETER_IPP_062904GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/named_parameter.hpp> +#include <boost/test/utils/runtime/cla/char_parameter.hpp> + +// Boost.Test +#include <boost/test/utils/algorithm.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** string_name_policy ************** // +// ************************************************************************** // + +BOOST_RT_PARAM_INLINE +string_name_policy::string_name_policy() +: basic_naming_policy( rtti::type_id<string_name_policy>() ) +, m_guess_name( false ) +{ + assign_op( p_prefix.value, BOOST_RT_PARAM_CSTRING_LITERAL( "-" ), 0 ); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE bool +string_name_policy::responds_to( cstring name ) const +{ + std::pair<cstring::iterator,dstring::const_iterator> mm_pos; + + mm_pos = unit_test::mismatch( name.begin(), name.end(), p_name->begin(), p_name->end() ); + + return mm_pos.first == name.end() && (m_guess_name || (mm_pos.second == p_name->end()) ); +} + +//____________________________________________________________________________// + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4244) +#endif + +BOOST_RT_PARAM_INLINE bool +string_name_policy::conflict_with( identification_policy const& id ) const +{ + if( id.p_type_id == p_type_id ) { + string_name_policy const& snp = static_cast<string_name_policy const&>( id ); + + if( p_name->empty() || snp.p_name->empty() ) + return false; + + if( p_prefix != snp.p_prefix ) + return false; + + std::pair<dstring::const_iterator,dstring::const_iterator> mm_pos = + unit_test::mismatch( p_name->begin(), p_name->end(), snp.p_name->begin(), snp.p_name->end() ); + + return mm_pos.first != p_name->begin() && // there is common substring + ((m_guess_name && (mm_pos.second == snp.p_name->end()) ) || // that match other guy and I am guessing + (snp.m_guess_name && (mm_pos.first == p_name->end()) )); // or me and the other guy is + } + + if( id.p_type_id == rtti::type_id<char_name_policy>() ) { + char_name_policy const& cnp = static_cast<char_name_policy const&>( id ); + + return m_guess_name && + (p_prefix == cnp.p_prefix) && + unit_test::first_char( cstring( p_name ) ) == unit_test::first_char( cstring( cnp.p_name ) ); + } + + return false; +} + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE bool +string_name_policy::match_name( argv_traverser& tr ) const +{ + if( !m_guess_name ) + return basic_naming_policy::match_name( tr ); + + cstring in = tr.input(); + + std::pair<cstring::iterator,dstring::const_iterator> mm_pos; + + mm_pos = unit_test::mismatch( in.begin(), in.end(), p_name->begin(), p_name->end() ); + + if( mm_pos.first == in.begin() ) + return false; + + tr.trim( mm_pos.first - in.begin() ); + + return true; +} + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_NAMED_PARAMETER_IPP_062904GER diff --git a/boost/test/utils/runtime/cla/parameter.hpp b/boost/test/utils/runtime/cla/parameter.hpp new file mode 100644 index 0000000000..58ec295308 --- /dev/null +++ b/boost/test/utils/runtime/cla/parameter.hpp @@ -0,0 +1,150 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : defines model of formal parameter +// *************************************************************************** + +#ifndef BOOST_RT_CLA_PARAMETER_HPP_062604GER +#define BOOST_RT_CLA_PARAMETER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/fwd.hpp> +#include <boost/test/utils/runtime/parameter.hpp> +#include <boost/test/utils/runtime/validation.hpp> + +#include <boost/test/utils/runtime/cla/fwd.hpp> +#include <boost/test/utils/runtime/cla/modifier.hpp> +#include <boost/test/utils/runtime/cla/iface/argument_factory.hpp> +#include <boost/test/utils/runtime/cla/iface/id_policy.hpp> + +// Boost.Test +#include <boost/test/utils/rtti.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** runtime::cla::parameter ************** // +// ************************************************************************** // + +class parameter : public BOOST_RT_PARAM_NAMESPACE::parameter { +public: + parameter( identification_policy& ID, argument_factory& F, bool optional_value = false ) + : p_optional( false ) + , p_multiplicable( false ) + , p_optional_value( optional_value ) + , m_id_policy( ID ) + , m_arg_factory( F ) + {} + + // Destructor + virtual ~parameter() {} + + unit_test::readwrite_property<bool> p_optional; + unit_test::readwrite_property<bool> p_multiplicable; + unit_test::readwrite_property<bool> p_optional_value; + unit_test::readwrite_property<dstring> p_description; + + // parameter properties modification + template<typename Modifier> + void accept_modifier( Modifier const& m ) + { + if( m.has( optional_m ) ) + p_optional.value = true; + + if( m.has( required_m ) ) + p_optional.value = false; + + if( m.has( multiplicable_m ) ) + p_multiplicable.value = true; + + if( m.has( optional_value_m ) ) + p_optional_value.value = true; + + nfp::optionally_assign( p_description.value, m, description ); + } + + // access methods + bool has_argument() const { return m_actual_argument; } + argument const& actual_argument() const { return *m_actual_argument; } + argument_ptr actual_argument() { return m_actual_argument; } + + + // identification interface + bool responds_to( cstring name ) const { return m_id_policy.responds_to( name ); } + bool conflict_with( parameter const& p ) const + { + return (id_2_report() == p.id_2_report() && !id_2_report().is_empty()) || + m_id_policy.conflict_with( p.m_id_policy ) || + ((m_id_policy.p_type_id != p.m_id_policy.p_type_id) && p.m_id_policy.conflict_with( m_id_policy )); + } + cstring id_2_report() const { return m_id_policy.id_2_report(); } + void usage_info( format_stream& fs ) const + { + m_id_policy.usage_info( fs ); + if( p_optional_value ) + fs << BOOST_RT_PARAM_LITERAL( '[' ); + + m_arg_factory.argument_usage_info( fs ); + + if( p_optional_value ) + fs << BOOST_RT_PARAM_LITERAL( ']' ); + } + + // argument match/produce based on input + bool matching( argv_traverser& tr, bool primary ) const + { + return m_id_policy.matching( *this, tr, primary ); + } + + // argument production based on different source + void produce_argument( argv_traverser& tr ) + { + m_id_policy.matching( *this, tr, true ); // !! can we save this position somehow + m_actual_argument = m_arg_factory.produce_using( *this, tr ); + } + void produce_argument( parser const& p ) + { + m_actual_argument = m_arg_factory.produce_using( *this, p ); + } + +private: + //Data members + identification_policy& m_id_policy; + argument_factory& m_arg_factory; + argument_ptr m_actual_argument; +}; + +//____________________________________________________________________________// + +template<typename Parameter,typename Modifier> +inline shared_ptr<Parameter> +operator-( shared_ptr<Parameter> p, Modifier const& m ) +{ + p->accept_modifier( m ); + + return p; +} + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_PARAMETER_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/parser.cpp b/boost/test/utils/runtime/cla/parser.cpp new file mode 100644 index 0000000000..2fdeb9afbe --- /dev/null +++ b/boost/test/utils/runtime/cla/parser.cpp @@ -0,0 +1,18 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : offline implementation for parser +// *************************************************************************** + +#include <boost/test/utils/runtime/config.hpp> + +#define BOOST_RT_PARAM_INLINE +#include <boost/test/utils/runtime/cla/parser.ipp> diff --git a/boost/test/utils/runtime/cla/parser.hpp b/boost/test/utils/runtime/cla/parser.hpp new file mode 100644 index 0000000000..5c3c341d94 --- /dev/null +++ b/boost/test/utils/runtime/cla/parser.hpp @@ -0,0 +1,153 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 57992 $ +// +// Description : defines parser - public interface for CLA parsing and accessing +// *************************************************************************** + +#ifndef BOOST_RT_CLA_PARSER_HPP_062604GER +#define BOOST_RT_CLA_PARSER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> +#include <boost/test/utils/runtime/fwd.hpp> +#include <boost/test/utils/runtime/argument.hpp> + +#include <boost/test/utils/runtime/cla/fwd.hpp> +#include <boost/test/utils/runtime/cla/modifier.hpp> +#include <boost/test/utils/runtime/cla/argv_traverser.hpp> + +// Boost +#include <boost/optional.hpp> + +// STL +#include <list> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** runtime::cla::parser ************** // +// ************************************************************************** // + +namespace cla_detail { + +template<typename Modifier> +class global_mod_parser { +public: + global_mod_parser( parser& p, Modifier const& m ) + : m_parser( p ) + , m_modifiers( m ) + {} + + template<typename Param> + global_mod_parser const& + operator<<( shared_ptr<Param> param ) const + { + param->accept_modifier( m_modifiers ); + + m_parser << param; + + return *this; + } + +private: + // Data members; + parser& m_parser; + Modifier const& m_modifiers; +}; + +} + +// ************************************************************************** // +// ************** runtime::cla::parser ************** // +// ************************************************************************** // + +class parser { +public: + typedef std::list<parameter_ptr>::const_iterator param_iterator; + + // Constructor + explicit parser( cstring program_name = cstring() ); + + // parameter list construction interface + parser& operator<<( parameter_ptr param ); + + // parser and global parameters modifiers + template<typename Modifier> + cla_detail::global_mod_parser<Modifier> + operator-( Modifier const& m ) + { + nfp::optionally_assign( m_traverser.p_separator.value, m, input_separator ); + nfp::optionally_assign( m_traverser.p_ignore_mismatch.value, m, ignore_mismatch_m ); + + return cla_detail::global_mod_parser<Modifier>( *this, m ); + } + + // input processing method + void parse( int& argc, char_type** argv ); + + // parameters access + param_iterator first_param() const; + param_iterator last_param() const; + + // arguments access + const_argument_ptr operator[]( cstring string_id ) const; + cstring get( cstring string_id ) const; + + template<typename T> + T const& get( cstring string_id ) const + { + return arg_value<T>( valid_argument( string_id ) ); + } + + template<typename T> + void get( cstring string_id, boost::optional<T>& res ) const + { + const_argument_ptr actual_arg = (*this)[string_id]; + + if( actual_arg ) + res = arg_value<T>( *actual_arg ); + else + res.reset(); + } + + // help/usage + void usage( out_stream& ostr ); + void help( out_stream& ostr ); + +private: + argument const& valid_argument( cstring string_id ) const; + + // Data members + argv_traverser m_traverser; + std::list<parameter_ptr> m_parameters; + dstring m_program_name; +}; + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#ifndef BOOST_RT_PARAM_OFFLINE + +# define BOOST_RT_PARAM_INLINE inline +# include <boost/test/utils/runtime/cla/parser.ipp> + +#endif + +#endif // BOOST_RT_CLA_PARSER_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/parser.ipp b/boost/test/utils/runtime/cla/parser.ipp new file mode 100644 index 0000000000..995411a73f --- /dev/null +++ b/boost/test/utils/runtime/cla/parser.ipp @@ -0,0 +1,258 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : implements parser - public interface for CLA parsing and accessing +// *************************************************************************** + +#ifndef BOOST_RT_CLA_PARSER_IPP_062904GER +#define BOOST_RT_CLA_PARSER_IPP_062904GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> +#include <boost/test/utils/runtime/trace.hpp> +#include <boost/test/utils/runtime/argument.hpp> + +#include <boost/test/utils/runtime/cla/argv_traverser.hpp> +#include <boost/test/utils/runtime/cla/parameter.hpp> +#include <boost/test/utils/runtime/cla/modifier.hpp> +#include <boost/test/utils/runtime/cla/validation.hpp> +#include <boost/test/utils/runtime/cla/parser.hpp> + +// Boost.Test +#include <boost/test/utils/basic_cstring/io.hpp> +#include <boost/test/utils/foreach.hpp> + +// Boost +#include <boost/lexical_cast.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** runtime::cla::parser ************** // +// ************************************************************************** // + +BOOST_RT_PARAM_INLINE +parser::parser( cstring program_name ) +{ + assign_op( m_program_name, program_name, 0 ); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE parser::param_iterator +parser::first_param() const +{ + return m_parameters.begin(); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE parser::param_iterator +parser::last_param() const +{ + return m_parameters.end(); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE argument const& +parser::valid_argument( cstring string_id ) const +{ + const_argument_ptr arg = (*this)[string_id]; + + BOOST_RT_PARAM_VALIDATE_LOGIC( !!arg, "Actual argument for parameter " << string_id << " is not present" ); + + return *arg; +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE parser& +parser::operator<<( parameter_ptr new_param ) +{ + BOOST_TEST_FOREACH( parameter_ptr, old_param, m_parameters ) { + BOOST_RT_PARAM_VALIDATE_LOGIC( !old_param->conflict_with( *new_param ), + BOOST_RT_PARAM_LITERAL( "Definition of parameter " ) << new_param->id_2_report() << + BOOST_RT_PARAM_LITERAL( " conflicts with defintion of parameter " ) << old_param->id_2_report() ); + } + + m_parameters.push_back( new_param ); + + return *this; +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE void +parser::parse( int& argc, char_type** argv ) +{ + if( m_program_name.empty() ) { + m_program_name.assign( argv[0] ); + dstring::size_type pos = m_program_name.find_last_of( BOOST_RT_PARAM_LITERAL( "/\\" ) ); + + if( pos != static_cast<dstring::size_type>(cstring::npos) ) + m_program_name.erase( 0, pos+1 ); + } + + m_traverser.init( argc, argv ); + + try { + while( !m_traverser.eoi() ) { + parameter_ptr found_param; + + BOOST_RT_PARAM_TRACE( "Total " << m_parameters.size() << " parameters registered" ); + + BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) { + BOOST_RT_PARAM_TRACE( "Try parameter " << curr_param->id_2_report() ); + + if( curr_param->matching( m_traverser, !found_param ) ) { + BOOST_RT_PARAM_TRACE( "Match found" ); + BOOST_RT_CLA_VALIDATE_INPUT( !found_param, (m_traverser.rollback(),m_traverser), "Ambiguous input" ); + + found_param = curr_param; + } + + m_traverser.rollback(); + } + + if( !found_param ) { + BOOST_RT_PARAM_TRACE( "No match found" ); + BOOST_RT_CLA_VALIDATE_INPUT( m_traverser.handle_mismatch(), m_traverser, + BOOST_RT_PARAM_LITERAL( "Unexpected input" ) ); + + continue; + } + + BOOST_RT_PARAM_TRACE( "Parse argument value" ); + found_param->produce_argument( m_traverser ); + + m_traverser.commit(); + } + + BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) { + if( !curr_param->p_optional && !curr_param->actual_argument() ) { + curr_param->produce_argument( *this ); + + BOOST_RT_PARAM_VALIDATE_LOGIC( curr_param->actual_argument(), + BOOST_RT_PARAM_LITERAL( "Required argument for parameter " ) << curr_param->id_2_report() + << BOOST_RT_PARAM_LITERAL( " is missing" ) ); + } + } + } + catch( bad_lexical_cast const& ) { + BOOST_RT_PARAM_REPORT_LOGIC_ERROR( + BOOST_RT_PARAM_LITERAL( "String to value convertion error during input parsing" ) ); + } + + m_traverser.remainder( argc, argv ); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE const_argument_ptr +parser::operator[]( cstring string_id ) const +{ + parameter_ptr found_param; + + BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) { + if( curr_param->responds_to( string_id ) ) { + BOOST_RT_PARAM_VALIDATE_LOGIC( !found_param, + BOOST_RT_PARAM_LITERAL( "Ambiguous parameter string id: " ) << string_id ); + + found_param = curr_param; + } + } + + return found_param ? found_param->actual_argument() : argument_ptr(); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE cstring +parser::get( cstring string_id ) const +{ + return get<cstring>( string_id ); +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE void +parser::usage( out_stream& ostr ) +{ + if( m_program_name.empty() ) + assign_op( m_program_name, BOOST_RT_PARAM_CSTRING_LITERAL( "<program>" ), 0 ); + + format_stream fs; + + fs << m_program_name; + + BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) { + fs << BOOST_RT_PARAM_LITERAL( ' ' ); + + if( curr_param->p_optional ) + fs << BOOST_RT_PARAM_LITERAL( '[' ); + + curr_param->usage_info( fs ); + + if( curr_param->p_optional ) + fs << BOOST_RT_PARAM_LITERAL( ']' ); + + if( curr_param->p_multiplicable ) { + fs << BOOST_RT_PARAM_CSTRING_LITERAL( " ... " ); + + if( curr_param->p_optional ) + fs << BOOST_RT_PARAM_LITERAL( '[' ); + + curr_param->usage_info( fs ); + + if( curr_param->p_optional ) + fs << BOOST_RT_PARAM_LITERAL( ']' ); + } + } + + ostr << BOOST_RT_PARAM_CSTRING_LITERAL( "Usage:\n" ) << fs.str() << std::endl; +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE void +parser::help( out_stream& ostr ) +{ + usage( ostr ); + + bool need_where = true; + + BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) { + if( curr_param->p_description->empty() ) + continue; + + if( need_where ) { + ostr << BOOST_RT_PARAM_CSTRING_LITERAL( "where:\n" ); + need_where = false; + } + + ostr << curr_param->id_2_report() << BOOST_RT_PARAM_CSTRING_LITERAL( " - " ) << curr_param->p_description << std::endl; + } +} + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_PARSER_IPP_062904GER diff --git a/boost/test/utils/runtime/cla/positional_parameter.hpp b/boost/test/utils/runtime/cla/positional_parameter.hpp new file mode 100644 index 0000000000..a4be029a22 --- /dev/null +++ b/boost/test/utils/runtime/cla/positional_parameter.hpp @@ -0,0 +1,91 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : positional parameter model +// *************************************************************************** + +#ifndef BOOST_RT_CLA_POSITIONAL_PARAMETER_HPP_062604GER +#define BOOST_RT_CLA_POSITIONAL_PARAMETER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/basic_parameter.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** trivial_id_policy ************** // +// ************************************************************************** // + +class trivial_id_policy : public identification_policy { +public: + trivial_id_policy() + : identification_policy( rtti::type_id<trivial_id_policy>() ) + {} + BOOST_RT_PARAM_UNNEEDED_VIRTUAL ~trivial_id_policy() {} + + virtual bool responds_to( cstring name ) const { return m_name == name; } + virtual bool conflict_with( identification_policy const& ) const { return false; } + virtual cstring id_2_report() const { return m_name; } + virtual void usage_info( format_stream& fs ) const + { + if( !m_name.empty() ) + fs << BOOST_RT_PARAM_LITERAL( '<' ) << m_name << BOOST_RT_PARAM_LITERAL( '>' ); + else + fs << BOOST_RT_PARAM_CSTRING_LITERAL( "<value>" ); + } + + virtual bool matching( parameter const& p, argv_traverser&, bool primary ) const + { + return primary && ( !p.has_argument() || p.p_multiplicable ); + } + + template<typename Modifier> + void accept_modifier( Modifier const& m ) + { + nfp::optionally_assign( m_name, m, name ); + } + +private: + // Data members + dstring m_name; +}; + +// ************************************************************************** // +// ************** runtime::cla::positional_parameter ************** // +// ************************************************************************** // + +template<typename T> +class positional_parameter_t : public basic_parameter<T,trivial_id_policy> { + typedef basic_parameter<T,trivial_id_policy> base; +public: + // Constructors + explicit positional_parameter_t( cstring name ) + : base( name ) + {} +}; + +//____________________________________________________________________________// + +BOOST_RT_CLA_NAMED_PARAM_GENERATORS( positional_parameter ) + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_POSITIONAL_PARAMETER_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/typed_parameter.hpp b/boost/test/utils/runtime/cla/typed_parameter.hpp new file mode 100644 index 0000000000..2d2e02eca1 --- /dev/null +++ b/boost/test/utils/runtime/cla/typed_parameter.hpp @@ -0,0 +1,70 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : generic typed parameter model +// *************************************************************************** + +#ifndef BOOST_RT_CLA_TYPED_PARAMETER_HPP_062604GER +#define BOOST_RT_CLA_TYPED_PARAMETER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/fwd.hpp> +#include <boost/test/utils/runtime/validation.hpp> + +#include <boost/test/utils/runtime/cla/parameter.hpp> +#include <boost/test/utils/runtime/cla/argument_factory.hpp> + +// Boost.Test +#include <boost/test/utils/rtti.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** runtime::cla::typed_parameter ************** // +// ************************************************************************** // + +template<typename T> +class typed_parameter : public cla::parameter { +public: + explicit typed_parameter( identification_policy& ID ) + : cla::parameter( ID, m_arg_factory, rtti::type_id<T>() == rtti::type_id<bool>() ) + {} + + // parameter properties modification + template<typename Modifier> + void accept_modifier( Modifier const& m ) + { + cla::parameter::accept_modifier( m ); + + m_arg_factory.accept_modifier( m ); + + BOOST_RT_PARAM_VALIDATE_LOGIC( !p_optional || !m_arg_factory.m_value_generator, + BOOST_RT_PARAM_LITERAL( "can't define a value generator for optional parameter " ) << id_2_report() ); + } + +private: + // Data members + typed_argument_factory<T> m_arg_factory; +}; + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_TYPED_PARAMETER_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/validation.cpp b/boost/test/utils/runtime/cla/validation.cpp new file mode 100644 index 0000000000..cbd70ad1e3 --- /dev/null +++ b/boost/test/utils/runtime/cla/validation.cpp @@ -0,0 +1,16 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : input validation helpers offline implementation +// *************************************************************************** + +#define BOOST_RT_PARAM_INLINE +#include <boost/test/utils/runtime/cla/validation.ipp> diff --git a/boost/test/utils/runtime/cla/validation.hpp b/boost/test/utils/runtime/cla/validation.hpp new file mode 100644 index 0000000000..6b2fea9711 --- /dev/null +++ b/boost/test/utils/runtime/cla/validation.hpp @@ -0,0 +1,55 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : input validation helpers definition +// *************************************************************************** + +#ifndef BOOST_RT_CLA_VALIDATION_HPP_062604GER +#define BOOST_RT_CLA_VALIDATION_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/fwd.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** runtime::cla::report_input_error ************** // +// ************************************************************************** // + +void report_input_error( argv_traverser const& tr, format_stream& msg ); + +//____________________________________________________________________________// + +#define BOOST_RT_CLA_VALIDATE_INPUT( b, tr, msg ) \ + if( b ) ; else ::boost::BOOST_RT_PARAM_NAMESPACE::cla::report_input_error( tr, format_stream().ref() << msg ) + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#ifndef BOOST_RT_PARAM_OFFLINE + +# define BOOST_RT_PARAM_INLINE inline +# include <boost/test/utils/runtime/cla/validation.ipp> + +#endif + +#endif // BOOST_RT_CLA_VALIDATION_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/validation.ipp b/boost/test/utils/runtime/cla/validation.ipp new file mode 100644 index 0000000000..8cde449c25 --- /dev/null +++ b/boost/test/utils/runtime/cla/validation.ipp @@ -0,0 +1,65 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : input validation helpers implementation +// *************************************************************************** + +#ifndef BOOST_RT_CLA_VALIDATION_IPP_070604GER +#define BOOST_RT_CLA_VALIDATION_IPP_070604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/argv_traverser.hpp> +#include <boost/test/utils/runtime/cla/validation.hpp> +#include <boost/test/utils/runtime/validation.hpp> // BOOST_RT_PARAM_NAMESPACE::logic_error + +// Boost +#include <boost/test/utils/basic_cstring/io.hpp> + +// STL + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +// ************************************************************************** // +// ************** runtime::cla::validation ************** // +// ************************************************************************** // + +BOOST_RT_PARAM_INLINE void +report_input_error( argv_traverser const& tr, format_stream& msg ) +{ + if( tr.eoi() ) + msg << BOOST_RT_PARAM_LITERAL( " at the end of input" ); + else { + msg << BOOST_RT_PARAM_LITERAL( " in the following position: " ); + + if( tr.input().size() > 5 ) + msg << tr.input().substr( 0, 5 ) << BOOST_RT_PARAM_LITERAL( "..." ); + else + msg << tr.input(); + } + + throw BOOST_RT_PARAM_NAMESPACE::logic_error( msg.str() ); +} + +//____________________________________________________________________________// + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_VALIDATION_IPP_070604GER diff --git a/boost/test/utils/runtime/cla/value_generator.hpp b/boost/test/utils/runtime/cla/value_generator.hpp new file mode 100644 index 0000000000..1851592b4d --- /dev/null +++ b/boost/test/utils/runtime/cla/value_generator.hpp @@ -0,0 +1,81 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : specific value generators +// *************************************************************************** + +#ifndef BOOST_RT_CLA_VALUE_GENERATOR_HPP_062604GER +#define BOOST_RT_CLA_VALUE_GENERATOR_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/fwd.hpp> +#include <boost/test/utils/runtime/cla/parser.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +namespace rt_cla_detail { + +// ************************************************************************** // +// ************** runtime::cla::const_generator ************** // +// ************************************************************************** // + +template<typename T> +class const_generator { +public: + // Constructor + explicit const_generator( T const& t ) : m_const_value( t ) {} + + // generator interface + void operator()( parser const&, boost::optional<T>& t ) const { t = m_const_value; } + +private: + // Data members + T m_const_value; +}; + +// ************************************************************************** // +// ************** runtime::cla::ref_generator ************** // +// ************************************************************************** // + +template<typename T> +class ref_generator { +public: + // Constructor + explicit ref_generator( cstring ref_id ) : m_ref_id( ref_id ) {} + + // generator interface + void operator()( parser const& p, boost::optional<T>& t ) const + { + p.get( m_ref_id, t ); + } + +private: + // Data members + cstring m_ref_id; +}; + +//____________________________________________________________________________// + +} // namespace rt_cla_detail + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_VALUE_GENERATOR_HPP_062604GER diff --git a/boost/test/utils/runtime/cla/value_handler.hpp b/boost/test/utils/runtime/cla/value_handler.hpp new file mode 100644 index 0000000000..2bc74b2382 --- /dev/null +++ b/boost/test/utils/runtime/cla/value_handler.hpp @@ -0,0 +1,57 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : specific value handlers +// *************************************************************************** + +#ifndef BOOST_RT_CLA_VALUE_HANDLER_HPP_062604GER +#define BOOST_RT_CLA_VALUE_HANDLER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/cla/fwd.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace cla { + +namespace rt_cla_detail { + +// ************************************************************************** // +// ************** runtime::cla::assigner ************** // +// ************************************************************************** // + +template<typename T> +class assigner { +public: + // Constructor + explicit assigner( T& loc ) : m_target( loc ) {} + + // value handler implementation + void operator()( parameter const&, T& t ) { m_target = t; } + +private: + // Data members + T& m_target; +}; + +} // namespace rt_cla_detail + +} // namespace cla + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CLA_VALUE_HANDLER_HPP_062604GER diff --git a/boost/test/utils/runtime/config.hpp b/boost/test/utils/runtime/config.hpp new file mode 100644 index 0000000000..3f3ede8fe0 --- /dev/null +++ b/boost/test/utils/runtime/config.hpp @@ -0,0 +1,156 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 57992 $ +// +// Description : Runtime.Param library configuration +// *************************************************************************** + +#ifndef BOOST_RT_CONFIG_HPP_062604GER +#define BOOST_RT_CONFIG_HPP_062604GER + +// Boost +#include <boost/config.hpp> +#ifdef BOOST_MSVC +# pragma warning(disable: 4511) // copy constructor could not be generated +# pragma warning(disable: 4512) // assignment operator could not be generated +# pragma warning(disable: 4181) // qualifier applied to reference type; ignored +# pragma warning(disable: 4675) // resolved overload was found by argument-dependent lookup +#endif + +// Boost.Test +#include <boost/test/detail/config.hpp> +#include <boost/test/utils/basic_cstring/basic_cstring.hpp> +#include <boost/test/utils/wrap_stringstream.hpp> +#include <boost/test/utils/basic_cstring/io.hpp> // operator<<(boost::runtime::cstring) + +// STL +#include <string> +#include <cstdlib> + +//____________________________________________________________________________// + +#ifndef BOOST_RT_PARAM_CUSTOM_STRING +# ifndef BOOST_RT_PARAM_WIDE_STRING +# define BOOST_RT_PARAM_NAMESPACE runtime +# else +# define BOOST_RT_PARAM_NAMESPACE wide_runtime +# endif +#endif + +#ifdef __SUNPRO_CC +extern int putenv(char*); +#endif + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +#ifndef BOOST_RT_PARAM_CUSTOM_STRING +# ifndef BOOST_RT_PARAM_WIDE_STRING + +typedef char char_type; +typedef std::string dstring; +typedef unit_test::const_string cstring; +typedef unit_test::literal_string literal_cstring; +typedef wrap_stringstream format_stream; + +#ifdef BOOST_CLASSIC_IOSTREAMS +typedef std::ostream out_stream; +#else +typedef std::basic_ostream<char_type> out_stream; +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4996) // putenv +#endif + +#ifndef UNDER_CE +#if defined(__COMO__) && 0 +inline void +putenv_impl( cstring name, cstring value ) +{ + using namespace std; + // !! this may actually fail. What should we do? + setenv( name.begin(), value.begin(), 1 ); +} +#else +inline void +putenv_impl( cstring name, cstring value ) +{ + format_stream fs; + + fs << name << '=' << value; + + // !! this may actually fail. What should we do? + // const_cast is used to satisfy putenv interface + using namespace std; + putenv( const_cast<char*>( fs.str().c_str() ) ); +} +#endif +#endif + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#define BOOST_RT_PARAM_LITERAL( l ) l +#define BOOST_RT_PARAM_CSTRING_LITERAL( l ) cstring( l, sizeof( l ) - 1 ) +#define BOOST_RT_PARAM_GETENV getenv +#define BOOST_RT_PARAM_PUTENV ::boost::BOOST_RT_PARAM_NAMESPACE::putenv_impl +#define BOOST_RT_PARAM_EXCEPTION_INHERIT_STD + +//____________________________________________________________________________// + +# else + +typedef wchar_t char_type; +typedef std::basic_string<char_type> dstring; +typedef unit_test::basic_cstring<wchar_t const> cstring; +typedef const unit_test::basic_cstring<wchar_t const> literal_cstring; +typedef wrap_wstringstream format_stream; +typedef std::wostream out_stream; + +#ifndef UNDER_CE +inline void +putenv_impl( cstring name, cstring value ) +{ + format_stream fs; + + fs << name << '=' << value; + + // !! this may actually fail. What should we do? + // const_cast is used to satisfy putenv interface + using namespace std; + wputenv( const_cast<wchar_t*>( fs.str().c_str() ) ); +} +#endif + +#define BOOST_RT_PARAM_LITERAL( l ) L ## l +#define BOOST_RT_PARAM_CSTRING_LITERAL( l ) cstring( L ## l, sizeof( L ## l )/sizeof(wchar_t) - 1 ) +#define BOOST_RT_PARAM_GETENV wgetenv +#define BOOST_RT_PARAM_PUTENV putenv_impl + +# endif +#endif + +#ifdef __GNUC__ +#define BOOST_RT_PARAM_UNNEEDED_VIRTUAL virtual +#else +#define BOOST_RT_PARAM_UNNEEDED_VIRTUAL +#endif + +//____________________________________________________________________________// + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CONFIG_HPP_062604GER diff --git a/boost/test/utils/runtime/configuration.hpp b/boost/test/utils/runtime/configuration.hpp new file mode 100644 index 0000000000..0ca5cf7dec --- /dev/null +++ b/boost/test/utils/runtime/configuration.hpp @@ -0,0 +1,61 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : abstract interface for the formal parameter +// *************************************************************************** + +#ifndef BOOST_RT_CONFIGURATION_HPP_062604GER +#define BOOST_RT_CONFIGURATION_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> +#include <boost/test/utils/runtime/parameter.hpp> +#include <boost/test/utils/runtime/argument.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +// ************************************************************************** // +// ************** runtime::configuration ************** // +// ************************************************************************** // + +class config_source { + virtual parameter const& config_param_begin() const = 0; + virtual parameter const& config_param_end() const = 0; + +protected: + config_source() {} + ~config_source() {} +}; + +// ************************************************************************** // +// ************** runtime::configuration ************** // +// ************************************************************************** // + +template<typename StoragePolicy,typename IdentificationPlicy,typename ConflictResolutionPolicy> +class configuration : public StoragePolicy, public IdentificationPlicy, public ConflictResolutionPolicy { +public: + // Constructor + configuration(); + + void use( config_source const& ) + { + + } +private: +}; + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_CONFIGURATION_HPP_062604GER diff --git a/boost/test/utils/runtime/env/environment.cpp b/boost/test/utils/runtime/env/environment.cpp new file mode 100644 index 0000000000..a710c21711 --- /dev/null +++ b/boost/test/utils/runtime/env/environment.cpp @@ -0,0 +1,23 @@ +// (C) Copyright Gennadiy Rozental 2004-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : implements offline model of program environment +// *************************************************************************** + +#include <boost/test/utils/runtime/config.hpp> + +#ifdef BOOST_MSVC +# pragma warning(disable: 4127) // conditional expression is constant +# pragma warning(disable: 4701) // local environment 'result' may be used without having been initialized +#endif + +#define BOOST_RT_PARAM_INLINE +#include <boost/test/utils/runtime/env/environment.ipp> diff --git a/boost/test/utils/runtime/env/environment.hpp b/boost/test/utils/runtime/env/environment.hpp new file mode 100644 index 0000000000..f5e88a26cd --- /dev/null +++ b/boost/test/utils/runtime/env/environment.hpp @@ -0,0 +1,172 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : defines and implements inline model of program environment +// *************************************************************************** + +#ifndef BOOST_RT_ENV_ENVIRONMENT_HPP_062604GER +#define BOOST_RT_ENV_ENVIRONMENT_HPP_062604GER + +#ifdef UNDER_CE +#error Windows CE does not support environment variables. +#endif + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> +#include <boost/test/utils/runtime/fwd.hpp> +#include <boost/test/utils/runtime/argument.hpp> +#include <boost/test/utils/runtime/interpret_argument_value.hpp> + +#include <boost/test/utils/runtime/env/fwd.hpp> +#include <boost/test/utils/runtime/env/modifier.hpp> +#include <boost/test/utils/runtime/env/variable.hpp> + +// Boost.Test +#include <boost/test/utils/callback.hpp> + +// Boost +#include <boost/optional.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +// ************************************************************************** // +// ************** runtime::environment implementation ************** // +// ************************************************************************** // + +namespace environment { + +namespace rt_env_detail { + +template<typename T, typename Modifiers> +variable_data& +init_new_var( cstring var_name, Modifiers m = nfp::no_params ) +{ + rt_env_detail::variable_data& new_vd = new_var_record( var_name ); + + cstring str_value = sys_read_var( new_vd.m_var_name ); + + if( !str_value.is_empty() ) { + try { + boost::optional<T> value; + + if( m.has( interpreter ) ) + m[interpreter]( str_value, value ); + else + interpret_argument_value( str_value, value, 0 ); + + if( !!value ) { + new_vd.m_value.reset( new typed_argument<T>( new_vd ) ); + + arg_value<T>( *new_vd.m_value ) = *value; + } + } + catch( ... ) { // !! could we do that + // !! should we report an error? + } + } + + if( !new_vd.m_value && m.has( default_value ) ) { + new_vd.m_value.reset( new typed_argument<T>( new_vd ) ); + + nfp::optionally_assign( arg_value<T>( *new_vd.m_value ), m[default_value] ); + } + + nfp::optionally_assign( new_vd.m_global_id, m, global_id ); + + return new_vd; +} + +//____________________________________________________________________________// + +} // namespace rt_env_detail + +} // namespace environment + +// ************************************************************************** // +// ************** runtime::environment ************** // +// ************************************************************************** // + +namespace environment { + + // variable access + variable_base + var( cstring var_name ); + + //________________________________________________________________________// + + template<typename T> + inline variable<T> + var( cstring var_name ) + { + rt_env_detail::variable_data* vd = rt_env_detail::find_var_record( var_name ); + + return environment::variable<T>( !vd ? rt_env_detail::init_new_var<T>( var_name, nfp::no_params ) : *vd ); + } + + //________________________________________________________________________// + + template<typename T, typename Modifiers> + inline variable<T> + var( cstring var_name, Modifiers const& m ) + { + rt_env_detail::variable_data* vd = rt_env_detail::find_var_record( var_name ); + + return environment::variable<T>( !vd ? rt_env_detail::init_new_var<T>( var_name, m ) : *vd ); + } + + //________________________________________________________________________// + + // direct variable value access + inline cstring + get( cstring var_name ) + { + return environment::var<cstring>( var_name ).value(); + } + + //________________________________________________________________________// + + template<typename T> + inline T const& + get( cstring var_name ) + { + return environment::var<T>( var_name ).value(); + } + + //________________________________________________________________________// + + template<typename T> + inline void + get( cstring var_name, boost::optional<T>& res ) + { + variable<T> const& v = environment::var<T>( var_name ); + v.value( res ); + } + + //________________________________________________________________________// + +} // namespace environment + +namespace env = environment; + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#ifndef BOOST_RT_PARAM_OFFLINE + +#define BOOST_RT_PARAM_INLINE inline +#include <boost/test/utils/runtime/env/environment.ipp> + +#endif + +#endif // BOOST_RT_ENV_ENVIRONMENT_HPP_062604GER diff --git a/boost/test/utils/runtime/env/environment.ipp b/boost/test/utils/runtime/env/environment.ipp new file mode 100644 index 0000000000..0a4afe87c6 --- /dev/null +++ b/boost/test/utils/runtime/env/environment.ipp @@ -0,0 +1,125 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 57992 $ +// +// Description : implements model of program environment +// *************************************************************************** + +#ifndef BOOST_RT_ENV_ENVIRONMENT_IPP_062904GER +#define BOOST_RT_ENV_ENVIRONMENT_IPP_062904GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> +#include <boost/test/utils/runtime/validation.hpp> + +#include <boost/test/utils/runtime/env/variable.hpp> + +// Boost.Test +#include <boost/test/utils/basic_cstring/compare.hpp> +#include <boost/test/utils/basic_cstring/io.hpp> + +// STL +#include <map> +#include <list> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace environment { + +// ************************************************************************** // +// ************** runtime::environment ************** // +// ************************************************************************** // + +namespace rt_env_detail { + +typedef std::map<cstring,rt_env_detail::variable_data> registry; +typedef std::list<dstring> keys; + +BOOST_RT_PARAM_INLINE registry& s_registry() { static registry instance; return instance; } +BOOST_RT_PARAM_INLINE keys& s_keys() { static keys instance; return instance; } + +BOOST_RT_PARAM_INLINE variable_data& +new_var_record( cstring var_name ) +{ + // save the name in list of keys + s_keys().push_back( dstring() ); + dstring& key = s_keys().back(); + assign_op( key, var_name, 0 ); + + // create and return new record + variable_data& new_var_data = s_registry()[key]; + + new_var_data.m_var_name = key; + + return new_var_data; +} + +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE variable_data* +find_var_record( cstring var_name ) +{ + registry::iterator it = s_registry().find( var_name ); + + return it == s_registry().end() ? 0 : &(it->second); +} + +//____________________________________________________________________________// + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4996) // getenv +#endif + +BOOST_RT_PARAM_INLINE cstring +sys_read_var( cstring var_name ) +{ + using namespace std; + return BOOST_RT_PARAM_GETENV( var_name.begin() ); +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +//____________________________________________________________________________// + +BOOST_RT_PARAM_INLINE void +sys_write_var( cstring var_name, format_stream& var_value ) +{ + BOOST_RT_PARAM_PUTENV( var_name, cstring( var_value.str() ) ); +} + +//____________________________________________________________________________// + +} // namespace rt_env_detail + +BOOST_RT_PARAM_INLINE variable_base +var( cstring var_name ) +{ + rt_env_detail::variable_data* vd = rt_env_detail::find_var_record( var_name ); + + BOOST_RT_PARAM_VALIDATE_LOGIC( !!vd, + BOOST_RT_PARAM_LITERAL( "First access to the environment variable " ) + << var_name << BOOST_RT_PARAM_LITERAL( " should be typed" ) ); + + return variable_base( *vd ); +} + +//____________________________________________________________________________// + +} // namespace environment + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_ENV_ENVIRONMENT_IPP_062904GER diff --git a/boost/test/utils/runtime/env/fwd.hpp b/boost/test/utils/runtime/env/fwd.hpp new file mode 100644 index 0000000000..0808d0eab0 --- /dev/null +++ b/boost/test/utils/runtime/env/fwd.hpp @@ -0,0 +1,54 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : environment subsystem forward declarations +// *************************************************************************** + +#ifndef BOOST_RT_ENV_FWD_HPP_062604GER +#define BOOST_RT_ENV_FWD_HPP_062604GER + +#ifdef UNDER_CE +#error Windows CE does not support environment variables. +#endif + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace environment { + +class variable_base; +variable_base var( cstring var_name ); + +namespace rt_env_detail { + +struct variable_data; + +variable_data& new_var_record( cstring var_name ); +variable_data* find_var_record( cstring var_name ); + +cstring sys_read_var( cstring var_name ); +void sys_write_var( cstring var_name, format_stream& var_value ); + +} + +template <typename T> class variable; + +} // namespace environment + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_ENV_FWD_HPP_062604GER diff --git a/boost/test/utils/runtime/env/modifier.hpp b/boost/test/utils/runtime/env/modifier.hpp new file mode 100644 index 0000000000..4204d0be88 --- /dev/null +++ b/boost/test/utils/runtime/env/modifier.hpp @@ -0,0 +1,47 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : defines variable modifiers +// *************************************************************************** + +#ifndef BOOST_RT_ENV_MODIFIER_HPP_062604GER +#define BOOST_RT_ENV_MODIFIER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +// Boost.Test +#include <boost/test/utils/named_params.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace environment { + +// ************************************************************************** // +// ************** environment variable modifiers ************** // +// ************************************************************************** // + +namespace { + +nfp::typed_keyword<cstring,struct global_id_t> global_id; +nfp::keyword<struct default_value_t> default_value; +nfp::keyword<struct interpreter_t> interpreter; + +} // local namespace +} // namespace environment + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_ENV_MODIFIER_HPP_062604GER diff --git a/boost/test/utils/runtime/env/variable.hpp b/boost/test/utils/runtime/env/variable.hpp new file mode 100644 index 0000000000..740745df1a --- /dev/null +++ b/boost/test/utils/runtime/env/variable.hpp @@ -0,0 +1,223 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : defines model of program environment variable +// *************************************************************************** + +#ifndef BOOST_RT_ENV_VARIABLE_HPP_062604GER +#define BOOST_RT_ENV_VARIABLE_HPP_062604GER + +#ifdef UNDER_CE +#error Windows CE does not support environment variables. +#endif + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> +#include <boost/test/utils/runtime/fwd.hpp> +#include <boost/test/utils/runtime/parameter.hpp> +#include <boost/test/utils/runtime/argument.hpp> + +#include <boost/test/utils/runtime/env/fwd.hpp> + +// Boost +#include <boost/optional.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace environment { + +// ************************************************************************** // +// ************** runtime::environment::variable_data ************** // +// ************************************************************************** // + +namespace rt_env_detail { + +struct variable_data : public runtime::parameter { + cstring m_var_name; + dstring m_global_id; + argument_ptr m_value; +}; + +} // namespace rt_env_detail + +// ************************************************************************** // +// ************** runtime::environment::variable_base ************** // +// ************************************************************************** // + +class variable_base { +public: + explicit variable_base( rt_env_detail::variable_data& data ) : m_data( &data ) {} + + // arguments access + template<typename T> + T const& value() const + { + return arg_value<T>( *m_data->m_value ); + } + + template<typename T> + void value( boost::optional<T>& res ) const + { + if( has_value() ) + res = arg_value<T>( *m_data->m_value ); + else + res.reset(); + } + + bool has_value() const { return m_data->m_value; } + cstring name() const { return m_data->m_var_name; } + +protected: + // Data members + rt_env_detail::variable_data* m_data; +} ; + +// ************************************************************************** // +// ************** runtime::environment::variable ************** // +// ************************************************************************** // + +template<typename T = cstring> +class variable : public variable_base { +public: + // Constructors + explicit variable( cstring var_name ); + + template<typename Modifiers> + explicit variable( cstring var_name, Modifiers const& m ); + + explicit variable( rt_env_detail::variable_data& data ) + : variable_base( data ) {} + + // other variable assignment + void operator=( variable const& v ) { m_data = v.m_data; } + + // access methods + T const& value() const { return variable_base::value<T>(); } + +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) || \ + BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0593)) + template<typename T> + void value( boost::optional<T>& res ) const { variable_base::value( res ); } +#else + using variable_base::value; +#endif + + // Value assignment + template<typename V> + void operator=( V const& v ) + { + if( !has_value() ) + m_data->m_value.reset( new typed_argument<T>( *m_data ) ); + + arg_value<T>( *m_data->m_value ) = v; + + rt_env_detail::sys_write_var( m_data->m_var_name, format_stream().ref() << value() ); + } +}; // class variable + +//____________________________________________________________________________// + +template<typename CharT, typename Tr,typename T> +inline std::basic_ostream<CharT,Tr>& +operator<<( std::basic_ostream<CharT,Tr>& os, variable<T> const& v ) +{ + os << v.name() << '='; + + if( v.has_value() ) + os << v.value(); + + return os; +} + +//____________________________________________________________________________// + +template<typename T, typename V> +inline bool +operator==( variable<T> ev, V const& v ) +{ + return ev.has_value() && ev.value() == v; +} + +//____________________________________________________________________________// + +template<typename T, typename V> +inline bool +operator==( V const& v, variable<T> ev ) +{ + return ev.has_value() && ev.value() == v; +} + +//____________________________________________________________________________// + +template<typename T, typename V> +inline bool +operator!=( variable<T> ev, V const& v ) +{ + return !ev.has_value() || ev.value() != v; +} + +//____________________________________________________________________________// + +template<typename T, typename V> +inline bool +operator!=( V const& v, variable<T> ev ) +{ + return !ev.has_value() || ev.value() != v; +} + +//____________________________________________________________________________// + +} // namespace environment + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +// ************************************************************************** // +// ************************************************************************** // +// Implementation + +#include <boost/test/utils/runtime/env/environment.hpp> + +// ************************************************************************** // +// ************** runtime::environment::variable ************** // +// ************************************************************************** // + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace environment { + +template<typename T> +variable<T>::variable( cstring var_name ) +: variable_base( environment::var<T>( var_name ) ) +{} + +//____________________________________________________________________________// + +template<typename T> +template<typename Modifiers> +variable<T>::variable( cstring var_name, Modifiers const& m ) +: variable_base( environment::var<T>( var_name, m ) ) +{} + +//____________________________________________________________________________// + +} // namespace environment + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_ENV_VARIABLE_HPP_062604GER diff --git a/boost/test/utils/runtime/file/config_file.cpp b/boost/test/utils/runtime/file/config_file.cpp new file mode 100644 index 0000000000..f17fef53d6 --- /dev/null +++ b/boost/test/utils/runtime/file/config_file.cpp @@ -0,0 +1,249 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : implements models configuration file, it's parameter and parameter namespaces +// *************************************************************************** + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/file/config_file.hpp> +#include <boost/test/utils/runtime/validation.hpp> + +// Boost.Test +#include <boost/test/utils/foreach.hpp> +#include <boost/test/utils/basic_cstring/basic_cstring.hpp> +#include <boost/test/utils/basic_cstring/io.hpp> +#include <boost/test/utils/iterator/token_iterator.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace file { + +// ************************************************************************** // +// ************** runtime::file::parameter ************** // +// ************************************************************************** // + +parameter::parameter( cstring name, cstring value, param_namespace const& parent ) +: m_parent( parent ) +{ + assign_op( p_name.value, name, 0 ); + assign_op( p_value.value, value, 0 ); +} + +//____________________________________________________________________________// + +std::ostream& +operator<<( std::ostream& os, parameter const& p ) +{ + p.m_parent.print_full_name( os ); + + return os << p.p_name << " = \"" << p.p_value << "\""; +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** runtime::file::param_namespace ************** // +// ************************************************************************** // + +param_namespace::param_namespace( cstring name, param_namespace const* parent ) +: p_parent( parent ) +{ + assign_op( p_name.value, name ); +} + +//____________________________________________________________________________// + +void +param_namespace::insert_param( cstring param_name, cstring param_value ) +{ + BOOST_TEST_FOREACH( parameter const&, p, m_parameters ) + BOOST_RT_PARAM_VALIDATE_LOGIC( p.p_name != param_name, + BOOST_RT_PARAM_LITERAL( "Duplicate parameter " ) << param_name ); + + m_parameters.push_back( parameter( param_name, param_value, *this ) ); +} + +//____________________________________________________________________________// + +param_namespace& +param_namespace::subnamespace( cstring namespace_name ) +{ + BOOST_TEST_FOREACH( param_namespace&, subns, m_subnamespaces ) + if( subns.p_name == namespace_name ) + return subns; + + m_subnamespaces.push_back( param_namespace( namespace_name, this ) ); + + return m_subnamespaces.back(); +} + +//____________________________________________________________________________// + +void +param_namespace::clear() +{ + m_parameters.clear(); + m_subnamespaces.clear(); +} + +//____________________________________________________________________________// + +void +param_namespace::print_full_name( std::ostream& os ) const +{ + if( !p_parent ) + return; + + p_parent.get()->print_full_name( os ); + + os << p_name << "::"; +} + +//____________________________________________________________________________// + +boost::optional<cstring> +get_param_value( param_namespace const& where_from, + cstring name_part1, + cstring name_part2, + cstring name_part3, + cstring name_part4, + cstring name_part5 ) +{ + if( name_part2.is_empty() ) { + boost::optional<cstring> res; + + BOOST_TEST_FOREACH( parameter const&, p, where_from ) { + if( p.p_name == name_part1 ) { + res = cstring( p.p_value ); + break; + } + } + + return res; + } + + param_namespace const* sns = get_param_subns( where_from, name_part1 ); + + return sns ? get_param_value( *sns, name_part2, name_part3, name_part4, name_part5 ) + : boost::optional<cstring>(); +} + +//____________________________________________________________________________// + +cstring +get_requ_param_value( param_namespace const& where_from, + cstring name_part1, + cstring name_part2, + cstring name_part3, + cstring name_part4, + cstring name_part5 ) +{ + boost::optional<cstring> v = get_param_value( where_from, name_part1, name_part2, name_part3, name_part4, name_part5 ); + +#define APPEND_PART( part ) (part.is_empty() ? "" : "::") << (part.is_empty() ? cstring() : part) + BOOST_RT_PARAM_VALIDATE_LOGIC( !!v, BOOST_RT_PARAM_LITERAL( "Required parameter " ) + << name_part1 + << APPEND_PART( name_part2 ) + << APPEND_PART( name_part3 ) + << APPEND_PART( name_part4 ) + << APPEND_PART( name_part5 ) + << BOOST_RT_PARAM_LITERAL( " value is missing" ) ); +#undef APPEND_PART + + return *v; +} + +//____________________________________________________________________________// + +param_namespace const* +get_param_subns( param_namespace const& where_from, cstring namespace_name ) +{ + param_namespace::sub_ns_const_iterator it = where_from.sub_ns_begin(); + param_namespace::sub_ns_const_iterator end = where_from.sub_ns_end(); + + while( it != end ) { + if( it->p_name == namespace_name ) + return &*it; + + ++it; + } + + return 0; +} + +//____________________________________________________________________________// + +void +param_namespace::load_impl( config_file_iterator cf_it, + cstring value_marker, cstring value_delimeter, cstring namespace_delimeter ) +{ + using namespace unit_test; + + while( cf_it != config_file_iterator() ) { + string_token_iterator ti( *cf_it, (max_tokens = 2,kept_delimeters = dt_none, dropped_delimeters = value_delimeter) ); + + cstring param_name = *ti; + cstring param_value = *(++ti); + + param_value.trim( value_marker ); + + param_namespace* targ_ns = this; + + while( !param_name.is_empty() ) { + cstring::size_type pos = param_name.find( namespace_delimeter ); + cstring subname( param_name.begin(), pos == cstring::npos ? param_name.size() : pos ); + + if( subname.size() == param_name.size() ) { + targ_ns->insert_param( param_name, param_value ); + break; + } + else { + targ_ns = &targ_ns->subnamespace( subname ); + + param_name.trim_left( subname.size() + namespace_delimeter.size() ); + } + } + ++cf_it; + } +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** runtime::file::config_file ************** // +// ************************************************************************** // + +config_file::config_file() +: param_namespace( cstring() ) +{ +} + +//____________________________________________________________________________// + +config_file::config_file( cstring file_name ) +: param_namespace( cstring() ) +{ + load( file_name ); +} + +//____________________________________________________________________________// + +} // namespace file + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +// EOF diff --git a/boost/test/utils/runtime/file/config_file.hpp b/boost/test/utils/runtime/file/config_file.hpp new file mode 100644 index 0000000000..9dac6cfaf5 --- /dev/null +++ b/boost/test/utils/runtime/file/config_file.hpp @@ -0,0 +1,182 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : defines models configuration file, it's parameter and parameter namespaces +// *************************************************************************** + +#ifndef BOOST_RT_FILE_CONFIG_FILE_HPP_010105GER +#define BOOST_RT_FILE_CONFIG_FILE_HPP_010105GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/file/config_file_iterator.hpp> + +// Boost.Test +#include <boost/test/utils/class_properties.hpp> +#include <boost/test/utils/named_params.hpp> + +// Boost +#include <boost/optional.hpp> + +// STL +#include <list> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace file { + +// ************************************************************************** // +// ************** runtime::file::parameter ************** // +// ************************************************************************** // + +class param_namespace; + +class parameter { +public: + // Constructor + parameter( cstring name, cstring value, param_namespace const& parent ); + + BOOST_READONLY_PROPERTY( dstring, (parameter)) p_name; + BOOST_READONLY_PROPERTY( dstring, (parameter)) p_value; + + friend std::ostream& operator<<( std::ostream& os, parameter const& ); + +private: + // Data members + param_namespace const& m_parent; +}; + +// ************************************************************************** // +// ************** runtime::file::modifiers ************** // +// ************************************************************************** // + +namespace { +nfp::typed_keyword<cstring, struct value_marker_t> value_marker; +nfp::typed_keyword<cstring, struct value_delimeter_t> value_delimeter; +nfp::typed_keyword<cstring, struct namespace_delimeter_t> namespace_delimeter; +} // local namespace + +// ************************************************************************** // +// ************** runtime::file::param_namespace ************** // +// ************************************************************************** // + +class param_namespace { +public: + typedef std::list<parameter>::iterator iterator; + typedef std::list<parameter>::const_iterator const_iterator; + typedef std::list<param_namespace>::iterator sub_ns_iterator; + typedef std::list<param_namespace>::const_iterator sub_ns_const_iterator; + + // Public properties + BOOST_READONLY_PROPERTY( dstring, (param_namespace)) p_name; + unit_test::readonly_property<param_namespace const*> p_parent; + + void load( config_file_iterator cf_it ) { load( cf_it, nfp::no_params ); } + template<typename Modifier> + void load( config_file_iterator cf_it, Modifier const& m ) + { + cstring vm = m.has( value_marker ) ? m[value_marker] : BOOST_RT_PARAM_CSTRING_LITERAL( "\"" ); + cstring vd = m.has( value_delimeter ) ? m[value_delimeter] : BOOST_RT_PARAM_CSTRING_LITERAL( "= \t\n\r" ); + cstring nd = m.has( namespace_delimeter ) ? m[namespace_delimeter] : BOOST_RT_PARAM_CSTRING_LITERAL( "::" ); + + load_impl( cf_it, vm, vd, nd ); + } + void load( cstring file_name ) + { + load( file_name, nfp::no_params ); + } + template<typename Modifier> + void load( cstring file_name, Modifier const& m ) + { + config_file_iterator cfi( file_name, m ); + + load( cfi, m ); + } + + void insert_param( cstring param_name, cstring param_value ); + param_namespace& subnamespace( cstring namespace_name ); // find and insert if not present + void clear(); + + iterator begin() { return m_parameters.begin(); } + const_iterator begin() const { return m_parameters.begin(); } + + iterator end() { return m_parameters.end(); } + const_iterator end() const { return m_parameters.end(); } + + sub_ns_iterator sub_ns_begin() { return m_subnamespaces.begin(); } + sub_ns_const_iterator sub_ns_begin() const { return m_subnamespaces.begin(); } + + sub_ns_iterator sub_ns_end() { return m_subnamespaces.end(); } + sub_ns_const_iterator sub_ns_end() const { return m_subnamespaces.end(); } + + void print_full_name( std::ostream& os ) const; + +protected: + explicit param_namespace( cstring name, param_namespace const* parent = 0 ); + +private: + void load_impl( config_file_iterator cf_it, + cstring value_marker_, cstring value_delimeter_, cstring namespace_delimeter_ ); + + // Data members + std::list<parameter> m_parameters; + std::list<param_namespace> m_subnamespaces; +}; + +//____________________________________________________________________________// + +boost::optional<cstring> +get_param_value( param_namespace const& where_from, + cstring name_part1, + cstring name_part2 = cstring(), + cstring name_part3 = cstring(), + cstring name_part4 = cstring(), + cstring name_part5 = cstring() ); + +//____________________________________________________________________________// + +cstring +get_requ_param_value( param_namespace const& where_from, + cstring name_part1, + cstring name_part2 = cstring(), + cstring name_part3 = cstring(), + cstring name_part4 = cstring(), + cstring name_part5 = cstring() ); + +//____________________________________________________________________________// + +param_namespace const* +get_param_subns( param_namespace const& where_from, + cstring namespace_name ); + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** runtime::file::config_file ************** // +// ************************************************************************** // + +class config_file : public param_namespace { +public: + // Constructor + config_file(); + config_file( cstring file_name ); +}; + +} // namespace file + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_FILE_CONFIG_FILE_HPP_010105GER diff --git a/boost/test/utils/runtime/file/config_file_iterator.cpp b/boost/test/utils/runtime/file/config_file_iterator.cpp new file mode 100644 index 0000000000..18a652474e --- /dev/null +++ b/boost/test/utils/runtime/file/config_file_iterator.cpp @@ -0,0 +1,685 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 54633 $ +// +// Description : flexible configuration file iterator implementation +// *************************************************************************** + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/file/config_file_iterator.hpp> +#include <boost/test/utils/runtime/validation.hpp> + +#ifndef UNDER_CE +#include <boost/test/utils/runtime/env/environment.hpp> +#endif + + +// Boost +#include <boost/utility.hpp> +#include <boost/scoped_array.hpp> +#include <boost/bind.hpp> + +// Boost.Test +#include <boost/test/utils/basic_cstring/compare.hpp> +#include <boost/test/utils/algorithm.hpp> +#include <boost/test/utils/iterator/token_iterator.hpp> +#include <boost/test/utils/assign_op.hpp> + +// STL +#include <memory> +#include <map> +#include <list> +#include <vector> +#include <fstream> +#include <cctype> +#include <iostream> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace file { + +// ************************************************************************** // +// ************** symbol_to_value_map ************** // +// ************************************************************************** // + +template<typename ValueType> +struct symbol_to_value_map : std::map<cstring, ValueType> { + template<typename ParamType> + void add( cstring name, ParamType const& value ) + { + using namespace unit_test; + + m_name_store.push_back( dstring() ); + + assign_op( m_name_store.back(), name, 0 ); + assign_op( (*this)[m_name_store.back()], value, 0 ); + } + void remove( cstring name ) + { + std::list<dstring>::iterator it = std::find( m_name_store.begin(), m_name_store.end(), name ); + + m_name_store.erase( it ); + + erase( name ); + } + +private: + std::list<dstring> m_name_store; +}; + +// ************************************************************************** // +// ************** symbol_table_t ************** // +// ************************************************************************** // + +typedef symbol_to_value_map<dstring> symbol_table_t; + +// ************************************************************************** // +// ************** command_handler_map ************** // +// ************************************************************************** // + +typedef symbol_to_value_map<config_file_iterator::command_handler> command_handler_map; + +// ************************************************************************** // +// ************** is_valid_identifier ************** // +// ************************************************************************** // + +static bool +is_valid_identifier( cstring const& source ) +{ + if( source.is_empty() ) + return false; + + cstring::const_iterator it = source.begin(); + + if( !std::isalpha( *it ) ) + return false; + + while( ++it < source.end() ) { + if( !std::isalnum( *it ) && *it != BOOST_RT_PARAM_LITERAL( '_' ) && *it != BOOST_RT_PARAM_LITERAL( '-' ) ) + return false; + } + + return true; +} + +// ************************************************************************** // +// ************** include_level ************** // +// ************************************************************************** // + +struct include_level; +typedef std::auto_ptr<include_level> include_level_ptr; + +struct include_level : noncopyable +{ + // Constructor + explicit include_level( cstring file_name, cstring path_separators, include_level* parent = 0 ); + + // Data members + std::ifstream m_stream; + location m_curr_location; + include_level_ptr m_parent; +}; + +//____________________________________________________________________________// + +include_level::include_level( cstring file_name, cstring path_separators, include_level* parent_ ) +: m_parent( parent_ ) +{ + if( file_name.is_empty() ) + return; + + assign_op( m_curr_location.first, file_name, 0 ); + m_curr_location.second = 0; + + m_stream.open( m_curr_location.first.c_str() ); + + if( !m_stream.is_open() && !!m_parent.get() ) { + cstring parent_path = m_parent->m_curr_location.first; + cstring::iterator it = unit_test::find_last_of( parent_path.begin(), parent_path.end(), + path_separators.begin(), + path_separators.end() ); + + if( it != parent_path.end() ) { + assign_op( m_curr_location.first, cstring( parent_path.begin(), it+1 ), 0 ); + m_curr_location.first.append( file_name.begin(), file_name.end() ); + m_stream.clear(); + m_stream.open( m_curr_location.first.c_str() ); + } + } + + BOOST_RT_PARAM_VALIDATE_LOGIC( m_stream.is_open(), BOOST_RT_PARAM_LITERAL( "can't open file " ) << file_name ); +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** config_file_iterator::Impl ************** // +// ************************************************************************** // + +struct config_file_iterator::Impl : noncopyable { + // Constructor + Impl(); + + bool get_next_line( cstring& next_line ); + + void process_command_line( cstring line ); + void process_include( cstring line ); + void process_define( cstring line ); + void process_undef( cstring line ); + void process_ifdef( cstring line ); + void process_ifndef( cstring line ); + void process_else( cstring line ); + void process_endif( cstring line ); + + boost::optional<cstring> + get_macro_value( cstring macro_name, bool ignore_missing = true ); + void substitute_macros( cstring& where ); + + bool is_active_line() { return m_inactive_ifdef_level == 0; } + + static bool match_front( cstring str, cstring pattern ) + { + return str.size() >= pattern.size() && str.substr( 0, pattern.size() ) == pattern; + } + static bool match_back( cstring str, cstring pattern ) + { + return str.size() >= pattern.size() && str.substr( str.size() - pattern.size() ) == pattern; + } + + // Configurable parameters + dstring m_path_separators; + char_type m_line_delimeter; + dstring m_sl_comment_delimeter; + dstring m_command_delimeter; + dstring m_line_beak; + dstring m_macro_ref_begin; + dstring m_macro_ref_end; + + dstring m_include_kw; + dstring m_define_kw; + dstring m_undef_kw; + dstring m_ifdef_kw; + dstring m_ifndef_kw; + dstring m_else_kw; + dstring m_endif_kw; + + std::size_t m_buffer_size; + + bool m_trim_trailing_spaces; + bool m_trim_leading_spaces; + bool m_skip_empty_lines; + bool m_detect_missing_macro; + + // Data members + dstring m_post_subst_line; + scoped_array<char> m_buffer; + include_level_ptr m_curr_level; + symbol_table_t m_symbols_table; + std::vector<bool> m_conditional_states; + std::size_t m_inactive_ifdef_level; + command_handler_map m_command_handler_map; +}; + +//____________________________________________________________________________// + +config_file_iterator::Impl::Impl() +: m_path_separators( BOOST_RT_PARAM_LITERAL( "/\\" ) ) +, m_line_delimeter( BOOST_RT_PARAM_LITERAL( '\n' ) ) +, m_sl_comment_delimeter( BOOST_RT_PARAM_LITERAL( "#" ) ) +, m_command_delimeter( BOOST_RT_PARAM_LITERAL( "$" ) ) +, m_line_beak( BOOST_RT_PARAM_LITERAL( "\\" ) ) +, m_macro_ref_begin( BOOST_RT_PARAM_LITERAL( "$" ) ) +, m_macro_ref_end( BOOST_RT_PARAM_LITERAL( "$" ) ) + +, m_include_kw( BOOST_RT_PARAM_LITERAL( "include" ) ) +, m_define_kw( BOOST_RT_PARAM_LITERAL( "define" ) ) +, m_undef_kw( BOOST_RT_PARAM_LITERAL( "undef" ) ) +, m_ifdef_kw( BOOST_RT_PARAM_LITERAL( "ifdef" ) ) +, m_ifndef_kw( BOOST_RT_PARAM_LITERAL( "ifndef" ) ) +, m_else_kw( BOOST_RT_PARAM_LITERAL( "else" ) ) +, m_endif_kw( BOOST_RT_PARAM_LITERAL( "endif" ) ) + +, m_buffer_size( 8192 ) + +, m_trim_trailing_spaces( true ) +, m_trim_leading_spaces( false ) +, m_skip_empty_lines( true ) +, m_detect_missing_macro( true ) + +, m_inactive_ifdef_level( 0 ) +{} + +//____________________________________________________________________________// + +bool +config_file_iterator::Impl::get_next_line( cstring& line ) +{ + bool broken_line = false; + + line.clear(); + + while( !m_curr_level->m_stream.eof() || !!m_curr_level->m_parent.get() ) { + // 10. Switch to upper include level if current one is finished + // 20. Read/append next file line + // 30. Increment line number + // 40. Remove comments + // 50. Remove trailing and leading spaces + // 60. Skip empty string + // 70. Concatenate broken lines if needed. Put the result into line + // 80. If line is not completed, try to finish it by reading the next line + // 90. Process command line + // 100. Substitute macros references with their definitions + // 110. Next line found. + + if( m_curr_level->m_stream.eof() ) { // 10 // + m_curr_level = m_curr_level->m_parent; + continue; + } + + std::ifstream& input = m_curr_level->m_stream; + char_type* buffer_insert_pos = broken_line ? m_buffer.get() + line.size() : m_buffer.get(); + + input.getline( buffer_insert_pos, (std::streamsize)(m_buffer_size - line.size()), // 20 // + m_line_delimeter ); + + cstring next_line( buffer_insert_pos, + input.gcount() > 0 + ? buffer_insert_pos + (input.eof() ? input.gcount() : (input.gcount()-1)) + : buffer_insert_pos ); + + + m_curr_level->m_curr_location.second++; // 30 // + + cstring::size_type comment_pos = next_line.find( m_sl_comment_delimeter ); + if( comment_pos != cstring::npos ) + next_line.trim_right( next_line.begin()+comment_pos ); // 40 // + + if( m_trim_trailing_spaces ) // 50 // + next_line.trim_right(); + if( m_trim_leading_spaces && !broken_line ) + next_line.trim_left(); + + if( next_line.is_empty() ) { // 60 // + if( m_skip_empty_lines ) + continue; + else + next_line.assign( buffer_insert_pos, buffer_insert_pos ); + } + + line = broken_line ? cstring( line.begin(), next_line.end() ) : next_line; // 70 // + + broken_line = match_back( line, m_line_beak ); + if( broken_line ) { // 80 // + line.trim_right( 1 ); + continue; + } + + if( match_front( line, m_command_delimeter ) ) { // 90 // + process_command_line( line ); + continue; + } + + if( !is_active_line() ) + continue; + + substitute_macros( line ); // 100 // + + return true; // 110 // + } + + BOOST_RT_PARAM_VALIDATE_LOGIC( !broken_line, BOOST_RT_PARAM_LITERAL( "broken line is not completed" ) ); + BOOST_RT_PARAM_VALIDATE_LOGIC( m_conditional_states.size() == 0, + BOOST_RT_PARAM_LITERAL( "matching endif command is missing" ) ); + + return false; +} + +//____________________________________________________________________________// + +boost::optional<cstring> +config_file_iterator::Impl::get_macro_value( cstring macro_name, bool ignore_missing ) +{ + symbol_table_t::const_iterator it = m_symbols_table.find( macro_name ); + + if( it == m_symbols_table.end() ) { + boost::optional<cstring> macro_value; // !! variable actually may have different type + + #ifndef UNDER_CE + env::get( macro_name, macro_value ); + #endif + + BOOST_RT_PARAM_VALIDATE_LOGIC( macro_value || ignore_missing || !m_detect_missing_macro, + BOOST_RT_PARAM_LITERAL( "Unknown macro \"" ) << macro_name << BOOST_RT_PARAM_LITERAL( "\"" ) ); + + if( !macro_value ) { + if( !ignore_missing ) + macro_value = cstring(); + } + else + m_symbols_table.add( macro_name, *macro_value ); + + return macro_value; + } + + return boost::optional<cstring>( cstring( it->second ) ); +} + +//____________________________________________________________________________// + +void +config_file_iterator::Impl::process_command_line( cstring line ) +{ + line.trim_left( m_command_delimeter.size() ); + + unit_test::string_token_iterator tit( line, unit_test::max_tokens = 2 ); + + command_handler_map::const_iterator it = m_command_handler_map.find( *tit ); + + BOOST_RT_PARAM_VALIDATE_LOGIC( it != m_command_handler_map.end(), BOOST_RT_PARAM_LITERAL( "Invalid command " ) << *tit ); + + ++tit; + + (it->second)( *tit ); +} + +//____________________________________________________________________________// + +void +config_file_iterator::Impl::process_include( cstring line ) +{ + using namespace unit_test; + + if( !is_active_line() ) + return; + + string_token_iterator tit( line, kept_delimeters = dt_none ); + + BOOST_RT_PARAM_VALIDATE_LOGIC( tit != string_token_iterator(), + BOOST_RT_PARAM_LITERAL( "include file name missing" ) ); + + cstring include_file_name = *tit; + + BOOST_RT_PARAM_VALIDATE_LOGIC( ++tit == string_token_iterator(), + BOOST_RT_PARAM_LITERAL( "unexpected tokens at the end of include command" ) ); + + substitute_macros( include_file_name ); + + m_curr_level.reset( new include_level( include_file_name, m_path_separators, m_curr_level.release() ) ); +} + +//____________________________________________________________________________// + +void +config_file_iterator::Impl::process_define( cstring line ) +{ + using namespace unit_test; + + if( !is_active_line() ) + return; + + string_token_iterator tit( line, (kept_delimeters = dt_none, max_tokens = 2 )); + + cstring macro_name = *tit; + BOOST_RT_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ), + BOOST_RT_PARAM_LITERAL( "invalid macro name" ) ); + + cstring macro_value = *(++tit); + substitute_macros( macro_value ); + + m_symbols_table.add( macro_name, macro_value ); +} + +//____________________________________________________________________________// + +void +config_file_iterator::Impl::process_undef( cstring line ) +{ + if( !is_active_line() ) + return; + + cstring macro_name = line; + BOOST_RT_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ), + BOOST_RT_PARAM_LITERAL( "invalid macro name" ) ); + + m_symbols_table.remove( macro_name ); +} + +//____________________________________________________________________________// + +void +config_file_iterator::Impl::process_ifdef( cstring line ) +{ + m_conditional_states.push_back( true ); + if( !is_active_line() ) + return; + + cstring macro_name = line; + BOOST_RT_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ), + BOOST_RT_PARAM_LITERAL( "invalid macro name" ) ); + + if( !get_macro_value( macro_name ) ) + m_inactive_ifdef_level = m_conditional_states.size(); +} + +//____________________________________________________________________________// + +void +config_file_iterator::Impl::process_ifndef( cstring line ) +{ + m_conditional_states.push_back( true ); + if( !is_active_line() ) + return; + + cstring macro_name = line; + BOOST_RT_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ), + BOOST_RT_PARAM_LITERAL( "invalid macro name" ) ); + + if( get_macro_value( macro_name ) ) + m_inactive_ifdef_level = m_conditional_states.size(); +} + +//____________________________________________________________________________// + +void +config_file_iterator::Impl::process_else( cstring line ) +{ + BOOST_RT_PARAM_VALIDATE_LOGIC( m_conditional_states.size() > 0 && m_conditional_states.back(), + BOOST_RT_PARAM_LITERAL( "else without matching if" ) ); + + m_inactive_ifdef_level = m_conditional_states.size() == m_inactive_ifdef_level ? 0 : m_conditional_states.size(); + + BOOST_RT_PARAM_VALIDATE_LOGIC( line.is_empty(), BOOST_RT_PARAM_LITERAL( "unexpected tokens at the end of else command" ) ); +} + +//____________________________________________________________________________// + +void +config_file_iterator::Impl::process_endif( cstring line ) +{ + BOOST_RT_PARAM_VALIDATE_LOGIC( m_conditional_states.size() > 0, BOOST_RT_PARAM_LITERAL( "endif without matching if" ) ); + + if( m_conditional_states.size() == m_inactive_ifdef_level ) + m_inactive_ifdef_level = 0; + + m_conditional_states.pop_back(); + BOOST_RT_PARAM_VALIDATE_LOGIC( line.is_empty(), BOOST_RT_PARAM_LITERAL( "unexpected tokens at the end of endif command" ) ); +} + +//____________________________________________________________________________// + +void +config_file_iterator::Impl::substitute_macros( cstring& where ) +{ + m_post_subst_line.clear(); + cstring::size_type pos; + + while( (pos = where.find( m_macro_ref_begin )) != cstring::npos ) { + m_post_subst_line.append( where.begin(), pos ); + + where.trim_left( where.begin() + pos + m_macro_ref_begin.size() ); + + pos = where.find( m_macro_ref_end ); + + BOOST_RT_PARAM_VALIDATE_LOGIC( pos != cstring::npos, BOOST_RT_PARAM_LITERAL( "incomplete macro reference" ) ); + + cstring value = *get_macro_value( where.substr( 0, pos ), false ); + m_post_subst_line.append( value.begin(), value.size() ); + + where.trim_left( where.begin() + pos + m_macro_ref_end.size() ); + } + + if( !m_post_subst_line.empty() ) { + m_post_subst_line.append( where.begin(), where.size() ); + where = m_post_subst_line; + } +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** runtime::file::config_file_iterator ************** // +// ************************************************************************** // + +void +config_file_iterator::construct() +{ + m_pimpl.reset( new Impl ); +} + +//____________________________________________________________________________// + +void +config_file_iterator::load( cstring file_name ) +{ + m_pimpl->m_curr_level.reset( new include_level( file_name, m_pimpl->m_path_separators ) ); + m_pimpl->m_buffer.reset( new char[m_pimpl->m_buffer_size] ); + + register_command_handler( m_pimpl->m_include_kw, bind( &Impl::process_include, m_pimpl.get(), _1 ) ); + register_command_handler( m_pimpl->m_define_kw, bind( &Impl::process_define, m_pimpl.get(), _1 ) ); + register_command_handler( m_pimpl->m_undef_kw, bind( &Impl::process_undef, m_pimpl.get(), _1 ) ); + register_command_handler( m_pimpl->m_ifdef_kw, bind( &Impl::process_ifdef, m_pimpl.get(), _1 ) ); + register_command_handler( m_pimpl->m_ifndef_kw, bind( &Impl::process_ifndef, m_pimpl.get(), _1 ) ); + register_command_handler( m_pimpl->m_else_kw, bind( &Impl::process_else, m_pimpl.get(), _1 ) ); + register_command_handler( m_pimpl->m_endif_kw, bind( &Impl::process_endif, m_pimpl.get(), _1 ) ); + + init(); +} + +//____________________________________________________________________________// + +location const& +config_file_iterator::curr_location() +{ + return m_pimpl->m_curr_level->m_curr_location; +} + +//____________________________________________________________________________// + +void +config_file_iterator::register_command_handler( cstring command_kw, command_handler const& ch ) +{ + m_pimpl->m_command_handler_map.add( command_kw, ch ); +} + +//____________________________________________________________________________// + +bool +config_file_iterator::get() +{ + return m_pimpl->get_next_line( m_value ); +} + +//____________________________________________________________________________// + +void +config_file_iterator::set_parameter( rtti::id_t id, cstring value ) +{ + BOOST_RTTI_SWITCH( id ) { + BOOST_RTTI_CASE( cfg_detail::path_separators_t ) + assign_op( m_pimpl->m_path_separators , value, 0 ); + BOOST_RTTI_CASE( cfg_detail::sl_comment_delimeter_t ) + assign_op( m_pimpl->m_sl_comment_delimeter , value, 0 ); + BOOST_RTTI_CASE( cfg_detail::command_delimeter_t ) + assign_op( m_pimpl->m_command_delimeter , value, 0 ); + BOOST_RTTI_CASE( cfg_detail::line_beak_t ) + assign_op( m_pimpl->m_line_beak , value, 0 ); + BOOST_RTTI_CASE( cfg_detail::macro_ref_begin_t ) + assign_op( m_pimpl->m_macro_ref_begin , value, 0 ); + BOOST_RTTI_CASE( cfg_detail::macro_ref_end_t ) + assign_op( m_pimpl->m_macro_ref_end , value, 0 ); + BOOST_RTTI_CASE( cfg_detail::include_kw_t ) + assign_op( m_pimpl->m_include_kw , value, 0 ); + BOOST_RTTI_CASE( cfg_detail::define_kw_t ) + assign_op( m_pimpl->m_define_kw , value, 0 ); + BOOST_RTTI_CASE( cfg_detail::undef_kw_t ) + assign_op( m_pimpl->m_undef_kw , value, 0 ); + BOOST_RTTI_CASE( cfg_detail::ifdef_kw_t ) + assign_op( m_pimpl->m_ifdef_kw , value, 0 ); + BOOST_RTTI_CASE( cfg_detail::ifndef_kw_t ) + assign_op( m_pimpl->m_ifndef_kw , value, 0 ); + BOOST_RTTI_CASE( cfg_detail::else_kw_t ) + assign_op( m_pimpl->m_else_kw , value, 0 ); + BOOST_RTTI_CASE( cfg_detail::endif_kw_t ) + assign_op( m_pimpl->m_endif_kw , value, 0 ); + } +} + +//____________________________________________________________________________// + +void +config_file_iterator::set_parameter( rtti::id_t id, bool value ) +{ + BOOST_RTTI_SWITCH( id ) { + BOOST_RTTI_CASE( cfg_detail::trim_leading_spaces_t ) + m_pimpl->m_trim_leading_spaces = value; + BOOST_RTTI_CASE( cfg_detail::trim_trailing_spaces_t ) + m_pimpl->m_trim_trailing_spaces = value; + BOOST_RTTI_CASE( cfg_detail::skip_empty_lines_t ) + m_pimpl->m_skip_empty_lines = value; + BOOST_RTTI_CASE( cfg_detail::detect_missing_macro_t ) + m_pimpl->m_detect_missing_macro = value; + } +} + +//____________________________________________________________________________// + +void +config_file_iterator::set_parameter( rtti::id_t id, char_type value ) +{ + BOOST_RTTI_SWITCH( id ) { + BOOST_RTTI_CASE( cfg_detail::line_delimeter_t ) + m_pimpl->m_line_delimeter = value; + } +} + +//____________________________________________________________________________// + +void +config_file_iterator::set_parameter( rtti::id_t id, std::size_t value ) +{ + BOOST_RTTI_SWITCH( id ) { + BOOST_RTTI_CASE( cfg_detail::buffer_size_t ) + m_pimpl->m_buffer_size = value; + } +} + +//____________________________________________________________________________// + +} // namespace file + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +// EOF diff --git a/boost/test/utils/runtime/file/config_file_iterator.hpp b/boost/test/utils/runtime/file/config_file_iterator.hpp new file mode 100644 index 0000000000..85467f66ab --- /dev/null +++ b/boost/test/utils/runtime/file/config_file_iterator.hpp @@ -0,0 +1,166 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// Use, modification, and distribution are subject to 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : flexible configuration file iterator definition +// *************************************************************************** + +#ifndef BOOST_RT_FILE_CONFIG_FILE_ITERATOR_HPP_062604GER +#define BOOST_RT_FILE_CONFIG_FILE_ITERATOR_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#include <boost/test/utils/runtime/fwd.hpp> + +// Boost.Test +#include <boost/test/utils/iterator/input_iterator_facade.hpp> +#include <boost/test/utils/callback.hpp> +#include <boost/test/utils/named_params.hpp> + +// Boost +#include <boost/shared_ptr.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +namespace file { + +// Public typedef +typedef std::pair<dstring,long> location; + +// ************************************************************************** // +// ************** modifiers ************** // +// ************************************************************************** // + +namespace cfg_detail { + struct path_separators_t; + struct line_delimeter_t; + struct sl_comment_delimeter_t; + struct command_delimeter_t; + struct line_beak_t; + struct macro_ref_begin_t; + struct macro_ref_end_t; + struct include_kw_t; + struct define_kw_t; + struct undef_kw_t; + struct ifdef_kw_t; + struct ifndef_kw_t; + struct else_kw_t; + struct endif_kw_t; + + struct buffer_size_t; + + struct trim_leading_spaces_t; + struct trim_trailing_spaces_t; + struct skip_empty_lines_t; + struct detect_missing_macro_t; +} // namespace cfg_detail + +namespace { + +nfp::typed_keyword<cstring,cfg_detail::path_separators_t> path_separators; +nfp::typed_keyword<char_type ,cfg_detail::line_delimeter_t> line_delimeter; +nfp::typed_keyword<cstring,cfg_detail::sl_comment_delimeter_t> single_line_comment_delimeter; +nfp::typed_keyword<cstring,cfg_detail::command_delimeter_t> command_delimeter; +nfp::typed_keyword<cstring,cfg_detail::line_beak_t> line_beak; +nfp::typed_keyword<cstring,cfg_detail::macro_ref_begin_t> macro_ref_begin; +nfp::typed_keyword<cstring,cfg_detail::macro_ref_end_t> macro_ref_end; +nfp::typed_keyword<cstring,cfg_detail::include_kw_t> include_kw; +nfp::typed_keyword<cstring,cfg_detail::define_kw_t> define_kw; +nfp::typed_keyword<cstring,cfg_detail::undef_kw_t> undef_kw; +nfp::typed_keyword<cstring,cfg_detail::ifdef_kw_t> ifdef_kw; +nfp::typed_keyword<cstring,cfg_detail::ifndef_kw_t> ifndef_kw; +nfp::typed_keyword<cstring,cfg_detail::else_kw_t> else_kw; +nfp::typed_keyword<cstring,cfg_detail::endif_kw_t> endif_kw; + +nfp::typed_keyword<std::size_t,cfg_detail::buffer_size_t> buffer_size; + +nfp::typed_keyword<bool,cfg_detail::trim_leading_spaces_t> trim_leading_spaces; +nfp::typed_keyword<bool,cfg_detail::trim_trailing_spaces_t> trim_trailing_spaces; +nfp::typed_keyword<bool,cfg_detail::skip_empty_lines_t> skip_empty_lines; +nfp::typed_keyword<bool,cfg_detail::detect_missing_macro_t> detect_missing_macro; + +} // local namespace + +// ************************************************************************** // +// ************** runtime::file::config_file_iterator ************** // +// ************************************************************************** // + +class config_file_iterator : public unit_test::input_iterator_facade<config_file_iterator,cstring,cstring> { + typedef unit_test::input_iterator_facade<config_file_iterator,cstring,cstring> base; +public: + // Public typedefs + typedef unit_test::callback1<cstring> command_handler; + + // Constructors + config_file_iterator() {} + explicit config_file_iterator( cstring file_name ) + { + construct(); + load( file_name ); + } + template<typename Modifiers> + config_file_iterator( cstring file_name, Modifiers const& m ) + { + construct(); + m.apply_to( *this ); + load( file_name ); + } + config_file_iterator( config_file_iterator const& rhs ) + : base( rhs ) + , m_pimpl( rhs.m_pimpl ) + { + rhs.m_valid = false; + } + + void operator=( config_file_iterator const& rhs ) + { + if( this == &rhs ) + return; + + (base&)(*this) = rhs; + m_pimpl = rhs.m_pimpl; + rhs.m_valid = false; + } // Assignment + + + // Access methods + location const& curr_location(); + void register_command_handler( cstring command_kw, command_handler const& ); + + // Parameters setters + void set_parameter( rtti::id_t, cstring ); + void set_parameter( rtti::id_t, bool ); + void set_parameter( rtti::id_t, char_type ); + void set_parameter( rtti::id_t, std::size_t ); + +private: + friend class unit_test::input_iterator_core_access; + + void construct(); + void load( cstring file_name ); + + // increment implementation + bool get(); + + // Data members + struct Impl; + shared_ptr<Impl> m_pimpl; +}; + +} // namespace file + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_FILE_CONFIG_FILE_ITERATOR_HPP_062604GER diff --git a/boost/test/utils/runtime/fwd.hpp b/boost/test/utils/runtime/fwd.hpp new file mode 100644 index 0000000000..8d298d7220 --- /dev/null +++ b/boost/test/utils/runtime/fwd.hpp @@ -0,0 +1,41 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : global framework level forward declaration +// *************************************************************************** + +#ifndef BOOST_RT_FWD_HPP_062604GER +#define BOOST_RT_FWD_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +// Boost +#include <boost/shared_ptr.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +class parameter; + +class argument; +typedef shared_ptr<argument> argument_ptr; +typedef shared_ptr<argument const> const_argument_ptr; + +template<typename T> class value_interpreter; +template<typename T> class typed_argument; + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_FWD_HPP_062604GER diff --git a/boost/test/utils/runtime/interpret_argument_value.hpp b/boost/test/utils/runtime/interpret_argument_value.hpp new file mode 100644 index 0000000000..cbf752dd5b --- /dev/null +++ b/boost/test/utils/runtime/interpret_argument_value.hpp @@ -0,0 +1,163 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : default algorithms for string to specific type convertions +// *************************************************************************** + +#ifndef BOOST_RT_INTERPRET_ARGUMENT_VALUE_HPP_062604GER +#define BOOST_RT_INTERPRET_ARGUMENT_VALUE_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> +#include <boost/test/utils/runtime/trace.hpp> + +// Boost.Test +#include <boost/test/utils/basic_cstring/io.hpp> +#include <boost/test/utils/basic_cstring/compare.hpp> + +// Boost +#include <boost/optional.hpp> +#include <boost/lexical_cast.hpp> + +// STL +// !! could we eliminate these includes? +#include <list> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +// ************************************************************************** // +// ************** runtime::interpret_argument_value ************** // +// ************************************************************************** // +// returns true if source is used false otherwise + +// generic case +template<typename T> +struct interpret_argument_value_impl { + static bool _( cstring source, boost::optional<T>& res ) + { + BOOST_RT_PARAM_TRACE( "In interpret_argument_value_impl<" << typeid(T).name() << ">" ); + + res = lexical_cast<T>( source ); + + BOOST_RT_PARAM_TRACE( "String " << source << " is interpreted as " << *res ); + return true; + } +}; + + +//____________________________________________________________________________// + +// dstring case +template<> +struct interpret_argument_value_impl<dstring> { + static bool _( cstring source, boost::optional<dstring>& res ) + { + BOOST_RT_PARAM_TRACE( "In interpret_argument_value_impl<dstring>" ); + + res = dstring(); + assign_op( *res, source, 0 ); + + return true; + } +}; + +//____________________________________________________________________________// + +// cstring case +template<> +struct interpret_argument_value_impl<cstring> { + static bool _( cstring source, boost::optional<cstring>& res ) + { + BOOST_RT_PARAM_TRACE( "In interpret_argument_value_impl<cstring>" ); + + res = source; + + return true; + } +}; + +//____________________________________________________________________________// + +// specialization for type bool +template<> +struct interpret_argument_value_impl<bool> { + static bool _( cstring source, boost::optional<bool>& res ) + { + BOOST_RT_PARAM_TRACE( "In interpret_argument_value_impl<bool>" ); + + static literal_cstring YES( BOOST_RT_PARAM_CSTRING_LITERAL( "YES" ) ); + static literal_cstring Y( BOOST_RT_PARAM_CSTRING_LITERAL( "Y" ) ); + static literal_cstring NO( BOOST_RT_PARAM_CSTRING_LITERAL( "NO" ) ); + static literal_cstring N( BOOST_RT_PARAM_CSTRING_LITERAL( "N" ) ); + static literal_cstring one( BOOST_RT_PARAM_CSTRING_LITERAL( "1" ) ); + static literal_cstring zero( BOOST_RT_PARAM_CSTRING_LITERAL( "0" ) ); + + source.trim(); + + if( case_ins_eq( source, YES ) || case_ins_eq( source, Y ) || case_ins_eq( source, one ) ) { + res = true; + return true; + } + else if( case_ins_eq( source, NO ) || case_ins_eq( source, N ) || case_ins_eq( source, zero ) ) { + res = false; + return true; + } + else { + res = true; + return false; + } + } +}; + +//____________________________________________________________________________// + +template<typename T> +inline bool +interpret_argument_value( cstring source, boost::optional<T>& res, long ) +{ + return interpret_argument_value_impl<T>::_( source, res ); +} + +//____________________________________________________________________________// + +// specialization for list of values +template<typename T> +inline bool +interpret_argument_value( cstring source, boost::optional<std::list<T> >& res, int ) +{ + BOOST_RT_PARAM_TRACE( "In interpret_argument_value<std::list<T>>" ); + + res = std::list<T>(); + + while( !source.is_empty() ) { + // !! should we use token_iterator + cstring::iterator single_value_end = std::find( source.begin(), source.end(), BOOST_RT_PARAM_LITERAL( ',' ) ); + + boost::optional<T> value; + interpret_argument_value( cstring( source.begin(), single_value_end ), value, 0 ); + + res->push_back( *value ); + + source.trim_left( single_value_end + 1 ); + } + + return true; +} + +//____________________________________________________________________________// + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_INTERPRET_ARGUMENT_VALUE_HPP_062604GER diff --git a/boost/test/utils/runtime/parameter.hpp b/boost/test/utils/runtime/parameter.hpp new file mode 100644 index 0000000000..9baf561ca5 --- /dev/null +++ b/boost/test/utils/runtime/parameter.hpp @@ -0,0 +1,38 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : abstract interface for the formal parameter +// *************************************************************************** + +#ifndef BOOST_RT_PARAMETER_HPP_062604GER +#define BOOST_RT_PARAMETER_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +// ************************************************************************** // +// ************** runtime::parameter ************** // +// ************************************************************************** // + +class parameter { +public: + virtual ~parameter() {} +}; + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_PARAMETER_HPP_062604GER diff --git a/boost/test/utils/runtime/trace.hpp b/boost/test/utils/runtime/trace.hpp new file mode 100644 index 0000000000..ba15eb6341 --- /dev/null +++ b/boost/test/utils/runtime/trace.hpp @@ -0,0 +1,30 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : optional internal tracing +// *************************************************************************** + +#ifndef BOOST_RT_TRACE_HPP_062604GER +#define BOOST_RT_TRACE_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +#ifdef BOOST_RT_PARAM_DEBUG + +#include <iostream> + +# define BOOST_RT_PARAM_TRACE( str ) std::cerr << str << std::endl +#else +# define BOOST_RT_PARAM_TRACE( str ) +#endif + +#endif // BOOST_RT_TRACE_HPP_062604GER diff --git a/boost/test/utils/runtime/validation.hpp b/boost/test/utils/runtime/validation.hpp new file mode 100644 index 0000000000..ff8e4691db --- /dev/null +++ b/boost/test/utils/runtime/validation.hpp @@ -0,0 +1,82 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : defines exceptions and validation tools +// *************************************************************************** + +#ifndef BOOST_RT_VALIDATION_HPP_062604GER +#define BOOST_RT_VALIDATION_HPP_062604GER + +// Boost.Runtime.Parameter +#include <boost/test/utils/runtime/config.hpp> + +// Boost.Test +#include <boost/test/utils/class_properties.hpp> + +// Boost +#include <boost/shared_ptr.hpp> + +// STL +#ifdef BOOST_RT_PARAM_EXCEPTION_INHERIT_STD +#include <stdexcept> +#endif + +namespace boost { + +namespace BOOST_RT_PARAM_NAMESPACE { + +// ************************************************************************** // +// ************** runtime::logic_error ************** // +// ************************************************************************** // + +class logic_error +#ifdef BOOST_RT_PARAM_EXCEPTION_INHERIT_STD +: public std::exception +#endif +{ + typedef shared_ptr<dstring> dstring_ptr; +public: + // Constructor // !! could we eliminate shared_ptr + explicit logic_error( cstring msg ) : m_msg( new dstring( msg.begin(), msg.size() ) ) {} + ~logic_error() throw() {} + + dstring const& msg() const { return *m_msg; } + virtual char_type const* what() const throw() { return m_msg->c_str(); } + +private: + dstring_ptr m_msg; +}; + +// ************************************************************************** // +// ************** runtime::report_logic_error ************** // +// ************************************************************************** // + +inline void +report_logic_error( format_stream& msg ) +{ + throw BOOST_RT_PARAM_NAMESPACE::logic_error( msg.str() ); +} + +//____________________________________________________________________________// + +#define BOOST_RT_PARAM_REPORT_LOGIC_ERROR( msg ) \ + boost::BOOST_RT_PARAM_NAMESPACE::report_logic_error( format_stream().ref() << msg ) + +#define BOOST_RT_PARAM_VALIDATE_LOGIC( b, msg ) \ + if( b ) {} else BOOST_RT_PARAM_REPORT_LOGIC_ERROR( msg ) + +//____________________________________________________________________________// + +} // namespace BOOST_RT_PARAM_NAMESPACE + +} // namespace boost + +#endif // BOOST_RT_VALIDATION_HPP_062604GER diff --git a/boost/test/utils/trivial_singleton.hpp b/boost/test/utils/trivial_singleton.hpp new file mode 100644 index 0000000000..1ce7797778 --- /dev/null +++ b/boost/test/utils/trivial_singleton.hpp @@ -0,0 +1,74 @@ +// (C) Copyright Gennadiy Rozental 2005-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : simple helpers for creating cusom output manipulators +// *************************************************************************** + +#ifndef BOOST_TEST_TRIVIAL_SIGNLETON_HPP_020505GER +#define BOOST_TEST_TRIVIAL_SIGNLETON_HPP_020505GER + +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> + +#include <boost/noncopyable.hpp> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +// ************************************************************************** // +// ************** singleton ************** // +// ************************************************************************** // + +template<typename Derived> +class singleton : private boost::noncopyable { +public: + static Derived& instance() { static Derived the_inst; return the_inst; } +protected: + singleton() {} + ~singleton() {} +}; + +} // namespace unit_test + +#define BOOST_TEST_SINGLETON_CONS( type ) \ +friend class boost::unit_test::singleton<type>; \ +type() {} \ +/**/ + +#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) + +#define BOOST_TEST_SINGLETON_INST( inst ) \ +template class unit_test::singleton< BOOST_JOIN( inst, _t ) > ; \ +namespace { BOOST_JOIN( inst, _t)& inst = BOOST_JOIN( inst, _t)::instance(); } + +#elif defined(__APPLE_CC__) && defined(__GNUC__) && __GNUC__ < 4 +#define BOOST_TEST_SINGLETON_INST( inst ) \ +static BOOST_JOIN( inst, _t)& inst = BOOST_JOIN (inst, _t)::instance(); + +#else + +#define BOOST_TEST_SINGLETON_INST( inst ) \ +namespace { BOOST_JOIN( inst, _t)& inst = BOOST_JOIN( inst, _t)::instance(); } + +#endif + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_TEST_TRIVIAL_SIGNLETON_HPP_020505GER diff --git a/boost/test/utils/wrap_stringstream.hpp b/boost/test/utils/wrap_stringstream.hpp new file mode 100644 index 0000000000..a3eaff1c8c --- /dev/null +++ b/boost/test/utils/wrap_stringstream.hpp @@ -0,0 +1,164 @@ +// (C) Copyright Gennadiy Rozental 2002-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 49312 $ +// +// Description : wraps strstream and stringstream (depends with one is present) +// to provide the unified interface +// *************************************************************************** + +#ifndef BOOST_WRAP_STRINGSTREAM_HPP_071894GER +#define BOOST_WRAP_STRINGSTREAM_HPP_071894GER + +// Boost.Test +#include <boost/test/detail/config.hpp> + +// STL +#ifdef BOOST_NO_STRINGSTREAM +#include <strstream> // for std::ostrstream +#else +#include <sstream> // for std::ostringstream +#endif // BOOST_NO_STRINGSTREAM + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +// ************************************************************************** // +// ************** basic_wrap_stringstream ************** // +// ************************************************************************** // + +template<typename CharT> +class basic_wrap_stringstream { +public: +#if defined(BOOST_CLASSIC_IOSTREAMS) + typedef std::ostringstream wrapped_stream; +#elif defined(BOOST_NO_STRINGSTREAM) + typedef std::basic_ostrstream<CharT> wrapped_stream; +#else + typedef std::basic_ostringstream<CharT> wrapped_stream; +#endif // BOOST_NO_STRINGSTREAM + // Access methods + basic_wrap_stringstream& ref(); + wrapped_stream& stream(); + std::basic_string<CharT> const& str(); + +private: + // Data members + wrapped_stream m_stream; + std::basic_string<CharT> m_str; +}; + +//____________________________________________________________________________// + +template <typename CharT, typename T> +inline basic_wrap_stringstream<CharT>& +operator<<( basic_wrap_stringstream<CharT>& targ, T const& t ) +{ + targ.stream() << t; + return targ; +} + +//____________________________________________________________________________// + +template <typename CharT> +inline typename basic_wrap_stringstream<CharT>::wrapped_stream& +basic_wrap_stringstream<CharT>::stream() +{ + return m_stream; +} + +//____________________________________________________________________________// + +template <typename CharT> +inline basic_wrap_stringstream<CharT>& +basic_wrap_stringstream<CharT>::ref() +{ + return *this; +} + +//____________________________________________________________________________// + +template <typename CharT> +inline std::basic_string<CharT> const& +basic_wrap_stringstream<CharT>::str() +{ + +#ifdef BOOST_NO_STRINGSTREAM + m_str.assign( m_stream.str(), m_stream.pcount() ); + m_stream.freeze( false ); +#else + m_str = m_stream.str(); +#endif + + return m_str; +} + +//____________________________________________________________________________// + +template <typename CharT> +inline basic_wrap_stringstream<CharT>& +operator<<( basic_wrap_stringstream<CharT>& targ, basic_wrap_stringstream<CharT>& src ) +{ + targ << src.str(); + return targ; +} + +//____________________________________________________________________________// + +#if BOOST_TEST_USE_STD_LOCALE + +template <typename CharT> +inline basic_wrap_stringstream<CharT>& +operator<<( basic_wrap_stringstream<CharT>& targ, std::ios_base& (BOOST_TEST_CALL_DECL *man)(std::ios_base&) ) +{ + targ.stream() << man; + return targ; +} + +//____________________________________________________________________________// + +template<typename CharT,typename Elem,typename Tr> +inline basic_wrap_stringstream<CharT>& +operator<<( basic_wrap_stringstream<CharT>& targ, std::basic_ostream<Elem,Tr>& (BOOST_TEST_CALL_DECL *man)(std::basic_ostream<Elem, Tr>&) ) +{ + targ.stream() << man; + return targ; +} + +//____________________________________________________________________________// + +template<typename CharT,typename Elem,typename Tr> +inline basic_wrap_stringstream<CharT>& +operator<<( basic_wrap_stringstream<CharT>& targ, std::basic_ios<Elem, Tr>& (BOOST_TEST_CALL_DECL *man)(std::basic_ios<Elem, Tr>&) ) +{ + targ.stream() << man; + return targ; +} + +//____________________________________________________________________________// + +#endif + +// ************************************************************************** // +// ************** wrap_stringstream ************** // +// ************************************************************************** // + +typedef basic_wrap_stringstream<char> wrap_stringstream; +typedef basic_wrap_stringstream<wchar_t> wrap_wstringstream; + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_WRAP_STRINGSTREAM_HPP_071894GER diff --git a/boost/test/utils/xml_printer.hpp b/boost/test/utils/xml_printer.hpp new file mode 100644 index 0000000000..7fd851d520 --- /dev/null +++ b/boost/test/utils/xml_printer.hpp @@ -0,0 +1,118 @@ +// (C) Copyright Gennadiy Rozental 2004-2008. +// 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) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision: 57992 $ +// +// Description : common code used by any agent serving as XML printer +// *************************************************************************** + +#ifndef BOOST_TEST_XML_PRINTER_HPP_071894GER +#define BOOST_TEST_XML_PRINTER_HPP_071894GER + +// Boost.Test +#include <boost/test/utils/basic_cstring/basic_cstring.hpp> +#include <boost/test/utils/fixed_mapping.hpp> +#include <boost/test/utils/custom_manip.hpp> +#include <boost/test/utils/foreach.hpp> +#include <boost/test/utils/basic_cstring/io.hpp> + +// Boost +#include <boost/config.hpp> + +// STL +#include <iostream> + +#include <boost/test/detail/suppress_warnings.hpp> + +//____________________________________________________________________________// + +namespace boost { + +namespace unit_test { + +// ************************************************************************** // +// ************** xml print helpers ************** // +// ************************************************************************** // + +inline void +print_escaped( std::ostream& where_to, const_string value ) +{ + static fixed_mapping<char,char const*> char_type( + '<' , "lt", + '>' , "gt", + '&' , "amp", + '\'', "apos" , + '"' , "quot", + + 0 + ); + + BOOST_TEST_FOREACH( char, c, value ) { + char const* ref = char_type[c]; + + if( ref ) + where_to << '&' << ref << ';'; + else + where_to << c; + } +} + +//____________________________________________________________________________// + +inline void +print_escaped( std::ostream& where_to, std::string const& value ) +{ + print_escaped( where_to, const_string( value ) ); +} + +//____________________________________________________________________________// + +template<typename T> +inline void +print_escaped( std::ostream& where_to, T const& value ) +{ + where_to << value; +} + +//____________________________________________________________________________// + +typedef custom_manip<struct attr_value_t> attr_value; + +template<typename T> +inline std::ostream& +operator<<( custom_printer<attr_value> const& p, T const& value ) +{ + *p << "=\""; + print_escaped( *p, value ); + *p << '"'; + + return *p; +} + +//____________________________________________________________________________// + +typedef custom_manip<struct cdata_t> cdata; + +inline std::ostream& +operator<<( custom_printer<cdata> const& p, const_string value ) +{ + return *p << BOOST_TEST_L( "<![CDATA[" ) << value << BOOST_TEST_L( "]]>" ); +} + +//____________________________________________________________________________// + +} // namespace unit_test + +} // namespace boost + +//____________________________________________________________________________// + +#include <boost/test/detail/enable_warnings.hpp> + +#endif // BOOST_TEST_XML_PRINTER_HPP_071894GER |