E-MailRelay
gstringview.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2023 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gstringview.cpp
19///
20
21#include "gdef.h"
22#include "gstringview.h"
23
24bool G::sv_imatch( string_view a , string_view b ) noexcept
25{
26 if( a.empty() || b.empty() ) return a.empty() && b.empty() ;
27 if( a.size() != b.size() ) return false ;
28 const char * const end = a.data() + a.size() ;
29 const char * q = b.data() ;
30 for( const char * p = a.data() ; p != end ; ++p , ++q )
31 {
32 char c1 = *p ;
33 char c2 = *q ;
34 if( c1 >= 'A' && c1 <= 'Z' ) c1 += '\x20' ;
35 if( c2 >= 'A' && c2 <= 'Z' ) c2 += '\x20' ;
36 if( c1 != c2 ) return false ;
37 }
38 return true ;
39}
40
41G::string_view G::sv_substr( string_view sv , std::size_t pos , std::size_t count ) noexcept
42{
43 if( pos >= sv.size() )
44 return { sv.data() , std::size_t(0U) } ;
45 else
46 return { sv.data() + pos , std::min(sv.size()-pos,count) } ;
47}
48
49// ==
50
51int G::string_view::compare( const string_view & other ) const noexcept
52{
53 int rc = ( empty() || other.empty() ) ? 0 : std::char_traits<char>::compare( m_p , other.m_p , std::min(m_n,other.m_n) ) ;
54 return rc == 0 ? ( m_n < other.m_n ? -1 : (m_n==other.m_n?0:1) ) : rc ;
55}
56
57G::string_view G::string_view::substr( std::size_t pos , std::size_t count ) const
58{
59 if( (empty() && pos!=0U) || pos > m_n )
60 throw std::out_of_range( "string_view::substr" ) ;
61 else if( pos == m_n )
62 return { m_p , std::size_t(0U) } ; // (more than the standard requires)
63 else
64 return { m_p + pos , std::min(m_n-pos,count) } ;
65}
66
67std::size_t G::string_view::find( char c , std::size_t pos ) const noexcept
68{
69 if( empty() || pos >= m_n ) return std::string::npos ;
70 const char * p = m_p + pos ;
71 std::size_t n = m_n - pos ;
72 for( ; n ; p++ , n-- , pos++ )
73 {
74 if( *p == c )
75 return pos ;
76 }
77 return std::string::npos ;
78}
79
80std::size_t G::string_view::find( const char * substr_p , std::size_t pos , std::size_t substr_n ) const
81{
82 return find( string_view(substr_p,substr_n) , pos ) ;
83}
84
85std::size_t G::string_view::find( string_view substr , std::size_t pos ) const
86{
87 if( empty() || pos >= m_n ) return std::string::npos ;
88 if( substr.empty() ) return pos ;
89 auto const end = m_p + m_n ;
90 auto p = std::search( m_p+pos , end , substr.m_p , substr.m_p+substr.m_n ) ;
91 return p == end ? std::string::npos : std::distance(m_p,p) ;
92}
93
94std::size_t G::string_view::find_first_of( const char * chars , std::size_t pos , std::size_t chars_size ) const noexcept
95{
96 return find_first_of( string_view(chars,chars_size) , pos ) ;
97}
98
99std::size_t G::string_view::find_first_of( string_view chars , std::size_t pos ) const noexcept
100{
101 if( empty() || pos >= m_n || chars.empty() ) return std::string::npos ;
102 const char * p = m_p + pos ;
103 std::size_t n = m_n - pos ;
104 for( ; n ; p++ , n-- , pos++ )
105 {
106 const std::size_t i_end = chars.size() ;
107 for( std::size_t i = 0U ; i < i_end ; i++ )
108 {
109 if( *p == chars[i] )
110 return pos ;
111 }
112 }
113 return std::string::npos ;
114}
115
116std::size_t G::string_view::find_first_not_of( char c , std::size_t pos ) const noexcept
117{
118 if( empty() || pos >= m_n ) return std::string::npos ;
119 const char * p = m_p + pos ;
120 std::size_t n = m_n - pos ;
121 for( ; n ; p++ , n-- , pos++ )
122 {
123 if( *p != c )
124 return pos ;
125 }
126 return std::string::npos ;
127}
128
129std::size_t G::string_view::find_first_not_of( const char * chars , std::size_t pos , std::size_t chars_size ) const noexcept
130{
131 return find_first_not_of( string_view(chars,chars_size) , pos ) ;
132}
133
134std::size_t G::string_view::find_first_not_of( string_view chars , std::size_t pos ) const noexcept
135{
136 if( empty() || pos >= m_n ) return std::string::npos ;
137 const char * p = m_p + pos ;
138 std::size_t n = m_n - pos ;
139 for( ; n ; p++ , n-- , pos++ )
140 {
141 bool match = false ;
142 const std::size_t i_end = chars.size() ;
143 for( std::size_t i = 0U ; !match && i < i_end ; i++ )
144 {
145 if( *p == chars[i] )
146 match = true ;
147 }
148 if( !match )
149 return pos ;
150 }
151 return std::string::npos ;
152}
153
154#ifndef G_LIB_SMALL
155std::size_t G::string_view::find_last_of( const char * chars , std::size_t pos , std::size_t chars_size ) const noexcept
156{
157 return find_last_of( string_view(chars,chars_size) , pos ) ;
158}
159#endif
160
161std::size_t G::string_view::find_last_of( string_view chars , std::size_t pos ) const noexcept
162{
163 if( empty() ) return std::string::npos ;
164 if( pos >= m_n ) pos = m_n - 1U ;
165 const char * p = data() + pos ;
166 std::size_t count = pos ;
167 for( std::size_t n = 0U ; n <= count ; n++ , p-- , pos-- )
168 {
169 bool match = false ;
170 const std::size_t i_end = chars.size() ;
171 for( std::size_t i = 0U ; !match && i < i_end ; i++ )
172 {
173 if( *p == chars[i] )
174 match = true ;
175 }
176 if( match )
177 return pos ;
178 }
179 return std::string::npos ;
180}
181
182#ifndef G_LIB_SMALL
183std::size_t G::string_view::find_last_not_of( const char * chars , std::size_t pos , std::size_t chars_size ) const noexcept
184{
185 return find_last_not_of( string_view(chars,chars_size) , pos ) ;
186}
187#endif
188
189std::size_t G::string_view::find_last_not_of( string_view chars , std::size_t pos ) const noexcept
190{
191 if( empty() ) return std::string::npos ;
192 if( pos >= m_n ) pos = m_n - 1U ;
193 const char * p = data() + pos ;
194 std::size_t count = pos ;
195 for( std::size_t n = 0U ; n <= count ; n++ , p-- , pos-- )
196 {
197 bool match = false ;
198 const std::size_t i_end = chars.size() ;
199 for( std::size_t i = 0U ; !match && i < i_end ; i++ )
200 {
201 if( *p == chars[i] )
202 match = true ;
203 }
204 if( !match )
205 return pos ;
206 }
207 return std::string::npos ;
208}
209
210std::size_t G::string_view::rfind( char c , std::size_t pos ) const noexcept
211{
212 if( empty() || pos == 0U ) return std::string::npos ;
213 if( pos == std::string::npos || pos > m_n ) pos = m_n ;
214 const char * p = m_p + pos - 1U ;
215 std::size_t n = pos - 1U ;
216 for( ; n ; n-- , p-- )
217 {
218 if( *p == c )
219 return n ;
220 }
221 return std::string::npos ;
222}
223
A class like c++17's std::string_view.
Definition: gstringview.h:51