// (C) Copyright Gennadiy Rozental 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$ // // Description : class basic_cstring wraps C string and provide std_string like // interface // *************************************************************************** #ifndef BOOST_TEST_UTILS_BASIC_CSTRING_HPP #define BOOST_TEST_UTILS_BASIC_CSTRING_HPP // Boost.Test #include #include // Boost #include // STL #include #include //____________________________________________________________________________// namespace boost { namespace unit_test { // ************************************************************************** // // ************** basic_cstring ************** // // ************************************************************************** // template class basic_cstring { typedef basic_cstring self_type; public: // Subtypes typedef ut_detail::bcs_char_traits traits_type; typedef typename traits_type::std_string std_string; typedef CharT value_type; typedef typename remove_cv::type value_ret_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(-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( basic_cstring const & ); basic_cstring( std_string const& s ); basic_cstring( pointer s ); template basic_cstring( pointer s, LenType len ) : m_begin( s ), m_end( m_begin + len ) {} basic_cstring( pointer first, pointer last ); // data access methods value_ret_type operator[]( size_type index ) const; value_ret_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 ); #if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(800)) 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 // VA C++/XL C++ v6 and v8 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() { return trim_left( self_type() ); } self_type& trim_right() { return trim_right( self_type() ); } self_type& trim() { return 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 basic_cstring& assign( basic_cstring const& s ) { return *this = basic_cstring( s.begin(), s.end() ); } template basic_cstring& assign( self_type const& s, PosType pos, LenType len ) { return *this = self_type( s.m_begin + pos, len ); } basic_cstring& assign( std_string const& s ); template basic_cstring& assign( std_string const& s, PosType pos, LenType len ) { return *this = self_type( s.c_str() + pos, len ); } basic_cstring& assign( pointer s ); template basic_cstring& assign( pointer s, LenType len ) { return *this = self_type( s, 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 inline typename basic_cstring::pointer basic_cstring::null_str() { static CharT null = 0; return &null; } //____________________________________________________________________________// template inline basic_cstring::basic_cstring() : m_begin( null_str() ) , m_end( m_begin ) { } //____________________________________________________________________________// template inline basic_cstring::basic_cstring(basic_cstring const & s) : m_begin( s.m_begin ) , m_end( s.m_end ) { } //____________________________________________________________________________// template inline basic_cstring::basic_cstring( std_string const& s ) : m_begin( s.c_str() ) , m_end( m_begin + s.size() ) { } //____________________________________________________________________________// template inline basic_cstring::basic_cstring( pointer s ) : m_begin( s ? s : null_str() ) , m_end ( m_begin + (s ? traits_type::length( s ) : 0 ) ) { } //____________________________________________________________________________// template inline basic_cstring::basic_cstring( pointer first, pointer last ) : m_begin( first ) , m_end( last ) { } //____________________________________________________________________________// template inline typename basic_cstring::value_ret_type basic_cstring::operator[]( size_type index ) const { return m_begin[index]; } //____________________________________________________________________________// template inline typename basic_cstring::value_ret_type basic_cstring::at( size_type index ) const { if( m_begin + index >= m_end ) return static_cast(0); return m_begin[index]; } //____________________________________________________________________________// template inline typename basic_cstring::size_type basic_cstring::size() const { return static_cast(m_end - m_begin); } //____________________________________________________________________________// template inline bool basic_cstring::is_empty() const { return m_end == m_begin; } //____________________________________________________________________________// template inline bool basic_cstring::empty() const { return is_empty(); } //____________________________________________________________________________// template inline void basic_cstring::clear() { m_begin = m_end; } //____________________________________________________________________________// template inline void basic_cstring::resize( size_type new_len ) { if( m_begin + new_len < m_end ) m_end = m_begin + new_len; } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::trim_left( size_type trim_size ) { m_begin += trim_size; if( m_end <= m_begin ) clear(); return *this; } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::trim_left( iterator it ) { m_begin = it; if( m_end <= m_begin ) clear(); return *this; } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::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(0) ) break; } return trim_left( it ); } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::trim_right( size_type trim_size ) { m_end -= trim_size; if( m_end <= m_begin ) clear(); return *this; } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::trim_right( iterator it ) { m_end = it; if( m_end <= m_begin ) clear(); return *this; } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::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(0) ) break; } return trim_right( it+1 ); } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::trim( basic_cstring exclusions ) { trim_left( exclusions ); trim_right( exclusions ); return *this; } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::operator=( basic_cstring const& s ) { m_begin = s.m_begin; m_end = s.m_end; return *this; } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::operator=( std_string const& s ) { return *this = self_type( s ); } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::operator=( pointer s ) { return *this = self_type( s ); } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::assign( std_string const& s ) { return *this = self_type( s ); } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::assign( pointer s ) { return *this = self_type( s ); } //____________________________________________________________________________// template inline basic_cstring& basic_cstring::assign( pointer f, pointer l ) { return *this = self_type( f, l ); } //____________________________________________________________________________// template inline void basic_cstring::swap( basic_cstring& 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 inline typename basic_cstring::iterator basic_cstring::begin() { return m_begin; } //____________________________________________________________________________// template inline typename basic_cstring::const_iterator basic_cstring::begin() const { return m_begin; } //____________________________________________________________________________// template inline typename basic_cstring::iterator basic_cstring::end() { return m_end; } //____________________________________________________________________________// template inline typename basic_cstring::const_iterator basic_cstring::end() const { return m_end; } //____________________________________________________________________________// template inline typename basic_cstring::size_type basic_cstring::find( basic_cstring str ) const { if( str.is_empty() || str.size() > size() ) return static_cast(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 ? npos : static_cast(it - begin()); } //____________________________________________________________________________// template inline typename basic_cstring::size_type basic_cstring::rfind( basic_cstring str ) const { if( str.is_empty() || str.size() > size() ) return static_cast(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(npos) : static_cast(it - begin()); } //____________________________________________________________________________// template inline basic_cstring basic_cstring::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 inline basic_cstring basic_cstring::default_trim_ex() { static CharT ws[3] = { CharT(' '), CharT('\t'), CharT('\n') }; // !! wide case return self_type( ws, 3 ); } //____________________________________________________________________________// // ************************************************************************** // // ************** comparison operators ************** // // ************************************************************************** // template inline bool operator==( basic_cstring const& s1, basic_cstring const& s2 ) { typedef typename basic_cstring::traits_type traits_type; return s1.size() == s2.size() && traits_type::compare( s1.begin(), s2.begin(), s1.size() ) == 0; } //____________________________________________________________________________// template inline bool operator==( basic_cstring const& s1, CharT2* s2 ) { #if !defined(__DMC__) return s1 == basic_cstring( s2 ); #else return s1 == basic_cstring( s2 ); #endif } //____________________________________________________________________________// template inline bool operator==( basic_cstring const& s1, typename basic_cstring::std_string const& s2 ) { return s1 == basic_cstring( s2 ); } //____________________________________________________________________________// template inline bool operator==( CharT1* s2, basic_cstring const& s1 ) { return s1 == s2; } //____________________________________________________________________________// template inline bool operator==( typename basic_cstring::std_string const& s2, basic_cstring const& s1 ) { return s1 == s2; } //____________________________________________________________________________// template inline bool operator!=( basic_cstring const& s1, CharT* s2 ) { return !(s1 == s2); } //____________________________________________________________________________// template inline bool operator!=( CharT* s2, basic_cstring const& s1 ) { return !(s1 == s2); } //____________________________________________________________________________// template inline bool operator!=( basic_cstring const& s1, basic_cstring const& s2 ) { return !(s1 == s2); } //____________________________________________________________________________// template inline bool operator!=( basic_cstring const& s1, typename basic_cstring::std_string const& s2 ) { return !(s1 == s2); } //____________________________________________________________________________// template inline bool operator!=( typename basic_cstring::std_string const& s2, basic_cstring const& s1 ) { return !(s1 == s2); } //____________________________________________________________________________// // ************************************************************************** // // ************** first_char ************** // // ************************************************************************** // template inline typename basic_cstring::value_ret_type first_char( basic_cstring source ) { typedef typename basic_cstring::value_ret_type res_type; return source.is_empty() ? static_cast(0) : *source.begin(); } //____________________________________________________________________________// // ************************************************************************** // // ************** last_char ************** // // ************************************************************************** // template inline typename basic_cstring::value_ret_type last_char( basic_cstring source ) { typedef typename basic_cstring::value_ret_type res_type; return source.is_empty() ? static_cast(0) : *(source.end()-1); } //____________________________________________________________________________// // ************************************************************************** // // ************** assign_op ************** // // ************************************************************************** // template inline void assign_op( std::basic_string& target, basic_cstring src, int ) { target.assign( src.begin(), src.size() ); } //____________________________________________________________________________// template inline std::basic_string& operator+=( std::basic_string& target, basic_cstring const& str ) { target.append( str.begin(), str.end() ); return target; } //____________________________________________________________________________// template inline std::basic_string operator+( std::basic_string const& lhs, basic_cstring const& rhs ) { std::basic_string res( lhs ); res.append( rhs.begin(), rhs.end() ); return res; } //____________________________________________________________________________// } // namespace unit_test } // namespace boost //____________________________________________________________________________// #include #endif // BOOST_TEST_UTILS_BASIC_CSTRING_HPP