libzypp 9.41.1

String.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <cstdio>
00013 #include <cstdarg>
00014 
00015 #include <iostream>
00016 
00017 #include "zypp/base/String.h"
00018 #include "zypp/base/LogTools.h"
00019 
00020 using std::string;
00021 
00023 namespace zypp
00024 { 
00025 
00026   namespace str
00027   { 
00028 
00029     /******************************************************************
00030      **
00031      **      FUNCTION NAME : form
00032      **      FUNCTION TYPE : std::string
00033     */
00034     std::string form( const char * format, ... )
00035     {
00036       SafeBuf safe;
00037 
00038       va_list ap;
00039       va_start( ap, format );
00040       vasprintf( &safe._buf, format, ap );
00041       va_end( ap );
00042 
00043       return safe.asString();
00044     }
00045 
00046     /******************************************************************
00047      **
00048      **      FUNCTION NAME : strerror
00049      **      FUNCTION TYPE : std::string
00050     */
00051     std::string strerror( int errno_r )
00052     {
00053       return form( "(%d)%s", errno_r, ::strerror( errno_r ) );
00054     }
00055 
00056     /******************************************************************
00057      **
00058      **      FUNCTION NAME : strToTrue
00059      **      FUNCTION TYPE : bool
00060     */
00061     bool strToTrue( const C_Str & str )
00062     {
00063       std::string t( toLower( str ) );
00064       return(    t == "1"
00065               || t == "yes"
00066               || t == "true"
00067               || t == "on"
00068               || t == "+"
00069               || strtonum<long long>( str )
00070             );
00071     }
00072 
00073     /******************************************************************
00074      **
00075      **      FUNCTION NAME : strToFalse
00076      **      FUNCTION TYPE : bool
00077     */
00078     bool strToFalse( const C_Str & str )
00079     {
00080       std::string t( toLower( str ) );
00081       return ! (    t == "0"
00082                  || t == "no"
00083                  || t == "false"
00084                  || t == "off"
00085                  || t == "-"
00086                );
00087     }
00088 
00090     // Hexencode
00092     namespace {
00094       inline bool heIsAlNum( char ch )
00095       {
00096         return ( ( 'a' <= ch && ch <= 'z' )
00097                ||( 'A' <= ch && ch <= 'Z' )
00098                ||( '0' <= ch && ch <= '9' ) );
00099       }
00101       inline int heDecodeCh( char ch )
00102       {
00103         if ( '0' <= ch && ch <= '9' )
00104           return( ch - '0' );
00105         if ( 'A' <= ch && ch <= 'F' )
00106           return( ch - 'A' + 10 );
00107         if ( 'a' <= ch && ch <= 'f' )
00108           return( ch - 'a' + 10 );
00109         return -1;
00110       }
00111     }
00112 
00113     std::string hexencode( const C_Str & str_r )
00114     {
00115       static const char *const hdig = "0123456789ABCDEF";
00116       std::string res;
00117       res.reserve( str_r.size() );
00118       for ( const char * it = str_r.c_str(); *it; ++it )
00119       {
00120         if ( heIsAlNum( *it ) )
00121         {
00122           res += *it;
00123         }
00124         else
00125         {
00126           res += '%';
00127           res += hdig[(unsigned char)(*it)/16];
00128           res += hdig[(unsigned char)(*it)%16];
00129         }
00130       }
00131       return res;
00132     }
00133 
00134     std::string hexdecode( const C_Str & str_r )
00135     {
00136       std::string res;
00137       res.reserve( str_r.size() );
00138       for_( it, str_r.c_str(), str_r.c_str()+str_r.size() )
00139       {
00140         if ( *it == '%' )
00141         {
00142           int d1 = heDecodeCh( *(it+1) );
00143           if ( d1 != -1 )
00144           {
00145             int d2 = heDecodeCh( *(it+2) );
00146             if ( d2 != -1 )
00147             {
00148               res += (d1<<4)|d2;
00149               it += 2;
00150               continue;
00151             }
00152           }
00153         }
00154         // verbatim if no %XX:
00155         res += *it;
00156       }
00157       return res;
00158     }
00160 
00161     /******************************************************************
00162      **
00163      **      FUNCTION NAME : toLower
00164      **      FUNCTION TYPE : std::string
00165     */
00166     std::string toLower( const std::string & s )
00167     {
00168       if ( s.empty() )
00169         return s;
00170 
00171       std::string ret( s );
00172       for ( std::string::size_type i = 0; i < ret.length(); ++i )
00173         {
00174           if ( isupper( ret[i] ) )
00175             ret[i] = static_cast<char>(tolower( ret[i] ));
00176         }
00177       return ret;
00178     }
00179 
00180     /******************************************************************
00181      **
00182      **      FUNCTION NAME : toUpper
00183      **      FUNCTION TYPE : std::string
00184     */
00185     std::string toUpper( const std::string & s )
00186     {
00187       if ( s.empty() )
00188         return s;
00189 
00190       std::string ret( s );
00191       for ( std::string::size_type i = 0; i < ret.length(); ++i )
00192         {
00193           if ( islower( ret[i] ) )
00194             ret[i] = static_cast<char>(toupper( ret[i] ));
00195         }
00196       return ret;
00197     }
00198 
00199     /******************************************************************
00200      **
00201      **      FUNCTION NAME : trim
00202      **      FUNCTION TYPE : std::string
00203     */
00204     std::string trim( const std::string & s, const Trim trim_r )
00205     {
00206       if ( s.empty() || trim_r == NO_TRIM )
00207         return s;
00208 
00209       std::string ret( s );
00210 
00211       if ( trim_r & L_TRIM )
00212         {
00213           std::string::size_type p = ret.find_first_not_of( " \t\n" );
00214           if ( p == std::string::npos )
00215             return std::string();
00216 
00217           ret = ret.substr( p );
00218         }
00219 
00220       if ( trim_r & R_TRIM )
00221         {
00222           std::string::size_type p = ret.find_last_not_of( " \t\n" );
00223           if ( p == std::string::npos )
00224             return std::string();
00225 
00226           ret = ret.substr( 0, p+1 );
00227         }
00228 
00229       return ret;
00230     }
00231 
00232     /******************************************************************
00233     **
00234     **  FUNCTION NAME : stripFirstWord
00235     **  FUNCTION TYPE : std::string
00236     */
00237     std::string stripFirstWord( std::string & line, const bool ltrim_first )
00238     {
00239       if ( ltrim_first )
00240         line = ltrim( line );
00241 
00242       if ( line.empty() )
00243         return line;
00244 
00245       std::string ret;
00246       std::string::size_type p = line.find_first_of( " \t" );
00247 
00248       if ( p == std::string::npos ) {
00249         // no ws on line
00250         ret = line;
00251         line.erase();
00252       } else if ( p == 0 ) {
00253         // starts with ws
00254         // ret remains empty
00255         line = ltrim( line );
00256       }
00257       else {
00258         // strip word and ltim line
00259         ret = line.substr( 0, p );
00260         line = ltrim( line.erase( 0, p ) );
00261       }
00262       return ret;
00263     }
00264 
00265     /******************************************************************
00266     **
00267     **  FUNCTION NAME : stripLastWord
00268     **  FUNCTION TYPE : std::string
00269     */
00270     std::string stripLastWord( std::string & line, const bool rtrim_first )
00271     {
00272       if ( rtrim_first )
00273         line = rtrim( line );
00274 
00275       if ( line.empty() )
00276         return line;
00277 
00278       std::string ret;
00279       std::string::size_type p = line.find_last_of( " \t" );
00280 
00281       if ( p == std::string::npos ) {
00282         // no ws on line
00283         ret = line;
00284         line.erase();
00285       } else if ( p == line.size()-1 ) {
00286         // ends with ws
00287         // ret remains empty
00288         line = rtrim( line );
00289       }
00290       else {
00291         // strip word and rtim line
00292         ret = line.substr( p+1 );
00293         line = rtrim( line.erase( p ) );
00294       }
00295       return ret;
00296     }
00297 
00298     string gsub(const string& sData, const string& sFrom, const string& sTo)
00299     {
00300       string sNew;
00301       sNew.reserve(sData.size());
00302 
00303       if (! sData.empty())
00304       {
00305         string::size_type frLen = sFrom.length();
00306         string::size_type loc = 0;
00307         string::size_type oldLoc = 0;
00308 
00309         while (string::npos != (loc = sData.find(sFrom, loc)))
00310         {
00311           sNew.append(sData,oldLoc,loc-oldLoc);
00312           sNew.append(sTo);
00313           loc += frLen;
00314           oldLoc = loc;
00315           if (loc >= sData.length())
00316             break;
00317         }
00318         if (oldLoc!=sData.size())
00319             sNew.append(sData,oldLoc,sData.size()-oldLoc);
00320       }
00321 
00322       return sNew;
00323     }
00324 
00325     string & replaceAll(string & str, const string & from, const string & to)
00326     {
00327       string::size_type pos = 0;
00328       while((pos = str.find(from, pos)) != string::npos)
00329       {
00330         str.replace(pos, from.size(), to);
00331         pos += to.size();
00332 
00333         if (pos >= str.length())
00334           break;
00335       }
00336       return str;
00337     }
00338 
00339 
00340     std::string escape( const C_Str & str_r, const char sep_r )
00341     {
00342       std::vector<char> buf;
00343       for_( s, str_r.c_str(), s+str_r.size() )
00344       {
00345         switch ( *s )
00346         {
00347         case '"':
00348         case '\'':
00349         case '\\':
00350           buf.push_back( '\\' );
00351           buf.push_back( *s );
00352           break;
00353         default:
00354           if ( *s == sep_r )
00355             buf.push_back( '\\' );
00356           buf.push_back( *s );
00357         }
00358       }
00359       return std::string( buf.begin(), buf.end() );
00360     }
00361 
00362 
00363     std::string bEscape( const std::string & str_r, const C_Str & special_r )
00364     {
00365       if ( str_r.empty() )
00366         return str_r;
00367 
00368       if ( str_r.find_first_of( special_r ) == std::string::npos
00369         && ( ::strchr( special_r.c_str(), '\\' ) ||  !::strchr( str_r.c_str(), '\\' ) ) )
00370         return str_r;
00371 
00372       Str buf;
00373       for_( s, str_r.c_str(), s+str_r.size() )
00374       {
00375         if ( *s == '\\' || ::strchr( special_r.c_str(), *s ) )
00376           buf << '\\';
00377         buf << *s;
00378       }
00379       return buf;
00380     }
00381 
00382     #define RXSPECIALCHARS "\\.*+?^$[()|{"
00383 
00384     std::string rxEscapeStr( const std::string & str_r )
00385     {
00386       return bEscape( str_r, RXSPECIALCHARS );
00387     }
00388 
00389     std::string rxEscapeGlob( const std::string & str_r )
00390     {
00391       if ( str_r.empty() )
00392         return str_r;
00393 
00394       if ( str_r.find_first_of( RXSPECIALCHARS ) == std::string::npos )
00395         return str_r;
00396 
00397       Str buf;
00398       for_( s, str_r.c_str(), s+str_r.size() )
00399       {
00400         if ( *s == '\\' )       // + next char literally
00401         {
00402           buf << '\\';
00403           if ( *(s+1) ) { ++s; buf << *s; }
00404         }
00405         else if ( *s == '?' )   // translate
00406         {
00407           buf << '.';
00408         }
00409         else if ( *s == '*' )   // translate
00410         {
00411           buf << ".*";
00412         }
00413         else if ( *s == '[' )   // character class if closing ] is found, else literally
00414         {
00415           const char * e = s+1;
00416           if ( *e == '^' || *e == '!' ) // negated cclass
00417             ++e;
00418           if ( *e == ']' )              // ] in cclass
00419             ++e;
00420           while ( *e && *e != ']' )     // ...to ] or \0
00421             ++e;
00422           if ( *e ) // on closing ']'
00423           {
00424             ++s;  buf << '[' << (*s == '!' ? '^' : *s );
00425             while ( ++s != e )
00426               buf << *s;
00427             buf << ']';
00428           }
00429           else
00430           {
00431             buf << "\\[";
00432           }
00433         }
00434         else if ( ::strchr( RXSPECIALCHARS, *s ) )      // escape
00435         {
00436           buf << '\\' << *s;
00437         }
00438         else
00439         {
00440           buf << *s;
00441         }
00442       }
00443       return buf;
00444     }
00445 
00446 
00447     std::string getline( std::istream & str, const Trim trim_r )
00448     {
00449       return trim( receiveUpTo( str, '\n' ), trim_r );
00450     }
00451 
00452     std::string getline( std::istream & str, bool trim_r )
00453     {
00454       return trim( receiveUpTo( str, '\n' ), trim_r?TRIM:NO_TRIM );
00455     }
00456 
00457     std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r )
00458     {
00459       std::ostringstream datas;
00460       do {
00461         char ch;
00462         if ( str.get( ch ) )
00463         {
00464           if ( ch != delim_r )
00465           {
00466             datas.put( ch );
00467           }
00468           else
00469           {
00470             if ( returnDelim_r )
00471               datas.put( ch );
00472             break;      // --> delimiter found
00473           }
00474         }
00475         else
00476         {
00477           // clear fail bit if we read data before reaching EOF
00478           if ( str.eof() && datas.tellp() )
00479             str.clear( std::ios::eofbit );
00480           break;        // --> no consumable data.
00481         }
00482       } while ( true );
00483       return datas.str();
00484     }
00485 
00487   } // namespace str
00490 } // namespace zypp