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