libzypp 17.37.17
String.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
13#include <cstdio>
14#include <cstdarg>
15
16#include <iostream>
17#include <utility>
18
21
22#include <zypp-core/TriBool.h>
23#include <glib.h>
24
25using std::string;
26
28namespace zypp
29{
31 namespace str
32 {
33
34 /******************************************************************
35 **
36 ** FUNCTION NAME : form
37 ** FUNCTION TYPE : std::string
38 */
39 std::string form( const char * format, ... )
40 {
41 SafeBuf safe;
42
43 va_list ap;
44 va_start( ap, format );
45 vasprintf( &safe._buf, format, ap );
46 va_end( ap );
47
48 return safe.asString();
49 }
50
51 /******************************************************************
52 **
53 ** FUNCTION NAME : strerror
54 ** FUNCTION TYPE : std::string
55 */
56 std::string strerror( int errno_r )
57 {
58 return form( "(%d)%s", errno_r, ::strerror( errno_r ) );
59 }
60
61 /******************************************************************
62 **
63 ** FUNCTION NAME : strToTrue
64 ** FUNCTION TYPE : bool
65 */
66 bool strToTrue( const C_Str & str )
67 {
68 std::string t( toLower( str ) );
69 return( t == "1"
70 || t == "yes"
71 || t == "true"
72 || t == "always"
73 || t == "on"
74 || t == "+"
76 );
77 }
78
79 /******************************************************************
80 **
81 ** FUNCTION NAME : strToFalse
82 ** FUNCTION TYPE : bool
83 */
84 bool strToFalse( const C_Str & str )
85 {
86 std::string t( toLower( str ) );
87 return ! ( t == "0"
88 || t == "no"
89 || t == "false"
90 || t == "never"
91 || t == "off"
92 || t == "-"
93 );
94 }
95
96 TriBool strToTriBool( const C_Str & str ) // from TriBool.h
97 {
98 if ( strToTrue( str ) ) return true;
99 if ( !strToFalse( str ) ) return false;
100 return indeterminate;
101 }
102
104 // Hexencode
106 namespace {
108 inline bool heIsAlNum( char ch )
109 {
110 return ( ( 'a' <= ch && ch <= 'z' )
111 ||( 'A' <= ch && ch <= 'Z' )
112 ||( '0' <= ch && ch <= '9' ) );
113 }
115 inline int heDecodeCh( char ch )
116 {
117 if ( '0' <= ch && ch <= '9' )
118 return( ch - '0' );
119 if ( 'A' <= ch && ch <= 'F' )
120 return( ch - 'A' + 10 );
121 if ( 'a' <= ch && ch <= 'f' )
122 return( ch - 'a' + 10 );
123 return -1;
124 }
125 }
126
127 std::string hexencode( const C_Str & str_r )
128 {
129 static const char *const hdig = "0123456789ABCDEF";
130 std::string res;
131 res.reserve( str_r.size() );
132 for ( const char * it = str_r.c_str(); *it; ++it )
133 {
134 if ( heIsAlNum( *it ) )
135 {
136 res += *it;
137 }
138 else
139 {
140 res += '%';
141 res += hdig[(unsigned char)(*it)/16];
142 res += hdig[(unsigned char)(*it)%16];
143 }
144 }
145 return res;
146 }
147
148 std::string hexdecode( const C_Str & str_r )
149 {
150 std::string res;
151 res.reserve( str_r.size() );
152 for_( it, str_r.c_str(), str_r.c_str()+str_r.size() )
153 {
154 if ( *it == '%' )
155 {
156 int d1 = heDecodeCh( *(it+1) );
157 if ( d1 != -1 )
158 {
159 int d2 = heDecodeCh( *(it+2) );
160 if ( d2 != -1 )
161 {
162 res += (d1<<4)|d2;
163 it += 2;
164 continue;
165 }
166 }
167 }
168 // verbatim if no %XX:
169 res += *it;
170 }
171 return res;
172 }
173
174
175 /******************************************************************
176 **
177 ** FUNCTION NAME : toLower
178 ** FUNCTION TYPE : std::string
179 */
180 std::string toLower( const std::string & s )
181 { return toLower( std::string(s) ); }
182
183 std::string toLower( std::string && s )
184 {
185 std::string ret( std::move(s) );
186
187 if ( ret.empty() )
188 return ret;
189
190 for ( std::string::size_type i = 0; i < ret.length(); ++i )
191 {
192 if ( isupper( ret[i] ) )
193 ret[i] = static_cast<char>(tolower( ret[i] ));
194 }
195 return ret;
196 }
197
198 /******************************************************************
199 **
200 ** FUNCTION NAME : toUpper
201 ** FUNCTION TYPE : std::string
202 */
203 std::string toUpper( const std::string & s )
204 { return toUpper( std::string(s) ); }
205
206 std::string toUpper( std::string && s )
207 {
208 std::string ret( std::move(s) );
209
210 if ( ret.empty() )
211 return ret;
212
213 for ( std::string::size_type i = 0; i < ret.length(); ++i )
214 {
215 if ( islower( ret[i] ) )
216 ret[i] = static_cast<char>(toupper( ret[i] ));
217 }
218 return ret;
219 }
220
221 /******************************************************************
222 **
223 ** FUNCTION NAME : trim
224 ** FUNCTION TYPE : std::string
225 */
226 std::string trim( const std::string & s, const Trim trim_r )
227 { return trim( std::string(s), trim_r ); }
228
229 std::string trim( std::string && s, const Trim trim_r )
230 {
231 std::string ret( std::move(s) );
232
233 if ( ret.empty() || trim_r == NO_TRIM )
234 return ret;
235
236 if ( trim_r & L_TRIM )
237 {
238 std::string::size_type p = ret.find_first_not_of( " \t\n" );
239 if ( p == std::string::npos )
240 {
241 ret.clear();
242 return ret;
243 }
244 ret.erase( 0, p );
245 }
246
247 if ( trim_r & R_TRIM )
248 {
249 std::string::size_type p = ret.find_last_not_of( " \t\n" );
250 if ( p == std::string::npos )
251 {
252 ret.clear();
253 return ret;
254 }
255 ret = ret.erase( p+1 );
256 }
257
258 return ret;
259 }
260
261 /******************************************************************
262 **
263 ** FUNCTION NAME : stripFirstWord
264 ** FUNCTION TYPE : std::string
265 */
266 std::string stripFirstWord( std::string & line, const bool ltrim_first )
267 {
268 if ( ltrim_first )
269 line = ltrim( line );
270
271 if ( line.empty() )
272 return line;
273
274 std::string ret;
275 std::string::size_type p = line.find_first_of( " \t" );
276
277 if ( p == std::string::npos ) {
278 // no ws on line
279 ret = line;
280 line.erase();
281 } else if ( p == 0 ) {
282 // starts with ws
283 // ret remains empty
284 line = ltrim( line );
285 }
286 else {
287 // strip word and ltim line
288 ret = line.substr( 0, p );
289 line = ltrim( line.erase( 0, p ) );
290 }
291 return ret;
292 }
293
294 /******************************************************************
295 **
296 ** FUNCTION NAME : stripLastWord
297 ** FUNCTION TYPE : std::string
298 */
299 std::string stripLastWord( std::string & line, const bool rtrim_first )
300 {
301 if ( rtrim_first )
302 line = rtrim( line );
303
304 if ( line.empty() )
305 return line;
306
307 std::string ret;
308 std::string::size_type p = line.find_last_of( " \t" );
309
310 if ( p == std::string::npos ) {
311 // no ws on line
312 ret = line;
313 line.erase();
314 } else if ( p == line.size()-1 ) {
315 // ends with ws
316 // ret remains empty
317 line = rtrim( line );
318 }
319 else {
320 // strip word and rtim line
321 ret = line.substr( p+1 );
322 line = rtrim( line.erase( p ) );
323 }
324 return ret;
325 }
326
327 std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r )
328 {
329 std::string ret( str_r );
330 return replaceAll( ret, from_r, to_r );
331 }
332
333 std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r )
334 {
335 if ( ! from_r.empty() )
336 {
337 std::string::size_type pos = 0;
338 while ( (pos = str_r.find( from_r, pos )) != std::string::npos )
339 {
340 str_r.replace( pos, from_r.size(), to_r );
341 pos += to_r.size();
342
343 if ( pos >= str_r.length() )
344 break;
345 }
346 }
347 return str_r;
348 }
349
350 std::string gsubFun( const std::string & str_r, const std::string & from_r, function<std::string()> to_r )
351 {
352 std::string ret( str_r );
353 return replaceAllFun( ret, from_r, std::move(to_r) );
354 }
355
356 std::string & replaceAllFun( std::string & str_r, const std::string & from_r, const function<std::string()>& to_r )
357 {
358 if ( ! from_r.empty() )
359 {
360 std::string::size_type pos = 0;
361 while ( (pos = str_r.find( from_r, pos )) != std::string::npos )
362 {
363 std::string to( to_r() );
364 str_r.replace( pos, from_r.size(), to );
365 pos += to.size();
366
367 if ( pos >= str_r.length() )
368 break;
369 }
370 }
371 return str_r;
372 }
373
374 std::string escape( const C_Str & str_r, const char sep_r )
375 {
376 std::vector<char> buf;
377 for_( s, str_r.c_str(), s+str_r.size() )
378 {
379 switch ( *s )
380 {
381 case '"':
382 case '\'':
383 case '\\':
384 buf.push_back( '\\' );
385 buf.push_back( *s );
386 break;
387 default:
388 if ( *s == sep_r )
389 buf.push_back( '\\' );
390 buf.push_back( *s );
391 }
392 }
393 return std::string( buf.begin(), buf.end() );
394 }
395
396
397 std::string bEscape( std::string str_r, const C_Str & special_r )
398 {
399 if ( str_r.empty() )
400 return str_r;
401
402 if ( str_r.find_first_of( special_r ) == std::string::npos
403 && ( ::strchr( special_r.c_str(), '\\' ) || !::strchr( str_r.c_str(), '\\' ) ) )
404 return str_r;
405
406 Str buf;
407 for_( s, str_r.c_str(), s+str_r.size() )
408 {
409 if ( *s == '\\' || ::strchr( special_r.c_str(), *s ) )
410 buf << '\\';
411 buf << *s;
412 }
413 return buf;
414 }
415
416 #define RXSPECIALCHARS "\\.*+?^$[()|{"
417
418 std::string rxEscapeStr( std::string str_r )
419 {
420 return bEscape( std::move(str_r), RXSPECIALCHARS );
421 }
422
423 std::string rxEscapeGlob( std::string str_r )
424 {
425 if ( str_r.empty() )
426 return str_r;
427
428 if ( str_r.find_first_of( RXSPECIALCHARS ) == std::string::npos )
429 return str_r;
430
431 Str buf;
432 for_( s, str_r.c_str(), s+str_r.size() )
433 {
434 if ( *s == '\\' ) // + next char literally
435 {
436 buf << '\\';
437 if ( *(s+1) ) { ++s; buf << *s; }
438 }
439 else if ( *s == '?' ) // translate
440 {
441 buf << '.';
442 }
443 else if ( *s == '*' ) // translate
444 {
445 buf << ".*";
446 }
447 else if ( *s == '[' ) // character class if closing ] is found, else literally
448 {
449 const char * e = s+1;
450 if ( *e == '^' || *e == '!' ) // negated cclass
451 ++e;
452 if ( *e == ']' ) // ] in cclass
453 ++e;
454 while ( *e && *e != ']' ) // ...to ] or \0
455 ++e;
456 if ( *e ) // on closing ']'
457 {
458 ++s; buf << '[' << (*s == '!' ? '^' : *s );
459 while ( ++s != e )
460 buf << *s;
461 buf << ']';
462 }
463 else
464 {
465 buf << "\\[";
466 }
467 }
468 else if ( ::strchr( RXSPECIALCHARS, *s ) ) // escape
469 {
470 buf << '\\' << *s;
471 }
472 else
473 {
474 buf << *s;
475 }
476 }
477 return buf;
478 }
479
480
481 std::string getline( std::istream & str, const Trim trim_r )
482 {
483 return trim( receiveUpTo( str, '\n' ), trim_r );
484 }
485
486 std::string getline( std::istream & str, bool trim_r )
487 {
488 return trim( receiveUpTo( str, '\n' ), trim_r?TRIM:NO_TRIM );
489 }
490
491 std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r )
492 {
493 std::ostringstream datas;
494 do {
495 char ch = 0;
496 if ( str.get( ch ) )
497 {
498 if ( ch != delim_r )
499 {
500 datas.put( ch );
501 }
502 else
503 {
504 if ( returnDelim_r )
505 datas.put( ch );
506 break; // --> delimiter found
507 }
508 }
509 else
510 {
511 // clear fail bit if we read data before reaching EOF
512 if ( str.eof() && datas.tellp() )
513 str.clear( std::ios::eofbit );
514 break; // --> no consumable data.
515 }
516 } while ( true );
517 return datas.str();
518 }
519
520 bool validateUtf8( std::string_view str )
521 {
522 return g_utf8_validate ( str.data(), str.length (), nullptr );
523 }
524
525 std::string codepointToUtf8String( uint32_t unichar )
526 {
527 char outbuf[6] = {'\0'};
528 auto bytes = g_unichar_to_utf8( unichar, outbuf );
529 if ( bytes == 0 )
530 return {};
531
532 return std::string( outbuf, bytes );
533 }
534
535 std::string hexCodepointToUtf8String(std::string_view hexChar)
536 {
537 auto codepoint = hexCharToValue<uint32_t>(hexChar);
538 if ( !codepoint )
539 return {};
540
541 return codepointToUtf8String ( *codepoint );
542 }
543
544 } // namespace str
547} // namespace zypp
#define RXSPECIALCHARS
Definition String.cc:416
Convenience char* constructible from std::string and char*, it maps (char*)0 to an empty string.
Definition String.h:92
size_type size() const
Definition String.h:109
const char * c_str() const
Definition String.h:117
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition String.h:31
String related utilities and Regular expression matching.
String related utilities and Regular expression matching.
std::string stripLastWord(std::string &line, const bool rtrim_first)
Definition String.cc:299
std::string hexdecode(const C_Str &str_r)
Decode hexencoded XX sequences.
Definition String.cc:148
Trim
To define how to trim.
Definition String.h:567
@ NO_TRIM
Definition String.h:568
std::string hexencode(const C_Str &str_r)
Encode all characters other than [a-zA-Z0-9] as XX.
Definition String.cc:127
std::string & replaceAll(std::string &str_r, const std::string &from_r, const std::string &to_r)
Replace all occurrences of from_r with to_r in str_r (inplace).
Definition String.cc:333
std::string hexCodepointToUtf8String(std::string_view hexChar)
Definition String.cc:535
std::string gsubFun(const std::string &str_r, const std::string &from_r, function< std::string()> to_r)
Definition String.cc:350
bool strToTrue(const C_Str &str)
Parsing boolean from string.
Definition String.cc:66
TriBool strToTriBool(const C_Str &str)
Parse str into a bool if it's a legal true or false string; else indeterminate.
Definition String.cc:96
std::string codepointToUtf8String(uint32_t unichar)
Definition String.cc:525
std::string rxEscapeGlob(std::string str_r)
Escape GLOB str_r for use in a regex (not anchored by "^" or "$").
Definition String.cc:423
std::string stripFirstWord(std::string &line, const bool ltrim_first)
Definition String.cc:266
std::string escape(const C_Str &str_r, const char sep_r)
Escape desired character c using a backslash.
Definition String.cc:374
std::string toLower(const std::string &s)
Return lowercase version of s.
Definition String.cc:180
std::string receiveUpTo(std::istream &str, const char delim_r, bool returnDelim_r)
Return stream content up to the next ocurrence of delim_r or EOF delim_r, if found,...
Definition String.cc:491
std::string rtrim(const std::string &s)
Definition String.h:582
std::string strerror(int errno_r)
Return string describing the error_r code.
Definition String.cc:56
std::string gsub(const std::string &str_r, const std::string &from_r, const std::string &to_r)
Return a string with all occurrences of from_r replaced with to_r.
Definition String.cc:327
std::string toUpper(const std::string &s)
Return uppercase version of s.
Definition String.cc:203
std::string ltrim(const std::string &s)
Definition String.h:577
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:39
std::string bEscape(std::string str_r, const C_Str &special_r)
Return str_r with '\'-escaped chars occurring in special_r (and '\').
Definition String.cc:397
std::string & replaceAllFun(std::string &str_r, const std::string &from_r, const function< std::string()> &to_r)
Definition String.cc:356
std::string rxEscapeStr(std::string str_r)
Escape plain STRING str_r for use in a regex (not anchored by "^" or "$").
Definition String.cc:418
std::string getline(std::istream &str, const Trim trim_r)
Return stream content up to (but not returning) the next newline.
Definition String.cc:481
bool validateUtf8(std::string_view str)
Definition String.cc:520
TInt strtonum(const C_Str &str)
Parsing numbers from string.
bool strToFalse(const C_Str &str)
Return false if str is 0, false, no, off, never.
Definition String.cc:84
std::string trim(const std::string &s, const Trim trim_r)
Definition String.cc:226
Easy-to use interface to the ZYPP dependency resolver.
Assert free called for allocated char *.
Definition String.h:192
std::string asString() const
Definition String.h:196
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition String.h:213
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:27