libzypp: zypp-core/base/StringV.h Source File

libzypp 17.38.11

StringV.h
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#ifndef ZYPP_BASE_STRINGV_H
13#define ZYPP_BASE_STRINGV_H
14#include <string_view>
15#ifdef __cpp_lib_string_view
16
17#include <zypp-core/Globals.h>
18#include <zypp-core/base/String.h>
19#include <zypp-core/base/Regex.h>
20#include <zypp-core/base/Flags.h>
21
23namespace zypp
24{
25 namespace strv
26 {
27 using regex = str::regex;
28 using smatch = str::smatch;
29
31 enum class Trim {
32 notrim = 0,
33 left = 1<<0,
34 right = 1<<1,
35 trim = (left|right),
36 };
37
38 ZYPP_DECLARE_FLAGS_AND_OPERATORS( TrimFlag, Trim );
39
41 inline constexpr std::string_view blank = " \t";
42
44 inline std::string_view ltrim( std::string_view str_r, std::string_view chars_r = blank )
45 {
46 if ( str_r.empty() )
47 return str_r;
48 auto pos = str_r.find_first_not_of( chars_r );
49 if ( pos == str_r.npos )
50 str_r.remove_prefix( str_r.size() );
51 else if ( pos )
52 str_r.remove_prefix( pos );
53 return str_r;
54 }
55
57 inline std::string_view rtrim( std::string_view str_r, std::string_view chars_r = blank )
58 {
59 if ( str_r.empty() )
60 return str_r;
61 auto pos = str_r.find_last_not_of( chars_r );
62 if ( pos == str_r.npos )
63 str_r.remove_suffix( str_r.size() );
64 else if ( (pos = str_r.size()-1-pos) )
65 str_r.remove_suffix( pos );
66 return str_r;
67 }
68
70 inline std::string_view trim( std::string_view str_r, std::string_view chars_r = blank )
71 {
72 if ( str_r.empty() )
73 return str_r;
74 str_r = ltrim( std::move(str_r), chars_r );
75 str_r = rtrim( std::move(str_r), chars_r );
76 return str_r;
77 }
78
80 inline std::string_view trim( std::string_view str_r, std::string_view chars_r, TrimFlag trim_r )
81 {
82 if ( str_r.empty() || trim_r == Trim::notrim )
83 return str_r;
84 if ( trim_r.testFlag( Trim::left ) )
85 str_r = ltrim( std::move(str_r), chars_r );
86 if ( trim_r.testFlag( Trim::right ) )
87 str_r = rtrim( std::move(str_r), chars_r );
88 return str_r;
89 }
91 inline std::string_view trim( std::string_view str_r, TrimFlag trim_r )
92 { return trim( std::move(str_r), blank, std::move(trim_r) ); }
93
95 inline bool hasPrefix( std::string_view str_r, std::string_view prefix_r )
96 { return( str_r.size() >= prefix_r.size() && ::strncmp( str_r.data(), prefix_r.data(), prefix_r.size() ) == 0 ); }
97
99 inline bool hasPrefixCI( std::string_view str_r, std::string_view prefix_r )
100 { return( str_r.size() >= prefix_r.size() && ::strncasecmp( str_r.data(), prefix_r.data(), prefix_r.size() ) == 0 ); }
101
103 namespace detail
104 {
106 using WordConsumer = std::function<bool(std::string_view,unsigned,bool)>;
107
122
123 template <typename Callable, std::enable_if_t<
124 std::is_invocable_r_v<bool,Callable,std::string_view,unsigned,bool>
125 , bool> = true>
126 WordConsumer wordConsumer( Callable && fnc_r )
127 { return std::forward<Callable>(fnc_r); }
129 template <typename Callable, std::enable_if_t<
130 ! std::is_invocable_r_v<bool,Callable,std::string_view,unsigned,bool>
131 && std::is_invocable_r_v<void,Callable,std::string_view,unsigned,bool>
132 , bool> = true>
133 WordConsumer wordConsumer( Callable && fnc_r )
134 { return [&fnc_r](std::string_view a1,unsigned a2,bool a3)->bool { fnc_r(a1,a2,a3); return true; }; }
135
137 template <typename Callable, std::enable_if_t<
138 std::is_invocable_r_v<bool,Callable,std::string_view,unsigned>
139 , bool> = true>
140 WordConsumer wordConsumer( Callable && fnc_r )
141 { return [&fnc_r](std::string_view a1,unsigned a2,bool)->bool { return fnc_r(a1,a2); }; }
143 template <typename Callable, std::enable_if_t<
144 ! std::is_invocable_r_v<bool,Callable,std::string_view,unsigned>
145 && std::is_invocable_r_v<void,Callable,std::string_view,unsigned>
146 , bool> = true>
147 WordConsumer wordConsumer( Callable && fnc_r )
148 { return [&fnc_r](std::string_view a1,unsigned a2,bool)->bool { fnc_r(a1,a2); return true; }; }
149
151 template <typename Callable, std::enable_if_t<
152 std::is_invocable_r_v<bool,Callable,std::string_view>
153 , bool> = true>
154 WordConsumer wordConsumer( Callable && fnc_r )
155 { return [&fnc_r](std::string_view a1,unsigned,bool)->bool { return fnc_r(a1); }; }
157 template <typename Callable, std::enable_if_t<
158 ! std::is_invocable_r_v<bool,Callable,std::string_view>
159 && std::is_invocable_r_v<void,Callable,std::string_view>
160 , bool> = true>
161 WordConsumer wordConsumer( Callable && fnc_r )
162 { return [&fnc_r](std::string_view a1,unsigned,bool)->bool { fnc_r(a1); return true; }; }
163
165 template <typename Callable, std::enable_if_t<
166 std::is_invocable_r_v<bool,Callable>
167 , bool> = true>
168 WordConsumer wordConsumer( Callable && fnc_r )
169 { return [&fnc_r](std::string_view,unsigned,bool)->bool { return fnc_r(); }; }
171 template <typename Callable, std::enable_if_t<
172 ! std::is_invocable_r_v<bool,Callable>
173 && std::is_invocable_r_v<void,Callable>
174 , bool> = true>
175 WordConsumer wordConsumer( Callable && fnc_r )
176 { return [&fnc_r](std::string_view,unsigned,bool)->bool { fnc_r(); return true; }; }
178
180 unsigned _split( std::string_view line_r, std::string_view sep_r, Trim trim_r, WordConsumer && fnc_r ) ZYPP_API;
181
183 unsigned _splitRx(std::string_view line_r, const regex & rx_r, const WordConsumer& fnc_r );
184 } // namespace detail
186
207 template <typename Callable = detail::WordConsumer>
208 unsigned splitRx( std::string_view line_r, const regex & rx_r, Callable && fnc_r = Callable() )
209 { return detail::_splitRx( line_r, rx_r, detail::wordConsumer( std::forward<Callable>(fnc_r) ) ); }
210
211
272 template <typename Callable = detail::WordConsumer>
273 unsigned split( std::string_view line_r, std::string_view sep_r, Trim trim_r, Callable && fnc_r = Callable() )
274 { return detail::_split( line_r, sep_r, trim_r, detail::wordConsumer( std::forward<Callable>(fnc_r) ) ); }
275
277 template <typename Callable = detail::WordConsumer>
278 inline unsigned split( std::string_view line_r, std::string_view sep_r, Callable && fnc_r = Callable() )
279 { return detail::_split( line_r, sep_r, Trim::notrim, detail::wordConsumer( std::forward<Callable>(fnc_r) ) ); }
280
282 template <typename Callable = detail::WordConsumer>
283 inline unsigned split( std::string_view line_r, Callable && fnc_r = Callable() )
284 { return detail::_split( line_r, std::string_view(), Trim::notrim, detail::wordConsumer( std::forward<Callable>(fnc_r) ) ); }
285
286 inline std::string_view asStringView( const char * t )
287 { return t == nullptr ? std::string_view() : t; }
288
289
295
296 std::string doBSEscape( std::string_view word_r, std::string_view special_r );
297
299 std::string unBSEscape( std::string_view word_r );
300
302 std::vector<std::string> unBSEscape( const std::vector<std::string_view> & words_r );
303
322 std::vector<std::string_view> splitBSEscaped( std::string_view line_r, std::string_view chars_r = blank, unsigned maxSplits_r = 0 );
323 inline std::vector<std::string_view> splitBSEscaped( std::string_view line_r, unsigned maxSplits_r )
324 { return splitBSEscaped( line_r, blank, maxSplits_r ); }
325
327 inline std::string_view ltrimBSEscaped( std::string_view str_r, std::string_view chars_r = blank )
328 {
329 // Leading characters are never escaped by definition, so we can reuse ltrim.
330 return ltrim( str_r, chars_r );
331 }
332
334 inline std::string_view rtrimBSEscaped( std::string_view str_r, std::string_view chars_r = blank )
335 {
336 while ( !str_r.empty() ) {
337 char lastChar = str_r.back();
338
339 // If the last character isn't in our trim set, we are done.
340 if ( chars_r.find( lastChar ) == std::string_view::npos ) {
341 break;
342 }
343
344 // Check if this character is escaped by counting backslashes preceding it.
345 size_t pos = str_r.size() - 1;
346 size_t bsCount = 0;
347 while ( pos > 0 && str_r[pos - 1] == '\\' ) {
348 ++bsCount;
349 --pos;
350 }
351
352 // If bsCount is odd, the character is escaped (e.g., " \ ") and shouldn't be trimmed.
353 if ( bsCount % 2 != 0 ) {
354 break;
355 }
356
357 // Otherwise, it's a literal separator and can be removed.
358 str_r.remove_suffix( 1 );
359 }
360 return str_r;
361 }
362
364 inline std::string_view trimBSEscaped( std::string_view str_r, std::string_view chars_r = blank )
365 {
366 if ( str_r.empty() ) {
367 return str_r;
368 }
369 // Order matters: ltrim first so we don't have to worry about
370 // shifted indices when calculating backslashes for the right side.
371 str_r = ltrimBSEscaped( str_r, chars_r );
372 str_r = rtrimBSEscaped( str_r, chars_r );
373 return str_r;
374 }
376 } // namespace strv
377} // namespace zypp
379#endif // __cpp_lib_string_view
380#endif // ZYPP_BASE_STRINGV_H
Flags.h
ZYPP_DECLARE_FLAGS_AND_OPERATORS
#define ZYPP_DECLARE_FLAGS_AND_OPERATORS(Name, Enum)
relates: Flags
Definition Flags.h:189
Globals.h
Provides API related macros.
Regex.h
String.h
std::enable_if_t
typename enable_if< B, T >::type enable_if_t
Definition TypeTraits.h:45
zypp::str::Trim
Trim
To define how to trim.
Definition String.h:567
zypp::str::hasPrefix
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition String.h:1097
zypp::str::rtrim
std::string rtrim(const std::string &s)
Definition String.h:582
zypp::str::ltrim
std::string ltrim(const std::string &s)
Definition String.h:577
zypp::str::hasPrefixCI
bool hasPrefixCI(const C_Str &str_r, const C_Str &prefix_r)
Definition String.h:1100
zypp::str::trim
std::string trim(const std::string &s, const Trim trim_r)
Definition String.cc:226
zypp::strv::detail
Definition StringV.cc:20
zypp::strv
Definition StringV.cc:18
zypp::strv::doBSEscape
std::string doBSEscape(std::string_view word_r, std::string_view special_r)
Definition StringV.cc:187
zypp::strv::splitBSEscaped
std::vector< std::string_view > splitBSEscaped(std::string_view line_r, std::string_view chars_r, unsigned maxSplits_r)
Definition StringV.cc:243
zypp::strv::unBSEscape
std::string unBSEscape(std::string_view word_r)
Definition StringV.cc:213
zypp::url::split
void split(ParamVec &pvec, const std::string &pstr, const std::string &psep)
Split into a parameter vector.
Definition UrlUtils.cc:164
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition CodePitfalls.doc:2
zypp::ZYPP_API
const Arch Arch_empty ZYPP_API
relates: Arch This is an empty Arch represented by an empty string.
Definition Arch.h:173