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