E-MailRelay

gstringtoken.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 gstringtoken.h
19///
20
21#ifndef G_STRING_TOKEN_H
22#define G_STRING_TOKEN_H
23
24#include "gdef.h"
25#include "gassert.h"
26#include "gstringview.h"
27#include <string>
28#include <type_traits>
29#include <algorithm>
30
31 namespace G
32{
33 template <typename T> class StringTokenT ;
34 using StringToken = StringTokenT<std::string> ;
35 using StringTokenView = StringTokenT<std::string_view> ;
36}
37
38//| \class G::StringTokenT
39/// A zero-copy string token iterator where the token separators
40/// are runs of whitespace characters, with no support for escape
41/// characters. Leading and trailing whitespace are not significant.
42/// Empty whitespace yields a single token. Stepping beyond the
43/// last token is allowed.
44///
45/// \code
46/// for( StringToken t(s," \t",2U) ; t ; ++t )
47/// std::cout << t() << "\n" ;
48/// \endcode
49///
50/// \see G::Str::splitIntoTokens()
51///
52 template <typename T>
53 class G::StringTokenT
54{
55 public:
56 using char_type = typename T::value_type ;
57
58 StringTokenT( const T & s , const char_type * ws , std::size_t wsn ) noexcept ;
59 ///< Constructor. The parameters must stay valid for
60 ///< the object lifefime.
61 ///<
62 ///< The rvalue overload is deleted to avoid passing a
63 ///< temporary T that has been implicitly constructed from
64 ///< something else. Temporary std::string_views constructed
65 ///< from a string would be safe, but might be unsafe for
66 ///< other types.
67
68 StringTokenT( const T & s , std::string_view ws ) noexcept ;
69 ///< Constructor. The parameters must stay valid
70 ///< for the object lifefime.
71
72 bool valid() const noexcept ;
73 ///< Returns true if a valid token position.
74
75 explicit operator bool() const noexcept ;
76 ///< Returns true if a valid token.
77
78 const char_type * data() const noexcept ;
79 ///< Returns the current token pointer.
80
81 std::size_t size() const noexcept ;
82 ///< Returns the current token size.
83
84 std::size_t pos() const noexcept ;
85 ///< Returns the offset of data().
86
87 T operator()() const noexcept(std::is_same<T,std::string_view>::value) ;
88 ///< Returns the current token substring or T() if
89 ///< not valid().
90
91 StringTokenT<T> & operator++() noexcept ;
92 ///< Moves to the next token.
93
94 StringTokenT<T> & next() noexcept ;
95 ///< Moves to the next token.
96
97 public:
98 ~StringTokenT() = default ;
99 StringTokenT( T && s , const char_type * , std::size_t ) = delete ;
100 StringTokenT( T && s , std::string_view ) = delete ;
101 StringTokenT( const StringTokenT<T> & ) = delete ;
102 StringTokenT( StringTokenT<T> && ) = delete ;
103 StringTokenT<T> & operator=( const StringTokenT<T> & ) = delete ;
104 StringTokenT<T> & operator=( StringTokenT<T> && ) = delete ;
105
106 private:
107 static constexpr std::size_t npos = T::npos ;
108 const T & m_s ;
109 const char_type * m_ws ;
110 std::size_t m_wsn ;
111 std::size_t m_pos ;
112 std::size_t m_endpos ;
113} ;
114
115 namespace G
116{
117 namespace StringTokenImp /// An implementation namespace for G::StringToken.
118 {
119 template <typename T> inline T substr( const T & s ,
120 std::size_t pos , std::size_t len ) noexcept
121 {
122 try { return s.substr( pos , len ) ; } catch(...) { return {} ; }
123 }
124 template <> inline std::string_view substr<std::string_view>( const std::string_view & s ,
125 std::size_t pos , std::size_t len ) noexcept
126 {
127 return sv_substr_noexcept( s , pos , len ) ;
128 }
129 }
130}
131
132 template <typename T>
133 G::StringTokenT<T>::StringTokenT( const T & s , const char_type * ws , std::size_t wsn ) noexcept :
134 m_s(s) ,
135 m_ws(ws) ,
136 m_wsn(wsn) ,
137 m_pos(s.empty()?npos:s.find_first_not_of(m_ws,0U,m_wsn)) ,
138 m_endpos(s.find_first_of(m_ws,m_pos,m_wsn))
139{
140 G_ASSERT( !(s.empty()) || ( m_pos == npos && m_endpos == npos ) ) ;
141 G_ASSERT( !(!s.empty() && wsn==0U) || ( m_pos == 0U && m_endpos == npos ) ) ;
142 G_ASSERT( !(m_pos == npos) || m_endpos == npos ) ;
143}
144
145 template <typename T>
146 G::StringTokenT<T>::StringTokenT( const T & s , std::string_view ws ) noexcept :
147 m_s(s) ,
148 m_ws(ws.data()) ,
149 m_wsn(ws.size()) ,
150 m_pos(s.empty()?npos:s.find_first_not_of(m_ws,0U,m_wsn)) ,
151 m_endpos(s.find_first_of(m_ws,m_pos,m_wsn))
152{
153}
154
155 template <typename T>
156 const typename T::value_type * G::StringTokenT<T>::data() const noexcept
157{
158 //static_assert( __cplusplus >= 201100 , "" ) ; // broken on msvc
159 return m_s.data() + (m_pos==npos?0U:m_pos) ;
160}
161
162 template <typename T>
163std::size_t G::StringTokenT<T>::size() const noexcept
164{
165 return (m_endpos==npos?m_s.size():m_endpos) - m_pos ;
166}
167
168 template <typename T>
169std::size_t G::StringTokenT<T>::pos() const noexcept
170{
171 return m_pos == npos ? 0U : m_pos ;
172}
173
174 template <typename T>
175 G::StringTokenT<T>::operator bool() const noexcept
176{
177 return m_pos != npos ;
178}
179
180 template <typename T>
181 bool G::StringTokenT<T>::valid() const noexcept
182{
183 return m_pos != npos ;
184}
185
186 template <typename T>
187T G::StringTokenT<T>::operator()() const noexcept(std::is_same<T,std::string_view>::value)
188{
189 using string_type = T ;
190 return m_pos == npos ? string_type{} : StringTokenImp::substr( m_s , m_pos , size() ) ;
191}
192
193 template <typename T>
194 G::StringTokenT<T> & G::StringTokenT<T>::operator++() noexcept
195{
196 m_pos = m_s.find_first_not_of( m_ws , m_endpos , m_wsn ) ;
197 m_endpos = m_s.find_first_of( m_ws , m_pos , m_wsn ) ;
198 G_ASSERT( !(m_s.empty()) || ( m_pos == npos && m_endpos == npos ) ) ;
199 G_ASSERT( !(!m_s.empty() && m_wsn==0U) || ( m_pos == npos && m_endpos == npos ) ) ;
200 G_ASSERT( !(m_pos == npos) || m_endpos == npos ) ;
201 return *this ;
202}
203
204 template <typename T>
205 G::StringTokenT<T> & G::StringTokenT<T>::next() noexcept
206{
207 return ++(*this) ;
208}
209
210#endif
G::StringTokenT
A zero-copy string token iterator where the token separators are runs of whitespace characters,...
Definition: gstringtoken.h:54
G::StringTokenT::next
StringTokenT< T > & next() noexcept
Moves to the next token.
Definition: gstringtoken.h:205
G::StringTokenT::operator()
T operator()() const noexcept(std::is_same< T, std::string_view >::value)
Returns the current token substring or T() if not valid().
Definition: gstringtoken.h:187
G::StringTokenT::data
const char_type * data() const noexcept
Returns the current token pointer.
Definition: gstringtoken.h:156
G::StringTokenT::valid
bool valid() const noexcept
Returns true if a valid token position.
Definition: gstringtoken.h:181
G::StringTokenT::size
std::size_t size() const noexcept
Returns the current token size.
Definition: gstringtoken.h:163
G::StringTokenT::pos
std::size_t pos() const noexcept
Returns the offset of data().
Definition: gstringtoken.h:169
G::StringTokenT::operator++
StringTokenT< T > & operator++() noexcept
Moves to the next token.
Definition: gstringtoken.h:194
G::StringTokenT::StringTokenT
StringTokenT(const T &s, const char_type *ws, std::size_t wsn) noexcept
Constructor.
Definition: gstringtoken.h:133
G::string_view
A class like c++17's std::string_view.
Definition: gstringview.h:70
gassert.h
gstringview.h
G
Low-level classes.
Definition: garg.h:36
std
STL namespace.