1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/base/String.cc
17 #include <zypp/base/String.h>
18 #include <zypp/base/LogTools.h>
20 #include <zypp/TriBool.h>
24 ///////////////////////////////////////////////////////////////////
26 { /////////////////////////////////////////////////////////////////
27 ///////////////////////////////////////////////////////////////////
29 { /////////////////////////////////////////////////////////////////
31 /******************************************************************
33 ** FUNCTION NAME : form
34 ** FUNCTION TYPE : std::string
36 std::string form( const char * format, ... )
41 va_start( ap, format );
42 vasprintf( &safe._buf, format, ap );
45 return safe.asString();
48 /******************************************************************
50 ** FUNCTION NAME : strerror
51 ** FUNCTION TYPE : std::string
53 std::string strerror( int errno_r )
55 return form( "(%d)%s", errno_r, ::strerror( errno_r ) );
58 /******************************************************************
60 ** FUNCTION NAME : strToTrue
61 ** FUNCTION TYPE : bool
63 bool strToTrue( const C_Str & str )
65 std::string t( toLower( str ) );
72 || strtonum<long long>( str )
76 /******************************************************************
78 ** FUNCTION NAME : strToFalse
79 ** FUNCTION TYPE : bool
81 bool strToFalse( const C_Str & str )
83 std::string t( toLower( str ) );
93 TriBool strToTriBool( const C_Str & str ) // from TriBool.h
95 if ( strToTrue( str ) ) return true;
96 if ( !strToFalse( str ) ) return false;
100 ///////////////////////////////////////////////////////////////////
102 ///////////////////////////////////////////////////////////////////
104 /** What's not decoded. */
105 inline bool heIsAlNum( char ch )
107 return ( ( 'a' <= ch && ch <= 'z' )
108 ||( 'A' <= ch && ch <= 'Z' )
109 ||( '0' <= ch && ch <= '9' ) );
111 /** Hex-digit to number or -1. */
112 inline int heDecodeCh( char ch )
114 if ( '0' <= ch && ch <= '9' )
116 if ( 'A' <= ch && ch <= 'F' )
117 return( ch - 'A' + 10 );
118 if ( 'a' <= ch && ch <= 'f' )
119 return( ch - 'a' + 10 );
124 std::string hexencode( const C_Str & str_r )
126 static const char *const hdig = "0123456789ABCDEF";
128 res.reserve( str_r.size() );
129 for ( const char * it = str_r.c_str(); *it; ++it )
131 if ( heIsAlNum( *it ) )
138 res += hdig[(unsigned char)(*it)/16];
139 res += hdig[(unsigned char)(*it)%16];
145 std::string hexdecode( const C_Str & str_r )
148 res.reserve( str_r.size() );
149 for_( it, str_r.c_str(), str_r.c_str()+str_r.size() )
153 int d1 = heDecodeCh( *(it+1) );
156 int d2 = heDecodeCh( *(it+2) );
165 // verbatim if no %XX:
170 ///////////////////////////////////////////////////////////////////
172 /******************************************************************
174 ** FUNCTION NAME : toLower
175 ** FUNCTION TYPE : std::string
177 std::string toLower( const std::string & s )
178 { return toLower( std::string(s) ); }
180 std::string toLower( std::string && s )
182 std::string ret( std::move(s) );
187 for ( std::string::size_type i = 0; i < ret.length(); ++i )
189 if ( isupper( ret[i] ) )
190 ret[i] = static_cast<char>(tolower( ret[i] ));
195 /******************************************************************
197 ** FUNCTION NAME : toUpper
198 ** FUNCTION TYPE : std::string
200 std::string toUpper( const std::string & s )
201 { return toUpper( std::string(s) ); }
203 std::string toUpper( std::string && s )
205 std::string ret( std::move(s) );
210 for ( std::string::size_type i = 0; i < ret.length(); ++i )
212 if ( islower( ret[i] ) )
213 ret[i] = static_cast<char>(toupper( ret[i] ));
218 /******************************************************************
220 ** FUNCTION NAME : trim
221 ** FUNCTION TYPE : std::string
223 std::string trim( const std::string & s, const Trim trim_r )
224 { return trim( std::string(s), trim_r ); }
226 std::string trim( std::string && s, const Trim trim_r )
228 std::string ret( std::move(s) );
230 if ( ret.empty() || trim_r == NO_TRIM )
233 if ( trim_r & L_TRIM )
235 std::string::size_type p = ret.find_first_not_of( " \t\n" );
236 if ( p == std::string::npos )
244 if ( trim_r & R_TRIM )
246 std::string::size_type p = ret.find_last_not_of( " \t\n" );
247 if ( p == std::string::npos )
252 ret = ret.erase( p+1 );
258 /******************************************************************
260 ** FUNCTION NAME : stripFirstWord
261 ** FUNCTION TYPE : std::string
263 std::string stripFirstWord( std::string & line, const bool ltrim_first )
266 line = ltrim( line );
272 std::string::size_type p = line.find_first_of( " \t" );
274 if ( p == std::string::npos ) {
278 } else if ( p == 0 ) {
281 line = ltrim( line );
284 // strip word and ltim line
285 ret = line.substr( 0, p );
286 line = ltrim( line.erase( 0, p ) );
291 /******************************************************************
293 ** FUNCTION NAME : stripLastWord
294 ** FUNCTION TYPE : std::string
296 std::string stripLastWord( std::string & line, const bool rtrim_first )
299 line = rtrim( line );
305 std::string::size_type p = line.find_last_of( " \t" );
307 if ( p == std::string::npos ) {
311 } else if ( p == line.size()-1 ) {
314 line = rtrim( line );
317 // strip word and rtim line
318 ret = line.substr( p+1 );
319 line = rtrim( line.erase( p ) );
324 std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r )
326 std::string ret( str_r );
327 return replaceAll( ret, from_r, to_r );
330 std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r )
332 if ( ! from_r.empty() )
334 std::string::size_type pos = 0;
335 while ( (pos = str_r.find( from_r, pos )) != std::string::npos )
337 str_r.replace( pos, from_r.size(), to_r );
340 if ( pos >= str_r.length() )
347 std::string gsubFun( const std::string & str_r, const std::string & from_r, function<std::string()> to_r )
349 std::string ret( str_r );
350 return replaceAllFun( ret, from_r, to_r );
353 std::string & replaceAllFun( std::string & str_r, const std::string & from_r, function<std::string()> to_r )
355 if ( ! from_r.empty() )
357 std::string::size_type pos = 0;
358 while ( (pos = str_r.find( from_r, pos )) != std::string::npos )
360 std::string to( to_r() );
361 str_r.replace( pos, from_r.size(), to );
364 if ( pos >= str_r.length() )
371 std::string escape( const C_Str & str_r, const char sep_r )
373 std::vector<char> buf;
374 for_( s, str_r.c_str(), s+str_r.size() )
381 buf.push_back( '\\' );
386 buf.push_back( '\\' );
390 return std::string( buf.begin(), buf.end() );
394 std::string bEscape( std::string str_r, const C_Str & special_r )
399 if ( str_r.find_first_of( special_r ) == std::string::npos
400 && ( ::strchr( special_r.c_str(), '\\' ) || !::strchr( str_r.c_str(), '\\' ) ) )
404 for_( s, str_r.c_str(), s+str_r.size() )
406 if ( *s == '\\' || ::strchr( special_r.c_str(), *s ) )
413 #define RXSPECIALCHARS "\\.*+?^$[()|{"
415 std::string rxEscapeStr( std::string str_r )
417 return bEscape( std::move(str_r), RXSPECIALCHARS );
420 std::string rxEscapeGlob( std::string str_r )
425 if ( str_r.find_first_of( RXSPECIALCHARS ) == std::string::npos )
429 for_( s, str_r.c_str(), s+str_r.size() )
431 if ( *s == '\\' ) // + next char literally
434 if ( *(s+1) ) { ++s; buf << *s; }
436 else if ( *s == '?' ) // translate
440 else if ( *s == '*' ) // translate
444 else if ( *s == '[' ) // character class if closing ] is found, else literally
446 const char * e = s+1;
447 if ( *e == '^' || *e == '!' ) // negated cclass
449 if ( *e == ']' ) // ] in cclass
451 while ( *e && *e != ']' ) // ...to ] or \0
453 if ( *e ) // on closing ']'
455 ++s; buf << '[' << (*s == '!' ? '^' : *s );
465 else if ( ::strchr( RXSPECIALCHARS, *s ) ) // escape
478 std::string getline( std::istream & str, const Trim trim_r )
480 return trim( receiveUpTo( str, '\n' ), trim_r );
483 std::string getline( std::istream & str, bool trim_r )
485 return trim( receiveUpTo( str, '\n' ), trim_r?TRIM:NO_TRIM );
488 std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r )
490 std::ostringstream datas;
503 break; // --> delimiter found
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.
517 /////////////////////////////////////////////////////////////////
519 ///////////////////////////////////////////////////////////////////
520 ////////////////////////////////////////////////////////////////
522 //////////////////////////////////////////////////////////////////