2
0
mirror of https://github.com/boostorg/test.git synced 2026-01-28 07:42:12 +00:00

input_iterator_adaptor simplified

token_iterator added


[SVN r23028]
This commit is contained in:
Gennadiy Rozental
2004-06-05 11:03:12 +00:00
parent e0e1117fcf
commit 4df2d9d3c1
4 changed files with 645 additions and 99 deletions

View File

@@ -35,7 +35,7 @@ template<typename CharT>
class ifstream_holder {
public:
// Constructor
explicit ifstream_holder( basic_cstring<CharT> file_name )
explicit ifstream_holder( basic_cstring<CharT const> file_name )
{
if( file_name.is_empty() )
return;
@@ -60,10 +60,10 @@ template<typename CharT>
class basic_ifstream_line_iterator : detail::ifstream_holder<CharT>, public basic_istream_line_iterator<CharT>
{
public:
basic_ifstream_line_iterator( basic_cstring<CharT> file_name, CharT delimeter )
basic_ifstream_line_iterator( basic_cstring<CharT const> file_name, CharT delimeter )
: detail::ifstream_holder<CharT>( file_name ), basic_istream_line_iterator<CharT>( this->m_stream, delimeter ) {}
explicit basic_ifstream_line_iterator( basic_cstring<CharT> file_name = basic_cstring<CharT>() )
explicit basic_ifstream_line_iterator( basic_cstring<CharT const> file_name = basic_cstring<CharT const>() )
: detail::ifstream_holder<CharT>( file_name ), basic_istream_line_iterator<CharT>( this->m_stream ) {}
};
@@ -78,6 +78,10 @@ typedef basic_ifstream_line_iterator<wchar_t> wifstream_line_iterator;
// Revision History :
//
// $Log$
// Revision 1.4 2004/06/05 11:03:12 rogeeff
// input_iterator_adaptor simplified
// token_iterator added
//
// Revision 1.3 2004/05/27 07:01:49 rogeeff
// portability workarounds
//

View File

@@ -17,79 +17,49 @@
// Boost
#include <boost/iterator/iterator_facade.hpp>
#include <boost/mpl/void.hpp>
#include <boost/mpl/if.hpp>
namespace boost {
namespace unit_test {
namespace detail {
// ************************************************************************** //
// ************** input_iterator_core_access ************** //
// ************************************************************************** //
template<typename T>
struct value_type_ident
class input_iterator_core_access
{
typedef T value_type;
};
#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<typename T>
struct ref_type_ident
{
typedef T reference;
};
template <class Facade>
static bool get( Facade& f )
{
return f.get();
}
} // namespace detail
private:
// objects of this class are useless
input_iterator_core_access(); //undefined
};
// ************************************************************************** //
// ************** input_iterator_facade ************** //
// ************************************************************************** //
template<typename ImplPolicy,typename Derived = mpl::void_,typename ValueType = mpl::void_,typename Reference = mpl::void_>
class input_iterator_facade : public iterator_facade<
typename mpl::if_<mpl::is_void_<Derived>,input_iterator_facade<ImplPolicy>,Derived>::type,
typename mpl::if_<mpl::is_void_<ValueType>,ImplPolicy,detail::value_type_ident<ValueType> >::type::value_type,
forward_traversal_tag,
typename mpl::if_<mpl::is_void_<Reference>,ImplPolicy,detail::ref_type_ident<Reference> >::type::reference>
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
explicit input_iterator_facade( ImplPolicy const& p = ImplPolicy() )
: m_policy( p )
{
increment();
}
//!! copy constructor/assigment - should we make rhs invalid after copy??
// input_iterator_facade( input_iterator_facade const& rhs )
// : m_policy( rhs.m_policy ), m_valid( rhs.m_valid )
// {
// const_cast<input_iterator_adaptor&>( rhs ).m_valid = false;
// }
//
// void operator=( input_iterator_facade const& rhs )
// {
// m_policies = rhs.p_policies;
// m_valid = rhs.m_valid;
//
// const_cast<input_iterator_adaptor&>( rhs ).m_valid = false;
// }
//!! do we need reset method?
// void reset()
// {
// m_valid = m_policy.intialize();
//
// increment();
// }
protected: // provide access to the derived
// Data members
ImplPolicy m_policy;
private:
typedef typename mpl::if_<mpl::is_void_<ValueType>,detail::value_type_ident<ValueType>,ImplPolicy>::type::value_type value_type;
typedef typename mpl::if_<mpl::is_void_<Reference>,ImplPolicy,detail::ref_type_ident<Reference> >::type::reference reference;
input_iterator_facade() : m_valid( false ), m_value() {}
protected:
friend class iterator_core_access;
// iterator facade interface implementation
@@ -97,23 +67,31 @@ private:
{
// we make post-end incrementation indefinetly safe
if( m_valid )
m_valid = m_policy.get();
m_valid = input_iterator_core_access::get( *static_cast<Derived*>(this) );
}
bool equal( input_iterator_facade const& rhs ) const
Reference dereference() const
{
// two invalid iterator equals, two valid need to be compared, invalid never equal to valid
return !m_valid && !rhs.m_valid || m_valid && rhs.m_valid && m_policy.equal( rhs.m_policy );
return m_value;
}
reference dereference() const
{
//!! should we call some kind of assert( m_valid ) here instead or do nothing???
// we pass m_valid inside the policy to decide what to do on attempt to dereference invalid iterator
return m_policy.dereference( m_valid );
protected: // provide access to the Derived
void init()
{
m_valid = true;
increment();
}
// Data members
bool m_valid;
ValueType m_value;
private:
// 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
@@ -124,6 +102,10 @@ private:
// Revision History :
//
// $Log$
// Revision 1.3 2004/06/05 11:03:12 rogeeff
// input_iterator_adaptor simplified
// token_iterator added
//
// Revision 1.2 2004/05/25 10:29:09 rogeeff
// use standard getline
// eliminate initialize

View File

@@ -18,7 +18,6 @@
// Boost
#include <boost/test/detail/basic_cstring/basic_cstring.hpp>
#include <boost/test/detail/iterator/input_iterator_facade.hpp>
#include <boost/shared_array.hpp>
// STL
#include <iosfwd>
@@ -31,44 +30,42 @@ namespace unit_test {
// ************** basic_istream_line_iterator ************** //
// ************************************************************************** //
namespace detail {
template<typename CharT>
class istream_line_iterator_impl {
public:
typedef basic_cstring<CharT const> value_type;
typedef basic_cstring<CharT const> reference;
istream_line_iterator_impl( std::basic_istream<CharT>& input, CharT delimeter )
: m_input_stream( &input ), m_delimeter( delimeter ) {}
bool get() { return std::getline( *m_input_stream, m_buffer, m_delimeter ); }
reference dereference( bool valid ) const { return m_buffer; }
bool equal( istream_line_iterator_impl const& ) const { return false; }
private:
// Data members
std::basic_istream<CharT>* m_input_stream;
std::basic_string<CharT> m_buffer;
CharT m_delimeter;
};
} // namespace detail
//!! Should we support policy based delimitation
template<typename CharT>
class basic_istream_line_iterator
: public input_iterator_facade<detail::istream_line_iterator_impl<CharT>,basic_istream_line_iterator<CharT> > {
typedef detail::istream_line_iterator_impl<CharT> impl;
typedef input_iterator_facade<impl,basic_istream_line_iterator<CharT> > base;
: 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;
public:
// Constructor
// Constructors
basic_istream_line_iterator() {}
basic_istream_line_iterator( std::basic_istream<CharT>& input, CharT delimeter )
: base( impl( input, delimeter ) ) {}
: m_input_stream( &input ), m_delimeter( delimeter )
{
init();
}
explicit basic_istream_line_iterator( std::basic_istream<CharT>& input )
: base( impl( input, input.widen( '\n' ) ) ) {}
: m_input_stream( &input ), m_delimeter( input.widen( '\n' ) )
{
init();
}
private:
friend class input_iterator_core_access;
// increment implementation
bool get()
{
return std::getline( *m_input_stream, m_value, m_delimeter );
}
// Data members
std::basic_istream<CharT>* m_input_stream;
CharT m_delimeter;
};
typedef basic_istream_line_iterator<char> istream_line_iterator;
@@ -82,6 +79,10 @@ typedef basic_istream_line_iterator<wchar_t> wistream_line_iterator;
// Revision History :
//
// $Log$
// Revision 1.4 2004/06/05 11:03:12 rogeeff
// input_iterator_adaptor simplified
// token_iterator added
//
// Revision 1.3 2004/05/27 07:01:49 rogeeff
// portability workarounds
//

View File

@@ -0,0 +1,559 @@
// (C) Copyright Gennadiy Rozental 2004.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description :
// ***************************************************************************
#ifndef BOOST_TOKEN_ITERATOR_HPP
#define BOOST_TOKEN_ITERATOR_HPP
// Boost
#include <boost/iterator/iterator_categories.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/test/detail/iterator/input_iterator_facade.hpp>
#include <boost/test/detail/basic_cstring/basic_cstring.hpp>
// STL
#include <iosfwd>
#include <cctype>
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std{ using ::ispunct; using ::isspace; }
#endif
namespace boost {
namespace unit_test {
// ************************************************************************** //
// ************** ti_delimeter_type ************** //
// ************************************************************************** //
enum ti_delimeter_type { use_delim, use_ispunct, use_isspace };
namespace detail {
// ************************************************************************** //
// ************** 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 = use_delim ) : m_type( t ) {}
explicit delim_policy( cstring d, ti_delimeter_type t )
{
use_delimeters( d, t );
}
void use_delimeters( cstring d, ti_delimeter_type t )
{
m_delimeters = d;
m_type = d.is_empty() ? t : use_delim;
}
bool operator()( CharT c )
{
switch( m_type ) {
case use_delim: {
typename cstring::iterator it = m_delimeters.begin();
for( ; it != m_delimeters.end(); ++it )
if( CharCompare()( *it, c ) )
break;
return it != m_delimeters.end();
}
case use_ispunct: return (std::ispunct)( c ) != 0;
case use_isspace: return (std::isspace)( c ) != 0;
}
return false;
}
// Data members
cstring m_delimeters;
ti_delimeter_type m_type;
};
// ************************************************************************** //
// ************** token_assigner ************** //
// ************************************************************************** //
template<typename TraversalTag>
struct token_assigner {
template<typename Iterator, typename Token>
static void assign( Iterator b, Iterator e, Token& t ) { t.assign( b, e ); }
template<typename Iterator, typename Token>
static void append_move( Iterator& b, Token& t ) { ++b; }
template<typename Token>
static void clear( Token& t ) {}
};
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; }
template<typename Token>
static void clear( Token& t ) { t.clear(); }
};
// ************************************************************************** //
// ************** default_char_compare ************** //
// ************************************************************************** //
template<typename CharT>
class default_char_compare {
public:
bool operator()( CharT c1, CharT c2 )
{
#if BOOST_WORKAROUND(__GNUC__, < 3) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
return std::string_char_traits<CharT>::eq( c1, c2 );
#else
return std::char_traits<CharT>::eq( c1, c2 );
#endif
}
};
// ************************************************************************** //
// ************** dropped_delimeters_m ************** //
// ************************************************************************** //
template<typename CharT>
struct dropped_delimeters_m
{
explicit dropped_delimeters_m( basic_cstring<CharT const> delims )
: m_delims( delims ) {}
template<typename CharCompare>
void apply( delim_policy<CharT,CharCompare>& is_drop, delim_policy<CharT,CharCompare>&, bool ) const
{
is_drop.use_delimeters( m_delims, use_isspace );
}
basic_cstring<CharT const> m_delims;
};
//____________________________________________________________________________//
template<>
struct dropped_delimeters_m<ti_delimeter_type>
{
explicit dropped_delimeters_m( ti_delimeter_type type )
: m_type( type ) {}
template<typename CharT, typename CharCompare>
void apply( delim_policy<CharT,CharCompare>& is_drop, delim_policy<CharT,CharCompare>&, bool ) const
{
is_drop.use_delimeters( "", m_type );
}
ti_delimeter_type m_type;
};
//____________________________________________________________________________//
// ************************************************************************** //
// ************** kept_delimeters_m ************** //
// ************************************************************************** //
template<typename CharT>
struct kept_delimeters_m
{
explicit kept_delimeters_m( basic_cstring<CharT const> delims, ti_delimeter_type type = use_ispunct )
: m_delims( delims ), m_type( type ) {}
template<typename CharCompare>
void apply( delim_policy<CharT,CharCompare>&, delim_policy<CharT,CharCompare>& is_kept, bool ) const
{
is_kept.use_delimeters( m_delims, m_type );
}
basic_cstring<CharT const> m_delims;
ti_delimeter_type m_type;
};
//____________________________________________________________________________//
template<>
struct kept_delimeters_m<ti_delimeter_type>
{
explicit kept_delimeters_m( ti_delimeter_type type )
: m_type( type ) {}
template<typename CharT, typename CharCompare>
void apply( delim_policy<CharT,CharCompare>&, delim_policy<CharT,CharCompare>& is_kept, bool ) const
{
is_kept.use_delimeters( "", m_type );
}
ti_delimeter_type m_type;
};
//____________________________________________________________________________//
// ************************************************************************** //
// ************** keep_empty_tokens_m ************** //
// ************************************************************************** //
struct keep_empty_tokens_m
{
explicit keep_empty_tokens_m( bool v )
: m_keep_empty_tokens( v ) {}
template<typename CharT,typename CharCompare>
void apply( delim_policy<CharT,CharCompare>&, delim_policy<CharT,CharCompare>&, bool& keep_empty_tokens ) const
{
keep_empty_tokens = m_keep_empty_tokens;
}
bool m_keep_empty_tokens;
};
} // namespace detail
// ************************************************************************** //
// ************** modifiers generators ************** //
// ************************************************************************** //
static struct dropped_delimeters_generator {
template<typename CharT>
detail::dropped_delimeters_m<CharT>
operator=( basic_cstring<CharT const> d ) { return detail::dropped_delimeters_m<CharT>( d ); }
template<typename CharT>
detail::dropped_delimeters_m<CharT>
operator=( CharT const* d ) { return detail::dropped_delimeters_m<CharT>( basic_cstring<CharT const>( d ) ); }
detail::dropped_delimeters_m<ti_delimeter_type>
operator=( ti_delimeter_type t ) { return detail::dropped_delimeters_m<ti_delimeter_type>( t ); }
} dropped_delimeters;
//____________________________________________________________________________//
static struct kept_delimeters_generator {
template<typename CharT>
detail::kept_delimeters_m<CharT>
operator=( basic_cstring<CharT const> d ) { return detail::kept_delimeters_m<CharT>( d ); }
template<typename CharT>
detail::kept_delimeters_m<CharT>
operator=( CharT const* d ) { return detail::kept_delimeters_m<CharT>( basic_cstring<CharT const>( d ) ); }
detail::kept_delimeters_m<ti_delimeter_type>
operator=( ti_delimeter_type t ) { return detail::kept_delimeters_m<ti_delimeter_type>( t ); }
} kept_delimeters;
//____________________________________________________________________________//
static struct keep_empty_tokens_generator : detail::keep_empty_tokens_m {
keep_empty_tokens_generator() : detail::keep_empty_tokens_m( true ) {}
detail::keep_empty_tokens_m
operator=( bool v ) { return detail::keep_empty_tokens_m( v ); }
} keep_empty_tokens;
//____________________________________________________________________________//
// ************************************************************************** //
// ************** token_iterator_base ************** //
// ************************************************************************** //
template<typename Derived,
typename CharT,
typename CharCompare = 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 detail::delim_policy<CharT,CharCompare> delim_policy;
typedef input_iterator_facade<Derived,ValueType,Reference,Traversal> base;
public:
// Constructor
explicit token_iterator_base()
: m_is_dropped( use_isspace ),
m_is_kept( use_ispunct ),
m_keep_empty_tokens( false ),
m_token_produced( false )
{
}
protected:
template<typename Modifier>
token_iterator_base&
use( Modifier const& m )
{
m.apply( m_is_dropped, m_is_kept, m_keep_empty_tokens );
return *this;
}
template<typename Iter>
bool get( Iter& begin, Iter end )
{
typedef detail::token_assigner<BOOST_DEDUCED_TYPENAME iterator_traversal<Iter>::type> Assigner;
Iter checkpoint;
Assigner::clear( m_value );
if( !m_keep_empty_tokens ) {
while( begin != end && m_is_dropped( *begin ) )
++begin;
if( begin == end )
return false;
checkpoint = begin;
if( m_is_kept( *begin ) )
Assigner::append_move( begin, m_value );
else
while( begin != end && !m_is_dropped( *begin ) && !m_is_kept( *begin ) )
Assigner::append_move( begin, m_value );
}
else { // m_keep_empty_tokens ia true
checkpoint = begin;
if( begin == end ) {
if( m_token_produced )
return false;
m_token_produced = true;
}
else if( m_is_kept( *begin ) ) {
if( m_token_produced )
Assigner::append_move( begin, 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 ) )
checkpoint = ++begin;
while( begin != end && !m_is_dropped( *begin ) && !m_is_kept( *begin ) )
Assigner::append_move( begin, m_value );
m_token_produced = true;
}
}
Assigner::assign( checkpoint, begin, m_value );
return true;
}
private:
// Data members
delim_policy m_is_dropped;
delim_policy m_is_kept;
bool m_keep_empty_tokens;
bool m_token_produced;
};
// ************************************************************************** //
// ************** basic_string_token_iterator ************** //
// ************************************************************************** //
template<typename CharT,
typename CharCompare = 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 M1>
basic_string_token_iterator( Src src, M1 const& m1 )
: m_src( src )
{
this->use( m1 );
this->init();
}
template<typename Src, typename M1, typename M2>
basic_string_token_iterator( Src src, M1 const& m1, M2 const& m2 )
: m_src( src )
{
this->use( m1 );
this->use( m2 );
this->init();
}
template<typename Src, typename M1, typename M2, typename M3>
basic_string_token_iterator( Src src, M1 const& m1, M2 const& m2, M3 const& m3 )
: m_src( src )
{
this->use( m1 );
this->use( m2 );
this->use( m3 );
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 = 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();
}
template<typename M1>
range_token_iterator( Iter begin, Iter end, M1 const& m1 )
: m_begin( begin ), m_end( end )
{
this->use( m1 );
this->init();
}
template<typename M1,typename M2>
range_token_iterator( Iter begin, Iter end, M1 const& m1, M2 const& m2 )
: m_begin( begin ), m_end( end )
{
this->use( m1 );
this->use( m2 );
this->init();
}
template<typename M1,typename M2,typename M3>
range_token_iterator( Iter begin, Iter end, M1 const& m1, M2 const& m2, M3 const& m3 )
: m_begin( begin ), m_end( end )
{
this->use( m1 );
this->use( m2 );
this->use( m3 );
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 M1>
inline range_token_iterator<Iter>
make_range_token_iterator( Iter begin, Iter end, M1 const& m1 )
{
return range_token_iterator<Iter>( begin, end, m1 );
}
//____________________________________________________________________________//
template<typename Iter, typename M1, typename M2>
inline range_token_iterator<Iter>
make_range_token_iterator( Iter begin, Iter end, M1 const& m1, M2 const& m2 )
{
return range_token_iterator<Iter>( begin, end, m1, m2 );
}
//____________________________________________________________________________//
template<typename Iter,typename M1, typename M2, typename M3>
inline range_token_iterator<Iter>
make_range_token_iterator( Iter begin, Iter end, M1 const& m1, M2 const& m2, M3 const& m3 )
{
return range_token_iterator<Iter>( begin, end, m1, m2, m3 );
}
//____________________________________________________________________________//
} // namespace unit_test
} // namespace boost
// ***************************************************************************
// Revision History :
//
// $Log$
// Revision 1.1 2004/06/05 11:03:12 rogeeff
// input_iterator_adaptor simplified
// token_iterator added
//
// ***************************************************************************
#endif // BOOST_TOKEN_ITERATOR_HPP