21#ifndef G_STRING_VIEW_H
22#define G_STRING_VIEW_H
32 template <
typename T
char>
class basic_string_view ;
33 using string_view = basic_string_view<char> ;
34 using wstring_view = basic_string_view<wchar_t> ;
36 namespace StringViewImp
38 constexpr unsigned int strlen_constexpr(
const char * p )
noexcept
40 return *p ? (strlen_constexpr(p+1)+1U) : 0U ;
42 constexpr unsigned int strlen_constexpr(
const wchar_t * p )
noexcept
44 return *p ? (strlen_constexpr(p+1)+1U) : 0U ;
46 inline std::size_t strlen(
const char * p )
noexcept
48 return std::strlen( p ) ;
50 inline std::size_t strlen(
const wchar_t * p )
noexcept
52 return std::wcslen( p ) ;
54 constexpr bool same( std::size_t n ,
const char * p1 ,
const char * p2 )
noexcept
56 return n == 0U ? true : ( *p1 == *p2 && same( n-1U , p1+1 , p2+1 ) ) ;
71template <
typename T
char>
75 using traits = std::char_traits<Tchar> ;
76 using iterator =
const Tchar * ;
77 using const_iterator =
const Tchar * ;
78 using size_type = std::size_t ;
79 using difference_type = std::ptrdiff_t ;
80 using value_type = Tchar ;
81 static constexpr std::size_t npos = std::size_t(-1) ;
90 m_n(p?StringViewImp::strlen(p):0U)
95 m_n(p?StringViewImp::strlen_constexpr(p):0U)
100 return a.size() == b.size() && ( a.empty() || StringViewImp::same( a.size() , a.data() , b.data() ) ) ;
102 constexpr std::size_t size()
const noexcept {
return m_n ; }
103 constexpr std::size_t length()
const noexcept {
return m_n ; }
104 constexpr const Tchar * data()
const noexcept {
return m_p ; }
105 constexpr bool empty()
const noexcept {
return m_n == 0U ; }
107 constexpr const Tchar & operator[]( std::size_t i )
const {
return m_p[i] ; }
108 const Tchar & at( std::size_t i )
const {
if( i >= m_n )
throw std::out_of_range(
"string_view") ;
return m_p[i] ; }
109 const Tchar * begin()
const noexcept {
return empty() ? nullptr : m_p ; }
110 const Tchar * cbegin()
const noexcept {
return empty() ? nullptr : m_p ; }
111 const Tchar * end()
const noexcept {
return empty() ? nullptr : (m_p+m_n) ; }
112 const Tchar * cend()
const noexcept {
return empty() ? nullptr : (m_p+m_n) ; }
121 int rc = ( empty() || other.empty() ) ? 0 : std::char_traits<Tchar>::compare( m_p , other.m_p , std::min(m_n,other.m_n) ) ;
122 return rc == 0 ? ( m_n < other.m_n ? -1 : (m_n==other.m_n?0:1) ) : rc ;
124 string_view substr( std::size_t pos , std::size_t count = npos )
const
126 if( empty() || pos > m_n )
throw std::out_of_range(
"string_view" ) ;
127 return string_view( m_p + pos , std::min(m_n-pos,count) ) ;
129 std::size_t find( Tchar c )
const noexcept
131 if( empty() )
return std::string::npos ;
132 const Tchar * p = m_p ;
133 std::size_t n = m_n ;
134 for( std::size_t pos = 0U ; n ; p++ , n-- , pos++ )
139 return std::string::npos ;
141 std::size_t find(
const Tchar * substr_p , std::size_t pos , std::size_t substr_n )
const
147 if( empty() || pos >= m_n )
return std::string::npos ;
148 if( substr.empty() )
return pos ;
149 auto const end = m_p + m_n ;
150 auto p = std::search( m_p+pos , end , substr.m_p , substr.m_p+substr.m_n ) ;
151 return p == end ? std::string::npos : std::distance(m_p,p) ;
153 std::size_t find_first_of(
const Tchar * chars , std::size_t pos , std::size_t chars_size )
const noexcept
159 if( empty() || pos >= m_n || chars.empty() )
return std::string::npos ;
160 const Tchar * p = m_p + pos ;
161 std::size_t n = m_n - pos ;
162 for( ; n ; p++ , n-- , pos++ )
164 const std::size_t i_end = chars.size() ;
165 for( std::size_t i = 0U ; i < i_end ; i++ )
171 return std::string::npos ;
173 std::size_t find_first_not_of(
const Tchar * chars , std::size_t pos , std::size_t chars_size )
const noexcept
179 if( empty() || pos >= m_n || chars.empty() )
return std::string::npos ;
180 const Tchar * p = m_p + pos ;
181 std::size_t n = m_n - pos ;
182 for( ; n ; p++ , n-- , pos++ )
185 const std::size_t i_end = chars.size() ;
186 for( std::size_t i = 0U ; !match && i < i_end ; i++ )
194 return std::string::npos ;
196 std::basic_string<Tchar> sv_to_string_imp()
const
198 return empty() ? std::basic_string<Tchar>() : std::basic_string<Tchar>( m_p , m_n ) ;
202 const Tchar * m_p{
nullptr} ;
203 std::size_t m_n{0U} ;
211 return std::basic_string<Tchar>( sv.sv_to_string_imp() ) ;
213 inline std::ostream & operator<<( std::ostream & stream ,
const string_view & sv )
216 stream.write( sv.data() , sv.size() ) ;
219 inline std::wostream & operator<<( std::wostream & stream ,
const wstring_view & sv )
222 stream.write( sv.data() , sv.size() ) ;
225 template <
typename T
char>
void swap( basic_string_view<Tchar> & a , basic_string_view<Tchar> b )
noexcept
229 inline bool operator==(
const std::string & s , string_view sv )
231 return sv.empty() ? s.empty() : ( 0 == s.compare( 0 , s.size() , sv.data() , sv.size() ) ) ;
233 inline bool operator==( string_view sv ,
const std::string & s )
235 return sv.empty() ? s.empty() : ( 0 == s.compare( 0 , s.size() , sv.data() , sv.size() ) ) ;
237 inline bool operator!=(
const std::string & s , string_view sv )
241 inline bool operator!=( string_view sv ,
const std::string & s )
A class template like c++17's std::basic_string_view.