libzypp  10.5.0
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 <= 'Z' )
00106           return( ch - 'A' + 10 );
00107         if ( 'a' <= ch && ch <= 'z' )
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     std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r )
00299     {
00300       std::string ret( str_r );
00301       return replaceAll( ret, from_r, to_r );
00302     }
00303 
00304     std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r )
00305     {
00306       std::string::size_type pos = 0;
00307       while ( (pos = str_r.find( from_r, pos )) != std::string::npos )
00308       {
00309         str_r.replace( pos, from_r.size(), to_r );
00310         pos += to_r.size();
00311 
00312         if ( pos >= str_r.length() )
00313           break;
00314       }
00315       return str_r;
00316     }
00317 
00318     std::string gsubFun( const std::string & str_r, const std::string & from_r, function<std::string()> to_r )
00319     {
00320       std::string ret( str_r );
00321       return replaceAllFun( ret, from_r, to_r );
00322     }
00323 
00324     std::string & replaceAllFun( std::string & str_r, const std::string & from_r, function<std::string()> to_r )
00325     {
00326       std::string::size_type pos = 0;
00327       while ( (pos = str_r.find( from_r, pos )) != std::string::npos )
00328       {
00329         std::string to( to_r() );
00330         str_r.replace( pos, from_r.size(), to );
00331         pos += to.size();
00332 
00333         if ( pos >= str_r.length() )
00334           break;
00335       }
00336       return str_r;
00337     }
00338 
00339     std::string escape( const C_Str & str_r, const char sep_r )
00340     {
00341       std::vector<char> buf;
00342       for_( s, str_r.c_str(), s+str_r.size() )
00343       {
00344         switch ( *s )
00345         {
00346         case '"':
00347         case '\'':
00348         case '\\':
00349           buf.push_back( '\\' );
00350           buf.push_back( *s );
00351           break;
00352         default:
00353           if ( *s == sep_r )
00354             buf.push_back( '\\' );
00355           buf.push_back( *s );
00356         }
00357       }
00358       return std::string( buf.begin(), buf.end() );
00359     }
00360 
00361     std::string getline( std::istream & str, const Trim trim_r )
00362     {
00363       return trim( receiveUpTo( str, '\n' ), trim_r );
00364     }
00365 
00366     std::string getline( std::istream & str, bool trim_r )
00367     {
00368       return trim( receiveUpTo( str, '\n' ), trim_r?TRIM:NO_TRIM );
00369     }
00370 
00371     std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r )
00372     {
00373       std::ostringstream datas;
00374       do {
00375         char ch;
00376         if ( str.get( ch ) )
00377         {
00378           if ( ch != delim_r )
00379           {
00380             datas.put( ch );
00381           }
00382           else
00383           {
00384             if ( returnDelim_r )
00385               datas.put( ch );
00386             break;      // --> delimiter found
00387           }
00388         }
00389         else
00390         {
00391           // clear fail bit if we read data before reaching EOF
00392           if ( str.eof() && datas.tellp() )
00393             str.clear( std::ios::eofbit );
00394           break;        // --> no consumable data.
00395         }
00396       } while ( true );
00397       return datas.str();
00398     }
00399 
00401   } // namespace str
00404 } // namespace zypp