E-MailRelay
gstringview.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 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.h
19///
20
21#ifndef G_STRING_VIEW_H
22#define G_STRING_VIEW_H
23
24#include "gdef.h"
25#include <string>
26#include <cstring>
27#include <new>
28
29#if GCONFIG_HAVE_CXX_STRING_VIEW
30
31#include <string_view>
32
33namespace G
34{
35 std::string_view sv_substr_noexcept( std::string_view sv , std::size_t pos , std::size_t count = std::string::npos ) noexcept ;
36 bool sv_imatch( std::string_view , std::string_view ) noexcept ;
37 inline std::string sv_to_string( std::string_view sv ) { return std::string(sv) ; }
38}
39
40constexpr std::string_view operator "" _sv( const char * p , std::size_t n ) noexcept
41{
42 return {p,n} ;
43}
44
45#else
46
47#include <stdexcept>
48#include <ostream>
49#include <algorithm> // std::min()
50
51namespace G
52{
53 class string_view ;
54 G::string_view sv_substr_noexcept( G::string_view sv , std::size_t pos , std::size_t count = std::string::npos ) noexcept ;
55 bool sv_imatch( G::string_view , G::string_view ) noexcept ;
56}
57
58namespace std /// NOLINT
59{
60 using string_view = G::string_view ;
61}
62
63//| \class G::string_view
64/// A class like c++17's std::string_view.
65///
66/// There is an implicit conversion constructor from std::string
67/// since std::string has its convertion operator "operator sv()".
68///
70{
71public:
72 using traits = std::char_traits<char> ;
73 using iterator = const char * ;
74 using const_iterator = const char * ;
75 using size_type = std::size_t ;
76 using difference_type = std::ptrdiff_t ;
77 using value_type = char ;
78 static constexpr std::size_t npos = std::size_t(-1) ;
79 string_view() noexcept = default ;
80 string_view( std::nullptr_t ) = delete ;
81 static constexpr /*consteval*/ std::size_t strlen_imp( const char * p , std::size_t n = 0U ) noexcept { return *p ? strlen_imp(p+1,n+1U) : n ; }
82 constexpr string_view( const char * p , std::size_t n ) noexcept : m_p(p) , m_n(n) {}
83 constexpr /*consteval*/ string_view( const char * p , std::nothrow_t ) noexcept : m_p(p) , m_n(p?strlen_imp(p):0U) {}
84 string_view( const char * p ) noexcept /*implicit*/ : m_p(p) , m_n(p?std::strlen(p):0U) {}
85 string_view( const std::string & s ) noexcept /* implicit */ : m_p(s.data()) , m_n(s.size()) {}
86 constexpr std::size_t size() const noexcept { return m_n ; }
87 constexpr std::size_t length() const noexcept { return m_n ; }
88 constexpr const char * data() const noexcept { return m_p ; }
89 constexpr bool empty() const noexcept { return m_n == 0U ; }
90 void swap( string_view & other ) noexcept { std::swap(m_p,other.m_p) ; std::swap(m_n,other.m_n) ; }
91 constexpr const char & operator[]( std::size_t i ) const noexcept { return m_p[i] ; }
92 const char & at( std::size_t i ) const { if( i >= m_n ) throw std::out_of_range("string_view::at") ; return m_p[i] ; }
93 const char * begin() const noexcept { return empty() ? nullptr : m_p ; }
94 const char * cbegin() const noexcept { return empty() ? nullptr : m_p ; }
95 const char * end() const noexcept { return empty() ? nullptr : (m_p+m_n) ; }
96 const char * cend() const noexcept { return empty() ? nullptr : (m_p+m_n) ; }
97 int compare( const string_view & other ) const noexcept {
98 int rc = ( empty() || other.empty() ) ? 0 : std::char_traits<char>::compare( m_p , other.m_p , std::min(m_n,other.m_n) ) ;
99 return rc == 0 ? ( m_n < other.m_n ? -1 : (m_n==other.m_n?0:1) ) : rc ;
100 }
101 int compare( std::size_t pos , std::size_t count , string_view other ) const noexcept { return substr(pos,count).compare(other) ; }
102 bool operator==( const string_view & other ) const noexcept { return compare(other) == 0 ; }
103 bool operator!=( const string_view & other ) const noexcept { return compare(other) != 0 ; }
104 bool operator<( const string_view & other ) const noexcept { return compare(other) < 0 ; }
105 bool operator<=( const string_view & other ) const noexcept { return compare(other) <= 0 ; }
106 bool operator>( const string_view & other ) const noexcept { return compare(other) > 0 ; }
107 bool operator>=( const string_view & other ) const noexcept { return compare(other) >= 0 ; }
108
109 string_view substr( std::size_t pos , std::size_t count = npos ) const ;
110 std::size_t find( char c , std::size_t pos = 0U ) const noexcept ;
111 std::size_t find( const char * substr_p , std::size_t pos , std::size_t substr_n ) const ;
112 std::size_t find( string_view substr , std::size_t pos = 0U ) const ;
113 std::size_t find_first_of( const char * chars , std::size_t pos , std::size_t chars_size ) const noexcept ;
114 std::size_t find_first_of( string_view chars , std::size_t pos = 0U ) const noexcept ;
115 std::size_t find_first_not_of( char c , std::size_t pos = 0U ) const noexcept ;
116 std::size_t find_first_not_of( const char * chars , std::size_t pos , std::size_t chars_size ) const noexcept ;
117 std::size_t find_first_not_of( string_view chars , std::size_t pos = 0U ) const noexcept ;
118 std::size_t find_last_of( const char * chars , std::size_t pos , std::size_t chars_size ) const noexcept ;
119 std::size_t find_last_of( string_view chars , std::size_t pos = std::string::npos ) const noexcept ;
120 std::size_t find_last_not_of( const char * chars , std::size_t pos , std::size_t chars_size ) const noexcept ;
121 std::size_t find_last_not_of( string_view chars , std::size_t pos = std::string::npos ) const noexcept ;
122 std::size_t rfind( char c , std::size_t pos = std::string::npos ) const noexcept ;
123
124private:
125 const char * m_p {nullptr} ;
126 std::size_t m_n {0U} ;
127} ;
128
129namespace G
130{
131 inline std::ostream & operator<<( std::ostream & stream , const string_view & sv )
132 {
133 if( !sv.empty() )
134 stream.write( sv.data() , sv.size() ) ; // NOLINT narrowing
135 return stream ;
136 }
137 inline void swap( string_view & a , string_view b ) noexcept
138 {
139 a.swap( b ) ;
140 }
141 inline bool operator==( const std::string & s , string_view sv )
142 {
143 return sv.empty() ? s.empty() : ( 0 == s.compare( 0 , s.size() , sv.data() , sv.size() ) ) ;
144 }
145 inline bool operator!=( const std::string & s , string_view sv )
146 {
147 return !(s == sv) ;
148 }
149 inline std::string sv_to_string( string_view sv )
150 {
151 return sv.empty() ? std::string() : std::string( sv.data() , sv.size() ) ;
152 }
153}
154
155namespace std /// NOLINT
156{
157 inline bool operator<( const string & s , G::string_view sv ) // NOLINT
158 {
159 return s.compare( 0 , s.size() , sv.data() , sv.size() ) < 0 ;
160 }
161}
162
163constexpr G::string_view operator "" _sv( const char * p , std::size_t n ) noexcept
164{
165 return {p,n} ;
166}
167
168#endif
169
170#endif
A class like c++17's std::string_view.
Definition: gstringview.h:70
Low-level classes.
Definition: garg.h:36
STL namespace.