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 
00026 namespace zypp
00027 { 
00028 
00067   class C_Str
00068   {
00069     public:
00070       typedef std::string::size_type size_type;
00071 
00072     public:
00073       C_Str()                            : _val( 0 ),             _sze( 0 ) {}
00074       C_Str( char * c_str_r )            : _val( c_str_r ),       _sze( std::string::npos ) {}
00075       C_Str( const char * c_str_r )      : _val( c_str_r ),       _sze( std::string::npos ) {}
00076       C_Str( const std::string & str_r ) : _val( str_r.c_str() ), _sze( str_r.size() ) {}
00077 
00078     public:
00079       bool      isNull()       const { return !_val; }
00080       bool      empty()        const { return !(_val && *_val); }
00081       size_type size()         const
00082       {
00083         if ( _sze == std::string::npos )
00084         { _sze = _val ? ::strlen( _val ) : 0; }
00085         return _sze;
00086       };
00087 
00088       operator const char *() const { return c_str(); }
00089       const char * c_str()    const { return _val ? _val : ""; }
00090 
00091     private:
00092       const char *const _val;
00093       mutable size_type _sze;
00094   };
00095 
00097   inline std::ostream & operator<<( std::ostream & str, const C_Str & obj )
00098   { return str << obj.c_str(); }
00099 
00101 
00104   namespace str
00105   { 
00106 
00108 
00111     inline std::string asString( const std::string &t )
00112     { return t; }
00113 
00114     inline std::string asString( const char * t )
00115     { return t; }
00116 
00117     template<class _T>
00118         inline std::string asString( const _T &t )
00119         { return t.asString(); }
00120 
00121     template<class _T>
00122         inline std::string asString( const intrusive_ptr<_T> &p )
00123         { return p->asString(); }
00124 
00125     template<class _T>
00126         inline std::string asString( const weak_ptr<_T> &p )
00127         { return p->asString(); }
00128 
00129     template<>
00130         inline std::string asString( const bool &t )
00131         { return t ? "+" : "-"; }
00132 
00134 
00135     std::string form( const char * format, ... )
00136     __attribute__ ((format (printf, 1, 2)));
00137 
00139 
00143     std::string strerror( int errno_r );
00144 
00146 
00156     struct SafeBuf
00157     {
00158       char * _buf;
00159       SafeBuf() : _buf( 0 ) {}
00160       ~SafeBuf() { if ( _buf ) free( _buf ); }
00161       std::string asString() const
00162       { return _buf ? std::string(_buf) : std::string(); }
00163     };
00164 
00166 
00176     struct Str
00177     {
00178       template<class _Tp>
00179       Str & operator<<( const _Tp & val )
00180       { _str << val; return *this; }
00181 
00182       operator std::string() const
00183       { return _str.str(); }
00184 
00185       std::ostringstream _str;
00186     };
00187 
00189 
00202     inline std::string numstring( char n,               int w = 0 ) { return form( "%*hhd",  w, n ); }
00203     inline std::string numstring( unsigned char n,      int w = 0 ) { return form( "%*hhu",  w, n ); }
00204     inline std::string numstring( short n,              int w = 0 ) { return form( "%*hd",   w, n ); }
00205     inline std::string numstring( unsigned short n,     int w = 0 ) { return form( "%*hu",   w, n ); }
00206     inline std::string numstring( int n,                int w = 0 ) { return form( "%*d",    w, n ); }
00207     inline std::string numstring( unsigned n,           int w = 0 ) { return form( "%*u",    w, n ); }
00208     inline std::string numstring( long n,               int w = 0 ) { return form( "%*ld",   w, n ); }
00209     inline std::string numstring( unsigned long n,      int w = 0 ) { return form( "%*lu",   w, n ); }
00210     inline std::string numstring( long long n,          int w = 0 ) { return form( "%*lld",  w, n ); }
00211     inline std::string numstring( unsigned long long n, int w = 0 ) { return form( "%*llu",  w, n ); }
00212 
00213     template<> inline std::string asString( const char & t )                    { return numstring( t ); }
00214     template<> inline std::string asString( const unsigned char & t )           { return numstring( t ); }
00215     template<> inline std::string asString( const short & t )                   { return numstring( t ); }
00216     template<> inline std::string asString( const unsigned short & t )          { return numstring( t ); }
00217     template<> inline std::string asString( const int & t )                     { return numstring( t ); }
00218     template<> inline std::string asString( const unsigned & t )                { return numstring( t ); }
00219     template<> inline std::string asString( const long & t )                    { return numstring( t ); }
00220     template<> inline std::string asString( const unsigned long & t )           { return numstring( t ); }
00221     template<> inline std::string asString( const long long & t )               { return numstring( t ); }
00222     template<> inline std::string asString( const unsigned long long & t )      { return numstring( t ); }
00224 
00226 
00237     inline std::string hexstring( char n,               int w = 4 ) { return form( "%#0*hhx", w, n ); }
00238     inline std::string hexstring( unsigned char n,      int w = 4 ) { return form( "%#0*hhx", w, n ); }
00239     inline std::string hexstring( short n,              int w = 10 ){ return form( "%#0*hx",  w, n ); }
00240     inline std::string hexstring( unsigned short n,     int w = 10 ){ return form( "%#0*hx",  w, n ); }
00241     inline std::string hexstring( int n,                int w = 10 ){ return form( "%#0*x",   w, n ); }
00242     inline std::string hexstring( unsigned n,           int w = 10 ){ return form( "%#0*x",   w, n ); }
00243     inline std::string hexstring( long n,               int w = 10 ){ return form( "%#0*lx",  w, n ); }
00244     inline std::string hexstring( unsigned long n,      int w = 10 ){ return form( "%#0*lx",  w, n ); }
00245     inline std::string hexstring( long long n,          int w = 0 ) { return form( "%#0*llx", w, n ); }
00246     inline std::string hexstring( unsigned long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
00248 
00250 
00261     inline std::string octstring( char n,               int w = 4 ) { return form( "%#0*hho",  w, n ); }
00262     inline std::string octstring( unsigned char n,      int w = 4 ) { return form( "%#0*hho",  w, n ); }
00263     inline std::string octstring( short n,              int w = 5 ) { return form( "%#0*ho",   w, n ); }
00264     inline std::string octstring( unsigned short n,     int w = 5 ) { return form( "%#0*ho",   w, n ); }
00265     inline std::string octstring( int n,                int w = 5 ) { return form( "%#0*o",    w, n ); }
00266     inline std::string octstring( unsigned n,           int w = 5 ) { return form( "%#0*o",    w, n ); }
00267     inline std::string octstring( long n,               int w = 5 ) { return form( "%#0*lo",   w, n ); }
00268     inline std::string octstring( unsigned long n,      int w = 5 ) { return form( "%#0*lo",   w, n ); }
00269     inline std::string octstring( long long n,          int w = 0 ) { return form( "%#0*llo",  w, n ); }
00270     inline std::string octstring( unsigned long long n, int w = 0 ) { return form( "%#0*llo",  w, n ); }
00272 
00274 
00283     template<typename _It>
00284       _It strtonum( const C_Str & str );
00285 
00286     template<>
00287       inline short              strtonum( const C_Str & str ) { return ::strtol  ( str, NULL, 0 ); }
00288     template<>
00289       inline int                strtonum( const C_Str & str ) { return ::strtol  ( str, NULL, 0 ); }
00290     template<>
00291       inline long               strtonum( const C_Str & str ) { return ::strtol  ( str, NULL, 0 ); }
00292     template<>
00293       inline long long          strtonum( const C_Str & str ) { return ::strtoll ( str, NULL, 0 ); }
00294 
00295     template<>
00296       inline unsigned short     strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
00297     template<>
00298       inline unsigned           strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
00299     template<>
00300       inline unsigned long      strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
00301     template<>
00302       inline unsigned long long strtonum( const C_Str & str ) { return ::strtoull( str, NULL, 0 ); }
00303 
00309     template<typename _It>
00310       inline _It strtonum( const C_Str & str, _It & i )
00311       { return i = strtonum<_It>( str ); }
00313 
00315 
00319     bool strToTrue( const C_Str & str );
00320 
00322     bool strToFalse( const C_Str & str );
00323 
00328     inline bool strToBool( const C_Str & str, bool default_r )
00329     { return( default_r ? strToFalse( str ) : strToTrue( str ) ); }
00330 
00335     inline bool strToBoolNodefault( const C_Str & str, bool & return_r )
00336     {
00337       if ( strToTrue( str ) ) return (return_r = true);
00338       if ( !strToFalse( str ) ) return (return_r = false);
00339       return return_r;
00340     }
00341 
00343 
00349     std::string gsub( const std::string& sData, const std::string& sFrom, const std::string& sTo);
00350 
00358     std::string& replaceAll( std::string & str, const std::string & from, const std::string & to);
00359 
00361 
00372     template<class _OutputIterator>
00373       unsigned split( const C_Str &   line_r,
00374                       _OutputIterator result_r,
00375                       const C_Str &   sepchars_r = " \t" )
00376       {
00377         const char * beg = line_r;
00378         const char * cur = beg;
00379         // skip leading sepchars
00380         while ( *cur && ::strchr( sepchars_r, *cur ) )
00381           ++cur;
00382         unsigned ret = 0;
00383         for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
00384           {
00385             // skip non sepchars
00386             while( *cur && !::strchr( sepchars_r, *cur ) )
00387               ++cur;
00388             // build string
00389             *result_r = std::string( beg, cur-beg );
00390             // skip sepchars
00391             while ( *cur && ::strchr( sepchars_r, *cur ) )
00392               ++cur;
00393           }
00394         return ret;
00395       }
00396 
00424     template<class _OutputIterator>
00425       unsigned splitEscaped( const C_Str &   line_r,
00426                       _OutputIterator result_r,
00427                       const C_Str &   sepchars_r = " \t",
00428                       bool withEmpty = false)
00429       {
00430         const char * beg = line_r;
00431         const char * cur = beg;
00432         unsigned ret = 0;
00433 
00434         // skip leading sepchars
00435         while ( *cur && ::strchr( sepchars_r, *cur ) )
00436         {
00437           ++cur;
00438           if (withEmpty)
00439           {
00440             *result_r = "";
00441             ++ret;
00442           }
00443         }
00444 
00445         // there were only sepchars in the string
00446         if (!*cur && withEmpty)
00447         {
00448           *result_r = "";
00449           return ++ret;
00450         }
00451 
00452         // after the leading sepchars
00453         for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
00454           {
00455             if ( *cur == '"'  || *cur == '\'' )
00456             {
00457               char closeChar = *cur;
00458               ++cur;
00459               bool cont = true;
00460               while (cont)
00461               {
00462                 while ( *cur && *cur != closeChar)
00463                   ++cur;
00464                 if ( *cur == '\0' )
00465                 {
00466                   return ret; //TODO parsing exception no closing quote
00467                 }
00468                 int escCount = 0;
00469                 const char * esc = cur-1;
00470                 while ( esc != beg && *esc == '\\' )
00471                 {
00472                   escCount++;
00473                   --esc;
00474                 }
00475                 cont = (escCount % 2 == 1); // find some non escaped escape char
00476                 cur++; //skip quote
00477               }
00478 
00479               std::string s( beg+1, cur-beg-2 ); //without quotes
00480               //transform escaped escape
00481               replaceAll( s, "\\\\", "\\" );
00482               //transform escaped quotes (only same as open
00483               char tmpn[2] = { closeChar, 0 };
00484               char tmpo[3] = { '\\', closeChar, 0 };
00485               replaceAll( s, tmpo, tmpn );
00486 
00487               *result_r = s;
00488             }
00489             else
00490             {
00491               // skip non sepchars
00492               while( *cur && !::strchr( sepchars_r, *cur ) )
00493               {
00494                 //ignore char after backslash
00495                 if ( *cur == '\\' )
00496                 {
00497                   ++cur;
00498                 }
00499                 ++cur;
00500               }
00501               // build string
00502               std::string s( beg, cur-beg );
00503               //transform escaped escape
00504               replaceAll( s, "\\\\", "\\" );
00505 
00506               const char *delimeter = sepchars_r;
00507               while ( *delimeter )
00508               {
00509                 std::string ds("\\");
00510                 const char tmp[2] = { *delimeter, '\0' };
00511                 std::string del(tmp);
00512                 ds+= del;
00513                 replaceAll( s, ds, del );
00514                 ++delimeter;
00515               }
00516 
00517               *result_r = s;
00518             }
00519             // skip sepchars
00520             if ( *cur && ::strchr( sepchars_r, *cur ) )
00521               ++cur;
00522             while ( *cur && ::strchr( sepchars_r, *cur ) )
00523             {
00524               ++cur;
00525               if (withEmpty)
00526               {
00527                 *result_r = "";
00528                 ++ret;
00529               }
00530             }
00531             // the last was a separator => one more field
00532             if ( !*cur && withEmpty && ::strchr( sepchars_r, *(cur-1) ) )
00533             {
00534               *result_r = "";
00535               ++ret;
00536             }
00537           }
00538         return ret;
00539       }
00540 
00561     template<class _OutputIterator>
00562       unsigned splitFields( const C_Str &   line_r,
00563                             _OutputIterator result_r,
00564                             const C_Str &   sepchars_r = ":" )
00565       {
00566         const char * beg = line_r;
00567         const char * cur = beg;
00568         unsigned ret = 0;
00569         for ( beg = cur; *beg; beg = cur, ++result_r )
00570           {
00571             // skip non sepchars
00572             while( *cur && !::strchr( sepchars_r, *cur ) )
00573               ++cur;
00574             // build string
00575             *result_r = std::string( beg, cur-beg );
00576             ++ret;
00577             // skip sepchar
00578             if ( *cur )
00579             {
00580               ++cur;
00581               if ( ! *cur )                // ending with sepchar
00582               {
00583                 *result_r = std::string(); // add final empty field
00584                 ++ret;
00585                 break;
00586               }
00587             }
00588           }
00589         return ret;
00590       }
00591 
00598     template<class _OutputIterator>
00599       unsigned splitFieldsEscaped( const C_Str &   line_r,
00600                             _OutputIterator result_r,
00601                             const C_Str &   sepchars_r = ":" )
00602       {
00603         return
00604           splitEscaped( line_r, result_r, sepchars_r, true /* withEmpty */ );
00605       }
00606 
00608 
00610 
00613     template <class _Iterator>
00614       std::string join( _Iterator begin, _Iterator end,
00615                         const C_Str & sep_r = " " )
00616       {
00617         std::string res;
00618         for ( _Iterator iter = begin; iter != end; ++ iter )
00619           {
00620             if ( iter != begin )
00621               res += sep_r;
00622             res += asString(*iter);
00623           }
00624         return res;
00625       }
00626 
00628     template <class _Container>
00629       std::string join( const _Container & cont_r,
00630                         const C_Str & sep_r = " " )
00631       { return join( cont_r.begin(), cont_r.end(), sep_r ); }
00632 
00637     template <class _Iterator>
00638       std::string joinEscaped( _Iterator begin, _Iterator end,
00639                                const char sep_r = ' ' )
00640       {
00641         std::vector<char> buf;
00642         for ( _Iterator iter = begin; iter != end; ++ iter )
00643         {
00644           if ( iter != begin )
00645             buf.push_back( sep_r );
00646 
00647           if ( iter->empty() )
00648           {
00649             // empty string goes ""
00650             buf.push_back( '"' );
00651             buf.push_back( '"' );
00652           }
00653           else
00654           {
00655             std::string toadd( asString(*iter) );
00656             for_( ch, toadd.begin(), toadd.end() )
00657             {
00658               switch ( *ch )
00659               {
00660                 case '"':
00661                 case '\'':
00662                 case '\\':
00663                   buf.push_back( '\\' );
00664                   buf.push_back( *ch );
00665                   break;
00666                 default:
00667                   if ( *ch == sep_r )
00668                     buf.push_back( '\\' );
00669                   buf.push_back( *ch );
00670               }
00671             }
00672           }
00673         }
00674         return std::string( buf.begin(), buf.end() );
00675       }
00676 
00677 
00689       std::string escape( const C_Str & str_r, const char c = ' ' );
00690 
00692       inline void appendEscaped( std::string & str_r, const C_Str & next_r, const char sep_r = ' ' )
00693       {
00694         if ( ! str_r.empty() )
00695           str_r += sep_r;
00696         if ( next_r.empty() )
00697           str_r += "\"\"";
00698         else
00699           str_r += escape( next_r, sep_r );
00700       }
00701 
00703 
00705 
00706 
00707 
00715     std::string hexencode( const C_Str & str_r );
00717     std::string hexdecode( const C_Str & str_r );
00719 
00720 
00726     std::string toLower( const std::string & s );
00728     inline std::string toLower( const char * s )
00729     { return( s ? toLower( std::string(s) ) : std::string() ); }
00730 
00734     std::string toUpper( const std::string & s );
00736     inline std::string toUpper( const char * s )
00737     { return( s ? toUpper( std::string(s) ) : std::string() ); }
00739 
00740 
00743     inline int compareCI( const C_Str & lhs, const C_Str & rhs )
00744     { return ::strcasecmp( lhs, rhs ); }
00746 
00750     inline bool contains( const C_Str & str_r, const C_Str & val_r )
00751     { return ::strstr( str_r, val_r ); }
00753     inline bool containsCI( const C_Str & str_r, const C_Str & val_r )
00754     { return ::strcasestr( str_r, val_r ); }
00756 
00758 
00763     enum Trim {
00764       NO_TRIM = 0x00,
00765       L_TRIM  = 0x01,
00766       R_TRIM  = 0x02,
00767       TRIM    = (L_TRIM|R_TRIM)
00768     };
00769 
00770     std::string trim( const std::string & s, const Trim trim_r = TRIM );
00771 
00772     inline std::string ltrim( const std::string & s )
00773     { return trim( s, L_TRIM ); }
00774 
00775     inline std::string rtrim( const std::string & s )
00776     { return trim( s, R_TRIM ); }
00778 
00779     std::string stripFirstWord( std::string & line, const bool ltrim_first );
00780 
00781     std::string stripLastWord( std::string & line, const bool rtrim_first );
00782 
00786     std::string getline( std::istream & str, bool trim = false );
00787 
00791     std::string getline( std::istream & str, const Trim trim_r );
00792 
00800     std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r = false );
00801 
00803 
00808     inline bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r )
00809     { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
00810 
00812     inline std::string stripPrefix( const C_Str & str_r, const C_Str & prefix_r )
00813     { return( hasPrefix( str_r, prefix_r ) ? str_r + prefix_r.size() : str_r.c_str() ); }
00814 
00816     inline bool hasSuffix( const C_Str & str_r, const C_Str & suffix_r )
00817     { return( str_r.size() >= suffix_r.size() && ::strncmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); }
00818 
00820     inline std::string stripSuffix( const C_Str & str_r, const C_Str & suffix_r )
00821     {
00822       if ( hasSuffix( str_r, suffix_r ) )
00823         return std::string( str_r, str_r.size() - suffix_r.size() );
00824       return str_r.c_str();
00825     }
00826 
00828     inline bool startsWith( const C_Str & str_r, const C_Str & prefix_r )
00829     { return hasPrefix( str_r, prefix_r ); }
00831     inline bool endsWith( const C_Str & str_r, const C_Str & prefix_r )
00832     { return hasSuffix( str_r, prefix_r ); }
00834 
00835   } // namespace str
00838 } // namespace zypp
00840 #endif // ZYPP_BASE_STRING_H

doxygen