libzypp  10.5.0
String.h
Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #ifndef ZYPP_BASE_STRING_H
00013 #define ZYPP_BASE_STRING_H
00014 
00015 #include <cstring>
00016 
00017 #include <iosfwd>
00018 #include <vector>
00019 #include <string>
00020 #include <sstream>
00021 
00022 #include "zypp/base/Easy.h"
00023 #include "zypp/base/PtrTypes.h"
00024 #include "zypp/base/Function.h"
00025 
00027 namespace zypp
00028 { 
00029 
00068   class C_Str
00069   {
00070     public:
00071       typedef std::string::size_type size_type;
00072 
00073     public:
00074       C_Str()                            : _val( 0 ),             _sze( 0 ) {}
00075       C_Str( char * c_str_r )            : _val( c_str_r ),       _sze( std::string::npos ) {}
00076       C_Str( const char * c_str_r )      : _val( c_str_r ),       _sze( std::string::npos ) {}
00077       C_Str( const std::string & str_r ) : _val( str_r.c_str() ), _sze( str_r.size() ) {}
00078 
00079     public:
00080       bool      isNull()       const { return !_val; }
00081       bool      empty()        const { return !(_val && *_val); }
00082       size_type size()         const
00083       {
00084         if ( _sze == std::string::npos )
00085         { _sze = _val ? ::strlen( _val ) : 0; }
00086         return _sze;
00087       };
00088 
00089       operator const char *() const { return c_str(); }
00090       const char * c_str()    const { return _val ? _val : ""; }
00091 
00092     private:
00093       const char *const _val;
00094       mutable size_type _sze;
00095   };
00096 
00098   inline std::ostream & operator<<( std::ostream & str, const C_Str & obj )
00099   { return str << obj.c_str(); }
00100 
00102 
00105   namespace str
00106   { 
00107 
00109 
00112     inline std::string asString( const std::string &t )
00113     { return t; }
00114 
00115     inline std::string asString( const char * t )
00116     { return t; }
00117 
00118     template<class _T>
00119         inline std::string asString( const _T &t )
00120         { return t.asString(); }
00121 
00122     template<class _T>
00123         inline std::string asString( const intrusive_ptr<_T> &p )
00124         { return p->asString(); }
00125 
00126     template<class _T>
00127         inline std::string asString( const weak_ptr<_T> &p )
00128         { return p->asString(); }
00129 
00130     template<>
00131         inline std::string asString( const bool &t )
00132         { return t ? "+" : "-"; }
00133 
00135 
00136     std::string form( const char * format, ... )
00137     __attribute__ ((format (printf, 1, 2)));
00138 
00140 
00144     std::string strerror( int errno_r );
00145 
00147 
00157     struct SafeBuf
00158     {
00159       char * _buf;
00160       SafeBuf() : _buf( 0 ) {}
00161       ~SafeBuf() { if ( _buf ) free( _buf ); }
00162       std::string asString() const
00163       { return _buf ? std::string(_buf) : std::string(); }
00164     };
00165 
00167 
00177     struct Str
00178     {
00179       template<class _Tp>
00180       Str & operator<<( const _Tp & val )
00181       { _str << val; return *this; }
00182 
00183       operator std::string() const
00184       { return _str.str(); }
00185 
00186       std::ostringstream _str;
00187     };
00188 
00190 
00203     inline std::string numstring( char n,               int w = 0 ) { return form( "%*hhd",  w, n ); }
00204     inline std::string numstring( unsigned char n,      int w = 0 ) { return form( "%*hhu",  w, n ); }
00205     inline std::string numstring( short n,              int w = 0 ) { return form( "%*hd",   w, n ); }
00206     inline std::string numstring( unsigned short n,     int w = 0 ) { return form( "%*hu",   w, n ); }
00207     inline std::string numstring( int n,                int w = 0 ) { return form( "%*d",    w, n ); }
00208     inline std::string numstring( unsigned n,           int w = 0 ) { return form( "%*u",    w, n ); }
00209     inline std::string numstring( long n,               int w = 0 ) { return form( "%*ld",   w, n ); }
00210     inline std::string numstring( unsigned long n,      int w = 0 ) { return form( "%*lu",   w, n ); }
00211     inline std::string numstring( long long n,          int w = 0 ) { return form( "%*lld",  w, n ); }
00212     inline std::string numstring( unsigned long long n, int w = 0 ) { return form( "%*llu",  w, n ); }
00213 
00214     template<> inline std::string asString( const char & t )                    { return numstring( t ); }
00215     template<> inline std::string asString( const unsigned char & t )           { return numstring( t ); }
00216     template<> inline std::string asString( const short & t )                   { return numstring( t ); }
00217     template<> inline std::string asString( const unsigned short & t )          { return numstring( t ); }
00218     template<> inline std::string asString( const int & t )                     { return numstring( t ); }
00219     template<> inline std::string asString( const unsigned & t )                { return numstring( t ); }
00220     template<> inline std::string asString( const long & t )                    { return numstring( t ); }
00221     template<> inline std::string asString( const unsigned long & t )           { return numstring( t ); }
00222     template<> inline std::string asString( const long long & t )               { return numstring( t ); }
00223     template<> inline std::string asString( const unsigned long long & t )      { return numstring( t ); }
00225 
00227 
00238     inline std::string hexstring( char n,               int w = 4 ) { return form( "%#0*hhx", w, n ); }
00239     inline std::string hexstring( unsigned char n,      int w = 4 ) { return form( "%#0*hhx", w, n ); }
00240     inline std::string hexstring( short n,              int w = 10 ){ return form( "%#0*hx",  w, n ); }
00241     inline std::string hexstring( unsigned short n,     int w = 10 ){ return form( "%#0*hx",  w, n ); }
00242     inline std::string hexstring( int n,                int w = 10 ){ return form( "%#0*x",   w, n ); }
00243     inline std::string hexstring( unsigned n,           int w = 10 ){ return form( "%#0*x",   w, n ); }
00244     inline std::string hexstring( long n,               int w = 10 ){ return form( "%#0*lx",  w, n ); }
00245     inline std::string hexstring( unsigned long n,      int w = 10 ){ return form( "%#0*lx",  w, n ); }
00246     inline std::string hexstring( long long n,          int w = 0 ) { return form( "%#0*llx", w, n ); }
00247     inline std::string hexstring( unsigned long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
00249 
00251 
00262     inline std::string octstring( char n,               int w = 4 ) { return form( "%#0*hho",  w, n ); }
00263     inline std::string octstring( unsigned char n,      int w = 4 ) { return form( "%#0*hho",  w, n ); }
00264     inline std::string octstring( short n,              int w = 5 ) { return form( "%#0*ho",   w, n ); }
00265     inline std::string octstring( unsigned short n,     int w = 5 ) { return form( "%#0*ho",   w, n ); }
00266     inline std::string octstring( int n,                int w = 5 ) { return form( "%#0*o",    w, n ); }
00267     inline std::string octstring( unsigned n,           int w = 5 ) { return form( "%#0*o",    w, n ); }
00268     inline std::string octstring( long n,               int w = 5 ) { return form( "%#0*lo",   w, n ); }
00269     inline std::string octstring( unsigned long n,      int w = 5 ) { return form( "%#0*lo",   w, n ); }
00270     inline std::string octstring( long long n,          int w = 0 ) { return form( "%#0*llo",  w, n ); }
00271     inline std::string octstring( unsigned long long n, int w = 0 ) { return form( "%#0*llo",  w, n ); }
00273 
00275 
00284     template<typename _It>
00285       _It strtonum( const C_Str & str );
00286 
00287     template<>
00288       inline short              strtonum( const C_Str & str ) { return ::strtol  ( str, NULL, 0 ); }
00289     template<>
00290       inline int                strtonum( const C_Str & str ) { return ::strtol  ( str, NULL, 0 ); }
00291     template<>
00292       inline long               strtonum( const C_Str & str ) { return ::strtol  ( str, NULL, 0 ); }
00293     template<>
00294       inline long long          strtonum( const C_Str & str ) { return ::strtoll ( str, NULL, 0 ); }
00295 
00296     template<>
00297       inline unsigned short     strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
00298     template<>
00299       inline unsigned           strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
00300     template<>
00301       inline unsigned long      strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
00302     template<>
00303       inline unsigned long long strtonum( const C_Str & str ) { return ::strtoull( str, NULL, 0 ); }
00304 
00310     template<typename _It>
00311       inline _It strtonum( const C_Str & str, _It & i )
00312       { return i = strtonum<_It>( str ); }
00314 
00316 
00320     bool strToTrue( const C_Str & str );
00321 
00323     bool strToFalse( const C_Str & str );
00324 
00329     inline bool strToBool( const C_Str & str, bool default_r )
00330     { return( default_r ? strToFalse( str ) : strToTrue( str ) ); }
00331 
00336     inline bool strToBoolNodefault( const C_Str & str, bool & return_r )
00337     {
00338       if ( strToTrue( str ) ) return (return_r = true);
00339       if ( !strToFalse( str ) ) return (return_r = false);
00340       return return_r;
00341     }
00342 
00344 
00348     std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r );
00349 
00352     std::string gsubFun( const std::string & str_r, const std::string & from_r, function<std::string()> to_r );
00353 
00358     std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r );
00359 
00362     std::string & replaceAllFun( std::string & str_r, const std::string & from_r, function<std::string()> to_r );
00363 
00364 
00366 
00377     template<class _OutputIterator>
00378       unsigned split( const C_Str &   line_r,
00379                       _OutputIterator result_r,
00380                       const C_Str &   sepchars_r = " \t" )
00381       {
00382         const char * beg = line_r;
00383         const char * cur = beg;
00384         // skip leading sepchars
00385         while ( *cur && ::strchr( sepchars_r, *cur ) )
00386           ++cur;
00387         unsigned ret = 0;
00388         for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
00389           {
00390             // skip non sepchars
00391             while( *cur && !::strchr( sepchars_r, *cur ) )
00392               ++cur;
00393             // build string
00394             *result_r = std::string( beg, cur-beg );
00395             // skip sepchars
00396             while ( *cur && ::strchr( sepchars_r, *cur ) )
00397               ++cur;
00398           }
00399         return ret;
00400       }
00401 
00429     template<class _OutputIterator>
00430       unsigned splitEscaped( const C_Str &   line_r,
00431                       _OutputIterator result_r,
00432                       const C_Str &   sepchars_r = " \t",
00433                       bool withEmpty = false)
00434       {
00435         const char * beg = line_r;
00436         const char * cur = beg;
00437         unsigned ret = 0;
00438 
00439         // skip leading sepchars
00440         while ( *cur && ::strchr( sepchars_r, *cur ) )
00441         {
00442           ++cur;
00443           if (withEmpty)
00444           {
00445             *result_r = "";
00446             ++ret;
00447           }
00448         }
00449 
00450         // there were only sepchars in the string
00451         if (!*cur && withEmpty)
00452         {
00453           *result_r = "";
00454           return ++ret;
00455         }
00456 
00457         // after the leading sepchars
00458         for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
00459           {
00460             if ( *cur == '"'  || *cur == '\'' )
00461             {
00462               char closeChar = *cur;
00463               ++cur;
00464               bool cont = true;
00465               while (cont)
00466               {
00467                 while ( *cur && *cur != closeChar)
00468                   ++cur;
00469                 if ( *cur == '\0' )
00470                 {
00471                   return ret; //TODO parsing exception no closing quote
00472                 }
00473                 int escCount = 0;
00474                 const char * esc = cur-1;
00475                 while ( esc != beg && *esc == '\\' )
00476                 {
00477                   escCount++;
00478                   --esc;
00479                 }
00480                 cont = (escCount % 2 == 1); // find some non escaped escape char
00481                 cur++; //skip quote
00482               }
00483 
00484               std::string s( beg+1, cur-beg-2 ); //without quotes
00485               //transform escaped escape
00486               replaceAll( s, "\\\\", "\\" );
00487               //transform escaped quotes (only same as open
00488               char tmpn[2] = { closeChar, 0 };
00489               char tmpo[3] = { '\\', closeChar, 0 };
00490               replaceAll( s, tmpo, tmpn );
00491 
00492               *result_r = s;
00493             }
00494             else
00495             {
00496               // skip non sepchars
00497               while( *cur && !::strchr( sepchars_r, *cur ) )
00498               {
00499                 //ignore char after backslash
00500                 if ( *cur == '\\' )
00501                 {
00502                   ++cur;
00503                 }
00504                 ++cur;
00505               }
00506               // build string
00507               std::string s( beg, cur-beg );
00508               //transform escaped escape
00509               replaceAll( s, "\\\\", "\\" );
00510 
00511               const char *delimeter = sepchars_r;
00512               while ( *delimeter )
00513               {
00514                 std::string ds("\\");
00515                 const char tmp[2] = { *delimeter, '\0' };
00516                 std::string del(tmp);
00517                 ds+= del;
00518                 replaceAll( s, ds, del );
00519                 ++delimeter;
00520               }
00521 
00522               *result_r = s;
00523             }
00524             // skip sepchars
00525             if ( *cur && ::strchr( sepchars_r, *cur ) )
00526               ++cur;
00527             while ( *cur && ::strchr( sepchars_r, *cur ) )
00528             {
00529               ++cur;
00530               if (withEmpty)
00531               {
00532                 *result_r = "";
00533                 ++ret;
00534               }
00535             }
00536             // the last was a separator => one more field
00537             if ( !*cur && withEmpty && ::strchr( sepchars_r, *(cur-1) ) )
00538             {
00539               *result_r = "";
00540               ++ret;
00541             }
00542           }
00543         return ret;
00544       }
00545 
00566     template<class _OutputIterator>
00567       unsigned splitFields( const C_Str &   line_r,
00568                             _OutputIterator result_r,
00569                             const C_Str &   sepchars_r = ":" )
00570       {
00571         const char * beg = line_r;
00572         const char * cur = beg;
00573         unsigned ret = 0;
00574         for ( beg = cur; *beg; beg = cur, ++result_r )
00575           {
00576             // skip non sepchars
00577             while( *cur && !::strchr( sepchars_r, *cur ) )
00578               ++cur;
00579             // build string
00580             *result_r = std::string( beg, cur-beg );
00581             ++ret;
00582             // skip sepchar
00583             if ( *cur )
00584             {
00585               ++cur;
00586               if ( ! *cur )                // ending with sepchar
00587               {
00588                 *result_r = std::string(); // add final empty field
00589                 ++ret;
00590                 break;
00591               }
00592             }
00593           }
00594         return ret;
00595       }
00596 
00603     template<class _OutputIterator>
00604       unsigned splitFieldsEscaped( const C_Str &   line_r,
00605                             _OutputIterator result_r,
00606                             const C_Str &   sepchars_r = ":" )
00607       {
00608         return
00609           splitEscaped( line_r, result_r, sepchars_r, true /* withEmpty */ );
00610       }
00611 
00613 
00615 
00618     template <class _Iterator>
00619       std::string join( _Iterator begin, _Iterator end,
00620                         const C_Str & sep_r = " " )
00621       {
00622         std::string res;
00623         for ( _Iterator iter = begin; iter != end; ++ iter )
00624           {
00625             if ( iter != begin )
00626               res += sep_r;
00627             res += asString(*iter);
00628           }
00629         return res;
00630       }
00631 
00633     template <class _Container>
00634       std::string join( const _Container & cont_r,
00635                         const C_Str & sep_r = " " )
00636       { return join( cont_r.begin(), cont_r.end(), sep_r ); }
00637 
00642     template <class _Iterator>
00643       std::string joinEscaped( _Iterator begin, _Iterator end,
00644                                const char sep_r = ' ' )
00645       {
00646         std::vector<char> buf;
00647         for ( _Iterator iter = begin; iter != end; ++ iter )
00648         {
00649           if ( iter != begin )
00650             buf.push_back( sep_r );
00651 
00652           if ( iter->empty() )
00653           {
00654             // empty string goes ""
00655             buf.push_back( '"' );
00656             buf.push_back( '"' );
00657           }
00658           else
00659           {
00660             std::string toadd( asString(*iter) );
00661             for_( ch, toadd.begin(), toadd.end() )
00662             {
00663               switch ( *ch )
00664               {
00665                 case '"':
00666                 case '\'':
00667                 case '\\':
00668                   buf.push_back( '\\' );
00669                   buf.push_back( *ch );
00670                   break;
00671                 default:
00672                   if ( *ch == sep_r )
00673                     buf.push_back( '\\' );
00674                   buf.push_back( *ch );
00675               }
00676             }
00677           }
00678         }
00679         return std::string( buf.begin(), buf.end() );
00680       }
00681 
00682 
00694       std::string escape( const C_Str & str_r, const char c = ' ' );
00695 
00697       inline void appendEscaped( std::string & str_r, const C_Str & next_r, const char sep_r = ' ' )
00698       {
00699         if ( ! str_r.empty() )
00700           str_r += sep_r;
00701         if ( next_r.empty() )
00702           str_r += "\"\"";
00703         else
00704           str_r += escape( next_r, sep_r );
00705       }
00706 
00708 
00710 
00711 
00712 
00720     std::string hexencode( const C_Str & str_r );
00722     std::string hexdecode( const C_Str & str_r );
00724 
00725 
00731     std::string toLower( const std::string & s );
00733     inline std::string toLower( const char * s )
00734     { return( s ? toLower( std::string(s) ) : std::string() ); }
00735 
00739     std::string toUpper( const std::string & s );
00741     inline std::string toUpper( const char * s )
00742     { return( s ? toUpper( std::string(s) ) : std::string() ); }
00744 
00745 
00748     inline int compareCI( const C_Str & lhs, const C_Str & rhs )
00749     { return ::strcasecmp( lhs, rhs ); }
00751 
00755     inline bool contains( const C_Str & str_r, const C_Str & val_r )
00756     { return ::strstr( str_r, val_r ); }
00758     inline bool containsCI( const C_Str & str_r, const C_Str & val_r )
00759     { return ::strcasestr( str_r, val_r ); }
00761 
00763 
00768     enum Trim {
00769       NO_TRIM = 0x00,
00770       L_TRIM  = 0x01,
00771       R_TRIM  = 0x02,
00772       TRIM    = (L_TRIM|R_TRIM)
00773     };
00774 
00775     std::string trim( const std::string & s, const Trim trim_r = TRIM );
00776 
00777     inline std::string ltrim( const std::string & s )
00778     { return trim( s, L_TRIM ); }
00779 
00780     inline std::string rtrim( const std::string & s )
00781     { return trim( s, R_TRIM ); }
00783 
00784     std::string stripFirstWord( std::string & line, const bool ltrim_first );
00785 
00786     std::string stripLastWord( std::string & line, const bool rtrim_first );
00787 
00791     std::string getline( std::istream & str, bool trim = false );
00792 
00796     std::string getline( std::istream & str, const Trim trim_r );
00797 
00805     std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r = false );
00806 
00808 
00813     inline bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r )
00814     { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
00815 
00817     inline std::string stripPrefix( const C_Str & str_r, const C_Str & prefix_r )
00818     { return( hasPrefix( str_r, prefix_r ) ? str_r + prefix_r.size() : str_r.c_str() ); }
00819 
00821     inline bool hasSuffix( const C_Str & str_r, const C_Str & suffix_r )
00822     { return( str_r.size() >= suffix_r.size() && ::strncmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); }
00823 
00825     inline std::string stripSuffix( const C_Str & str_r, const C_Str & suffix_r )
00826     {
00827       if ( hasSuffix( str_r, suffix_r ) )
00828         return std::string( str_r, str_r.size() - suffix_r.size() );
00829       return str_r.c_str();
00830     }
00831 
00833     inline bool startsWith( const C_Str & str_r, const C_Str & prefix_r )
00834     { return hasPrefix( str_r, prefix_r ); }
00836     inline bool endsWith( const C_Str & str_r, const C_Str & prefix_r )
00837     { return hasSuffix( str_r, prefix_r ); }
00839 
00840   } // namespace str
00843 } // namespace zypp
00845 #endif // ZYPP_BASE_STRING_H