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