// (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 |