Chris@16: // (C) Copyright Gennadiy Rozental 2004-2008. Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // See http://www.boost.org/libs/test for the library home page. Chris@16: // Chris@16: // File : $RCSfile$ Chris@16: // Chris@101: // Version : $Revision$ Chris@16: // Chris@16: // Description : class basic_cstring wraps C string and provide std_string like Chris@16: // interface Chris@16: // *************************************************************************** Chris@16: Chris@16: #ifndef BOOST_TEST_BASIC_CSTRING_HPP_071894GER Chris@16: #define BOOST_TEST_BASIC_CSTRING_HPP_071894GER Chris@16: Chris@16: // Boost.Test Chris@16: #include Chris@16: #include Chris@16: Chris@16: // STL Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: namespace unit_test { Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** basic_cstring ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: class basic_cstring { Chris@16: typedef basic_cstring self_type; Chris@16: public: Chris@16: // Subtypes Chris@16: typedef ut_detail::bcs_char_traits traits_type; Chris@16: typedef typename ut_detail::bcs_char_traits::std_string std_string; Chris@16: Chris@16: typedef CharT value_type; Chris@16: typedef value_type* pointer; Chris@16: typedef value_type const* const_pointer; Chris@16: typedef value_type& reference; Chris@16: typedef const value_type& const_reference; Chris@16: typedef std::size_t size_type; Chris@16: typedef std::ptrdiff_t difference_type; Chris@16: Chris@16: typedef value_type const* const_iterator; Chris@16: typedef value_type* iterator; Chris@16: Chris@16: // !! should also present reverse_iterator, const_reverse_iterator Chris@16: Chris@16: #if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) Chris@16: enum npos_type { npos = static_cast(-1) }; Chris@16: #else Chris@16: // IBM/VisualAge version 6 is not able to handle enums larger than 4 bytes. Chris@16: // But size_type is 8 bytes in 64bit mode. Chris@16: static const size_type npos = -1 ; Chris@16: #endif Chris@16: Chris@16: static pointer null_str(); Chris@16: Chris@16: // Constructors; default copy constructor is generated by compiler Chris@16: basic_cstring(); Chris@16: basic_cstring( std_string const& s ); Chris@16: basic_cstring( pointer s ); Chris@16: basic_cstring( pointer s, size_type arg_size ); Chris@16: basic_cstring( pointer first, pointer last ); Chris@16: Chris@16: // data access methods Chris@16: value_type operator[]( size_type index ) const; Chris@16: value_type at( size_type index ) const; Chris@16: Chris@16: // size operators Chris@16: size_type size() const; Chris@16: bool is_empty() const; Chris@16: void clear(); Chris@16: void resize( size_type new_len ); Chris@16: Chris@16: // !! only for STL container conformance use is_empty instead Chris@16: bool empty() const; Chris@16: Chris@16: // Trimming Chris@16: self_type& trim_right( size_type trim_size ); Chris@16: self_type& trim_left( size_type trim_size ); Chris@16: self_type& trim_right( iterator it ); Chris@16: self_type& trim_left( iterator it ); Chris@16: #ifndef __IBMCPP__ Chris@16: self_type& trim_left( self_type exclusions = self_type() ) ; Chris@16: self_type& trim_right( self_type exclusions = self_type() ) ; Chris@16: self_type& trim( self_type exclusions = self_type() ) ; Chris@16: #else Chris@16: // VisualAge version 6 has in this case a problem with the default arguments. Chris@16: self_type& trim_left( self_type exclusions ) ; Chris@16: self_type& trim_right( self_type exclusions ) ; Chris@16: self_type& trim( self_type exclusions ) ; Chris@16: self_type& trim_left() { trim_left( self_type() ) ; } Chris@16: self_type& trim_right() { trim_right( self_type() ) ; } Chris@16: self_type& trim() { trim( self_type() ) ; } Chris@16: #endif Chris@16: Chris@16: // Assignment operators Chris@16: basic_cstring& operator=( self_type const& s ); Chris@16: basic_cstring& operator=( std_string const& s ); Chris@16: basic_cstring& operator=( pointer s ); Chris@16: Chris@16: template Chris@16: basic_cstring& assign( basic_cstring const& s ) { *this = basic_cstring( s.begin(), s.end() ); return *this; } Chris@16: basic_cstring& assign( self_type const& s, size_type pos, size_type len ); Chris@16: basic_cstring& assign( std_string const& s ); Chris@16: basic_cstring& assign( std_string const& s, size_type pos, size_type len ); Chris@16: basic_cstring& assign( pointer s ); Chris@16: basic_cstring& assign( pointer s, size_type len ); Chris@16: basic_cstring& assign( pointer f, pointer l ); Chris@16: Chris@16: // swapping Chris@16: void swap( self_type& s ); Chris@16: Chris@16: // Iterators Chris@16: iterator begin(); Chris@16: const_iterator begin() const; Chris@16: iterator end(); Chris@16: const_iterator end() const; Chris@16: Chris@16: // !! should have rbegin, rend Chris@16: Chris@16: // substring search operation Chris@16: size_type find( basic_cstring ) const; Chris@16: size_type rfind( basic_cstring ) const; Chris@16: self_type substr( size_type beg_index, size_type end_index = npos ) const; Chris@16: Chris@16: private: Chris@16: static self_type default_trim_ex(); Chris@16: Chris@16: // Data members Chris@16: iterator m_begin; Chris@16: iterator m_end; Chris@16: }; Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline typename basic_cstring::pointer Chris@16: basic_cstring::null_str() Chris@16: { Chris@16: static CharT null = 0; Chris@16: return &null; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline Chris@16: basic_cstring::basic_cstring() Chris@16: : m_begin( null_str() ) Chris@16: , m_end( m_begin ) Chris@16: { Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline Chris@16: basic_cstring::basic_cstring( std_string const& s ) Chris@16: : m_begin( s.c_str() ) Chris@16: , m_end( m_begin + s.size() ) Chris@16: { Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline Chris@16: basic_cstring::basic_cstring( pointer s ) Chris@16: : m_begin( s ? s : null_str() ) Chris@16: , m_end ( m_begin + (s ? traits_type::length( s ) : 0 ) ) Chris@16: { Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline Chris@16: basic_cstring::basic_cstring( pointer s, size_type arg_size ) Chris@16: : m_begin( s ), m_end( m_begin + arg_size ) Chris@16: { Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline Chris@16: basic_cstring::basic_cstring( pointer first, pointer last ) Chris@16: : m_begin( first ) Chris@16: , m_end( last ) Chris@16: { Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline typename basic_cstring::value_type Chris@16: basic_cstring::operator[]( size_type index ) const Chris@16: { Chris@16: return m_begin[index]; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline typename basic_cstring::value_type Chris@16: basic_cstring::at( size_type index ) const Chris@16: { Chris@16: if( m_begin + index >= m_end ) Chris@16: return static_cast(0); Chris@16: Chris@16: return m_begin[index]; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline typename basic_cstring::size_type Chris@16: basic_cstring::size() const Chris@16: { Chris@16: return m_end - m_begin; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline bool Chris@16: basic_cstring::is_empty() const Chris@16: { Chris@16: return m_end == m_begin; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline bool Chris@16: basic_cstring::empty() const Chris@16: { Chris@16: return is_empty(); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline void Chris@16: basic_cstring::clear() Chris@16: { Chris@16: m_begin = m_end; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline void Chris@16: basic_cstring::resize( size_type new_len ) Chris@16: { Chris@16: if( m_begin + new_len < m_end ) Chris@16: m_end = m_begin + new_len; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::trim_left( size_type trim_size ) Chris@16: { Chris@16: m_begin += trim_size; Chris@16: if( m_end <= m_begin ) Chris@16: clear(); Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::trim_left( iterator it ) Chris@16: { Chris@16: m_begin = it; Chris@16: if( m_end <= m_begin ) Chris@16: clear(); Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::trim_left( basic_cstring exclusions ) Chris@16: { Chris@16: if( exclusions.is_empty() ) Chris@16: exclusions = default_trim_ex(); Chris@16: Chris@16: iterator it; Chris@16: for( it = begin(); it != end(); ++it ) { Chris@16: if( traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast(0) ) Chris@16: break; Chris@16: } Chris@16: Chris@16: return trim_left( it ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::trim_right( size_type trim_size ) Chris@16: { Chris@16: m_end -= trim_size; Chris@16: if( m_end <= m_begin ) Chris@16: clear(); Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::trim_right( iterator it ) Chris@16: { Chris@16: m_end = it; Chris@16: if( m_end <= m_begin ) Chris@16: clear(); Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::trim_right( basic_cstring exclusions ) Chris@16: { Chris@16: if( exclusions.is_empty() ) Chris@16: exclusions = default_trim_ex(); Chris@16: Chris@16: iterator it; Chris@16: Chris@16: for( it = end()-1; it != begin()-1; --it ) { Chris@16: if( self_type::traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast(0) ) Chris@16: break; Chris@16: } Chris@16: Chris@16: return trim_right( it+1 ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::trim( basic_cstring exclusions ) Chris@16: { Chris@16: trim_left( exclusions ); Chris@16: trim_right( exclusions ); Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::operator=( basic_cstring const& s ) Chris@16: { Chris@16: m_begin = s.m_begin; Chris@16: m_end = s.m_end; Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::operator=( std_string const& s ) Chris@16: { Chris@16: return *this = self_type( s ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::operator=( pointer s ) Chris@16: { Chris@16: return *this = self_type( s ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::assign( basic_cstring const& s, size_type pos, size_type len ) Chris@16: { Chris@16: return *this = self_type( s.m_begin + pos, len ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::assign( std_string const& s ) Chris@16: { Chris@16: return *this = self_type( s ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::assign( std_string const& s, size_type pos, size_type len ) Chris@16: { Chris@16: return *this = self_type( s.c_str() + pos, len ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::assign( pointer s ) Chris@16: { Chris@16: return *this = self_type( s ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::assign( pointer s, size_type len ) Chris@16: { Chris@16: return *this = self_type( s, len ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring& Chris@16: basic_cstring::assign( pointer f, pointer l ) Chris@16: { Chris@16: return *this = self_type( f, l ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline void Chris@16: basic_cstring::swap( basic_cstring& s ) Chris@16: { Chris@16: // do not want to include alogrithm Chris@16: pointer tmp1 = m_begin; Chris@16: pointer tmp2 = m_end; Chris@16: Chris@16: m_begin = s.m_begin; Chris@16: m_end = s.m_end; Chris@16: Chris@16: s.m_begin = tmp1; Chris@16: s.m_end = tmp2; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline typename basic_cstring::iterator Chris@16: basic_cstring::begin() Chris@16: { Chris@16: return m_begin; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline typename basic_cstring::const_iterator Chris@16: basic_cstring::begin() const Chris@16: { Chris@16: return m_begin; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline typename basic_cstring::iterator Chris@16: basic_cstring::end() Chris@16: { Chris@16: return m_end; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline typename basic_cstring::const_iterator Chris@16: basic_cstring::end() const Chris@16: { Chris@16: return m_end; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline typename basic_cstring::size_type Chris@16: basic_cstring::find( basic_cstring str ) const Chris@16: { Chris@16: if( str.is_empty() || str.size() > size() ) Chris@16: return static_cast(npos); Chris@16: Chris@16: const_iterator it = begin(); Chris@16: const_iterator last = end() - str.size() + 1; Chris@16: Chris@16: while( it != last ) { Chris@16: if( traits_type::compare( it, str.begin(), str.size() ) == 0 ) Chris@16: break; Chris@16: Chris@16: ++it; Chris@16: } Chris@16: Chris@16: return it == last ? static_cast(npos) : it - begin(); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline typename basic_cstring::size_type Chris@16: basic_cstring::rfind( basic_cstring str ) const Chris@16: { Chris@16: if( str.is_empty() || str.size() > size() ) Chris@16: return static_cast(npos); Chris@16: Chris@16: const_iterator it = end() - str.size(); Chris@16: const_iterator last = begin()-1; Chris@16: Chris@16: while( it != last ) { Chris@16: if( traits_type::compare( it, str.begin(), str.size() ) == 0 ) Chris@16: break; Chris@16: Chris@16: --it; Chris@16: } Chris@16: Chris@16: return it == last ? static_cast(npos) : static_cast(it - begin()); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring Chris@16: basic_cstring::substr( size_type beg_index, size_type end_index ) const Chris@16: { Chris@16: return beg_index > size() Chris@16: ? self_type() Chris@16: : end_index > size() Chris@16: ? self_type( m_begin + beg_index, m_end ) Chris@16: : self_type( m_begin + beg_index, m_begin + end_index ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline basic_cstring Chris@16: basic_cstring::default_trim_ex() Chris@16: { Chris@16: static CharT ws[3] = { CharT(' '), CharT('\t'), CharT('\n') }; // !! wide case Chris@16: Chris@16: return self_type( ws, 3 ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** comparison operators ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator==( basic_cstring const& s1, basic_cstring const& s2 ) Chris@16: { Chris@16: typedef typename basic_cstring::traits_type traits_type; Chris@16: return s1.size() == s2.size() && Chris@16: traits_type::compare( s1.begin(), s2.begin(), s1.size() ) == 0; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator==( basic_cstring const& s1, CharT2* s2 ) Chris@16: { Chris@16: #if !defined(__DMC__) Chris@16: return s1 == basic_cstring( s2 ); Chris@16: #else Chris@16: return s1 == basic_cstring( s2 ); Chris@16: #endif Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator==( basic_cstring const& s1, typename basic_cstring::std_string const& s2 ) Chris@16: { Chris@16: return s1 == basic_cstring( s2 ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator==( CharT1* s2, basic_cstring const& s1 ) Chris@16: { Chris@16: return s1 == s2; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator==( typename basic_cstring::std_string const& s2, basic_cstring const& s1 ) Chris@16: { Chris@16: return s1 == s2; Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator!=( basic_cstring const& s1, CharT* s2 ) Chris@16: { Chris@16: return !(s1 == s2); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator!=( CharT* s2, basic_cstring const& s1 ) Chris@16: { Chris@16: return !(s1 == s2); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator!=( basic_cstring const& s1, basic_cstring const& s2 ) Chris@16: { Chris@16: return !(s1 == s2); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator!=( basic_cstring const& s1, typename basic_cstring::std_string const& s2 ) Chris@16: { Chris@16: return !(s1 == s2); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator!=( typename basic_cstring::std_string const& s2, basic_cstring const& s1 ) Chris@16: { Chris@16: return !(s1 == s2); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** first_char ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: inline typename basic_cstring::value_type Chris@16: first_char( basic_cstring source ) Chris@16: { Chris@16: typedef typename basic_cstring::value_type string_value_type; Chris@16: Chris@16: return source.is_empty() ? static_cast(0) : *source.begin(); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** last_char ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: inline typename basic_cstring::value_type Chris@16: last_char( basic_cstring source ) Chris@16: { Chris@16: typedef typename basic_cstring::value_type string_value_type; Chris@16: Chris@16: return source.is_empty() ? static_cast(0) : *(source.end()-1); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** assign_op ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: inline void Chris@16: assign_op( std::basic_string& target, basic_cstring src, int ) Chris@16: { Chris@16: target.assign( src.begin(), src.size() ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: } // namespace unit_test Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_TEST_BASIC_CSTRING_HPP_071894GER