libzypp 9.41.1

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 #include <boost/format.hpp>
00022 
00023 #include "zypp/base/Easy.h"
00024 #include "zypp/base/PtrTypes.h"
00025 
00026 
00028 namespace boost
00029 {
00035   inline format formatNAC( const std::string & string_r ) {
00036     using namespace boost::io;
00037     format fmter( string_r );
00038     fmter.exceptions( all_error_bits ^ ( too_many_args_bit | too_few_args_bit ) );
00039     return fmter;
00040   }
00041 } // namespace boost
00043 
00045 namespace zypp
00046 { 
00047 
00086   class C_Str
00087   {
00088     public:
00089       typedef std::string::size_type size_type;
00090 
00091     public:
00092       C_Str()                            : _val( 0 ),             _sze( 0 ) {}
00093       C_Str( char * c_str_r )            : _val( c_str_r ),       _sze( std::string::npos ) {}
00094       C_Str( const char * c_str_r )      : _val( c_str_r ),       _sze( std::string::npos ) {}
00095       C_Str( const std::string & str_r ) : _val( str_r.c_str() ), _sze( str_r.size() ) {}
00096 
00097     public:
00098       bool      isNull()       const { return !_val; }
00099       bool      empty()        const { return !(_val && *_val); }
00100       size_type size()         const
00101       {
00102         if ( _sze == std::string::npos )
00103         { _sze = _val ? ::strlen( _val ) : 0; }
00104         return _sze;
00105       };
00106 
00107       operator const char *() const { return c_str(); }
00108       const char * c_str()    const { return _val ? _val : ""; }
00109 
00110     private:
00111       const char *const _val;
00112       mutable size_type _sze;
00113   };
00114 
00116   inline std::ostream & operator<<( std::ostream & str, const C_Str & obj )
00117   { return str << obj.c_str(); }
00118 
00120 
00123   namespace str
00124   { 
00125 
00127 
00130     inline std::string asString( const std::string &t )
00131     { return t; }
00132 
00133     inline std::string asString( const char * t )
00134     { return t; }
00135 
00136     inline std::string asString( char * t )
00137     { return t; }
00138 
00139     template<class _T>
00140         inline std::string asString( const _T &t )
00141         { return t.asString(); }
00142 
00143     template<class _T>
00144         inline std::string asString( const intrusive_ptr<_T> &p )
00145         { return p->asString(); }
00146 
00147     template<class _T>
00148         inline std::string asString( const weak_ptr<_T> &p )
00149         { return p->asString(); }
00150 
00151     template<>
00152         inline std::string asString( const bool &t )
00153         { return t ? "+" : "-"; }
00154 
00156 
00157     std::string form( const char * format, ... )
00158     __attribute__ ((format (printf, 1, 2)));
00159 
00161 
00165     std::string strerror( int errno_r );
00166 
00168 
00178     struct SafeBuf
00179     {
00180       char * _buf;
00181       SafeBuf() : _buf( 0 ) {}
00182       ~SafeBuf() { if ( _buf ) free( _buf ); }
00183       std::string asString() const
00184       { return _buf ? std::string(_buf) : std::string(); }
00185     };
00186 
00188 
00198     struct Str
00199     {
00200       template<class _Tp>
00201       Str & operator<<( const _Tp & val )
00202       { _str << val; return *this; }
00203 
00204       operator std::string() const
00205       { return _str.str(); }
00206 
00207       std::ostringstream _str;
00208     };
00209 
00211 
00224     inline std::string numstring( char n,               int w = 0 ) { return form( "%*hhd",  w, n ); }
00225     inline std::string numstring( unsigned char n,      int w = 0 ) { return form( "%*hhu",  w, n ); }
00226     inline std::string numstring( short n,              int w = 0 ) { return form( "%*hd",   w, n ); }
00227     inline std::string numstring( unsigned short n,     int w = 0 ) { return form( "%*hu",   w, n ); }
00228     inline std::string numstring( int n,                int w = 0 ) { return form( "%*d",    w, n ); }
00229     inline std::string numstring( unsigned n,           int w = 0 ) { return form( "%*u",    w, n ); }
00230     inline std::string numstring( long n,               int w = 0 ) { return form( "%*ld",   w, n ); }
00231     inline std::string numstring( unsigned long n,      int w = 0 ) { return form( "%*lu",   w, n ); }
00232     inline std::string numstring( long long n,          int w = 0 ) { return form( "%*lld",  w, n ); }
00233     inline std::string numstring( unsigned long long n, int w = 0 ) { return form( "%*llu",  w, n ); }
00234 
00235     template<> inline std::string asString( const char & t )                    { return numstring( t ); }
00236     template<> inline std::string asString( const unsigned char & t )           { return numstring( t ); }
00237     template<> inline std::string asString( const short & t )                   { return numstring( t ); }
00238     template<> inline std::string asString( const unsigned short & t )          { return numstring( t ); }
00239     template<> inline std::string asString( const int & t )                     { return numstring( t ); }
00240     template<> inline std::string asString( const unsigned & t )                { return numstring( t ); }
00241     template<> inline std::string asString( const long & t )                    { return numstring( t ); }
00242     template<> inline std::string asString( const unsigned long & t )           { return numstring( t ); }
00243     template<> inline std::string asString( const long long & t )               { return numstring( t ); }
00244     template<> inline std::string asString( const unsigned long long & t )      { return numstring( t ); }
00246 
00248 
00259     inline std::string hexstring( char n,               int w = 4 ) { return form( "%#0*hhx", w, n ); }
00260     inline std::string hexstring( unsigned char n,      int w = 4 ) { return form( "%#0*hhx", w, n ); }
00261     inline std::string hexstring( short n,              int w = 10 ){ return form( "%#0*hx",  w, n ); }
00262     inline std::string hexstring( unsigned short n,     int w = 10 ){ return form( "%#0*hx",  w, n ); }
00263     inline std::string hexstring( int n,                int w = 10 ){ return form( "%#0*x",   w, n ); }
00264     inline std::string hexstring( unsigned n,           int w = 10 ){ return form( "%#0*x",   w, n ); }
00265     inline std::string hexstring( long n,               int w = 10 ){ return form( "%#0*lx",  w, n ); }
00266     inline std::string hexstring( unsigned long n,      int w = 10 ){ return form( "%#0*lx",  w, n ); }
00267     inline std::string hexstring( long long n,          int w = 0 ) { return form( "%#0*llx", w, n ); }
00268     inline std::string hexstring( unsigned long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
00270 
00272 
00283     inline std::string octstring( char n,               int w = 4 ) { return form( "%#0*hho",  w, n ); }
00284     inline std::string octstring( unsigned char n,      int w = 4 ) { return form( "%#0*hho",  w, n ); }
00285     inline std::string octstring( short n,              int w = 5 ) { return form( "%#0*ho",   w, n ); }
00286     inline std::string octstring( unsigned short n,     int w = 5 ) { return form( "%#0*ho",   w, n ); }
00287     inline std::string octstring( int n,                int w = 5 ) { return form( "%#0*o",    w, n ); }
00288     inline std::string octstring( unsigned n,           int w = 5 ) { return form( "%#0*o",    w, n ); }
00289     inline std::string octstring( long n,               int w = 5 ) { return form( "%#0*lo",   w, n ); }
00290     inline std::string octstring( unsigned long n,      int w = 5 ) { return form( "%#0*lo",   w, n ); }
00291     inline std::string octstring( long long n,          int w = 0 ) { return form( "%#0*llo",  w, n ); }
00292     inline std::string octstring( unsigned long long n, int w = 0 ) { return form( "%#0*llo",  w, n ); }
00294 
00296 
00305     template<typename _It>
00306       _It strtonum( const C_Str & str );
00307 
00308     template<>
00309       inline short              strtonum( const C_Str & str ) { return ::strtol  ( str, NULL, 0 ); }
00310     template<>
00311       inline int                strtonum( const C_Str & str ) { return ::strtol  ( str, NULL, 0 ); }
00312     template<>
00313       inline long               strtonum( const C_Str & str ) { return ::strtol  ( str, NULL, 0 ); }
00314     template<>
00315       inline long long          strtonum( const C_Str & str ) { return ::strtoll ( str, NULL, 0 ); }
00316 
00317     template<>
00318       inline unsigned short     strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
00319     template<>
00320       inline unsigned           strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
00321     template<>
00322       inline unsigned long      strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
00323     template<>
00324       inline unsigned long long strtonum( const C_Str & str ) { return ::strtoull( str, NULL, 0 ); }
00325 
00331     template<typename _It>
00332       inline _It strtonum( const C_Str & str, _It & i )
00333       { return i = strtonum<_It>( str ); }
00335 
00337 
00341     bool strToTrue( const C_Str & str );
00342 
00344     bool strToFalse( const C_Str & str );
00345 
00350     inline bool strToBool( const C_Str & str, bool default_r )
00351     { return( default_r ? strToFalse( str ) : strToTrue( str ) ); }
00352 
00357     inline bool strToBoolNodefault( const C_Str & str, bool & return_r )
00358     {
00359       if ( strToTrue( str ) ) return (return_r = true);
00360       if ( !strToFalse( str ) ) return (return_r = false);
00361       return return_r;
00362     }
00363 
00365 
00371     std::string gsub( const std::string& sData, const std::string& sFrom, const std::string& sTo);
00372 
00380     std::string& replaceAll( std::string & str, const std::string & from, const std::string & to);
00381 
00383 
00394     template<class _OutputIterator>
00395       unsigned split( const C_Str &   line_r,
00396                       _OutputIterator result_r,
00397                       const C_Str &   sepchars_r = " \t" )
00398       {
00399         const char * beg = line_r;
00400         const char * cur = beg;
00401         // skip leading sepchars
00402         while ( *cur && ::strchr( sepchars_r, *cur ) )
00403           ++cur;
00404         unsigned ret = 0;
00405         for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
00406           {
00407             // skip non sepchars
00408             while( *cur && !::strchr( sepchars_r, *cur ) )
00409               ++cur;
00410             // build string
00411             *result_r = std::string( beg, cur-beg );
00412             // skip sepchars
00413             while ( *cur && ::strchr( sepchars_r, *cur ) )
00414               ++cur;
00415           }
00416         return ret;
00417       }
00418 
00446     template<class _OutputIterator>
00447       unsigned splitEscaped( const C_Str &   line_r,
00448                       _OutputIterator result_r,
00449                       const C_Str &   sepchars_r = " \t",
00450                       bool withEmpty = false)
00451       {
00452         const char * beg = line_r;
00453         const char * cur = beg;
00454         unsigned ret = 0;
00455 
00456         // skip leading sepchars
00457         while ( *cur && ::strchr( sepchars_r, *cur ) )
00458         {
00459           ++cur;
00460           if (withEmpty)
00461           {
00462             *result_r = "";
00463             ++ret;
00464           }
00465         }
00466 
00467         // there were only sepchars in the string
00468         if (!*cur && withEmpty)
00469         {
00470           *result_r = "";
00471           return ++ret;
00472         }
00473 
00474         // after the leading sepchars
00475         for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
00476           {
00477             if ( *cur == '"'  || *cur == '\'' )
00478             {
00479               char closeChar = *cur;
00480               ++cur;
00481               bool cont = true;
00482               while (cont)
00483               {
00484                 while ( *cur && *cur != closeChar)
00485                   ++cur;
00486                 if ( *cur == '\0' )
00487                 {
00488                   return ret; //TODO parsing exception no closing quote
00489                 }
00490                 int escCount = 0;
00491                 const char * esc = cur-1;
00492                 while ( esc != beg && *esc == '\\' )
00493                 {
00494                   escCount++;
00495                   --esc;
00496                 }
00497                 cont = (escCount % 2 == 1); // find some non escaped escape char
00498                 cur++; //skip quote
00499               }
00500 
00501               std::string s( beg+1, cur-beg-2 ); //without quotes
00502               //transform escaped escape
00503               replaceAll( s, "\\\\", "\\" );
00504               //transform escaped quotes (only same as open
00505               char tmpn[2] = { closeChar, 0 };
00506               char tmpo[3] = { '\\', closeChar, 0 };
00507               replaceAll( s, tmpo, tmpn );
00508 
00509               *result_r = s;
00510             }
00511             else
00512             {
00513               // skip non sepchars
00514               while( *cur && !::strchr( sepchars_r, *cur ) )
00515               {
00516                 //ignore char after backslash
00517                 if ( *cur == '\\' )
00518                 {
00519                   ++cur;
00520                 }
00521                 ++cur;
00522               }
00523               // build string
00524               std::string s( beg, cur-beg );
00525               //transform escaped escape
00526               replaceAll( s, "\\\\", "\\" );
00527 
00528               const char *delimeter = sepchars_r;
00529               while ( *delimeter )
00530               {
00531                 std::string ds("\\");
00532                 const char tmp[2] = { *delimeter, '\0' };
00533                 std::string del(tmp);
00534                 ds+= del;
00535                 replaceAll( s, ds, del );
00536                 ++delimeter;
00537               }
00538 
00539               *result_r = s;
00540             }
00541             // skip sepchars
00542             if ( *cur && ::strchr( sepchars_r, *cur ) )
00543               ++cur;
00544             while ( *cur && ::strchr( sepchars_r, *cur ) )
00545             {
00546               ++cur;
00547               if (withEmpty)
00548               {
00549                 *result_r = "";
00550                 ++ret;
00551               }
00552             }
00553             // the last was a separator => one more field
00554             if ( !*cur && withEmpty && ::strchr( sepchars_r, *(cur-1) ) )
00555             {
00556               *result_r = "";
00557               ++ret;
00558             }
00559           }
00560         return ret;
00561       }
00562 
00583     template<class _OutputIterator>
00584       unsigned splitFields( const C_Str &   line_r,
00585                             _OutputIterator result_r,
00586                             const C_Str &   sepchars_r = ":" )
00587       {
00588         const char * beg = line_r;
00589         const char * cur = beg;
00590         unsigned ret = 0;
00591         for ( beg = cur; *beg; beg = cur, ++result_r )
00592           {
00593             // skip non sepchars
00594             while( *cur && !::strchr( sepchars_r, *cur ) )
00595               ++cur;
00596             // build string
00597             *result_r = std::string( beg, cur-beg );
00598             ++ret;
00599             // skip sepchar
00600             if ( *cur )
00601             {
00602               ++cur;
00603               if ( ! *cur )                // ending with sepchar
00604               {
00605                 *result_r = std::string(); // add final empty field
00606                 ++ret;
00607                 break;
00608               }
00609             }
00610           }
00611         return ret;
00612       }
00613 
00620     template<class _OutputIterator>
00621       unsigned splitFieldsEscaped( const C_Str &   line_r,
00622                             _OutputIterator result_r,
00623                             const C_Str &   sepchars_r = ":" )
00624       {
00625         return
00626           splitEscaped( line_r, result_r, sepchars_r, true /* withEmpty */ );
00627       }
00628 
00630 
00632 
00635     template <class _Iterator>
00636       std::string join( _Iterator begin, _Iterator end,
00637                         const C_Str & sep_r = " " )
00638       {
00639         std::string res;
00640         for ( _Iterator iter = begin; iter != end; ++ iter )
00641           {
00642             if ( iter != begin )
00643               res += sep_r;
00644             res += asString(*iter);
00645           }
00646         return res;
00647       }
00648 
00650     template <class _Container>
00651       std::string join( const _Container & cont_r,
00652                         const C_Str & sep_r = " " )
00653       { return join( cont_r.begin(), cont_r.end(), sep_r ); }
00654 
00659     template <class _Iterator>
00660       std::string joinEscaped( _Iterator begin, _Iterator end,
00661                                const char sep_r = ' ' )
00662       {
00663         std::vector<char> buf;
00664         for ( _Iterator iter = begin; iter != end; ++ iter )
00665         {
00666           if ( iter != begin )
00667             buf.push_back( sep_r );
00668 
00669           if ( iter->empty() )
00670           {
00671             // empty string goes ""
00672             buf.push_back( '"' );
00673             buf.push_back( '"' );
00674           }
00675           else
00676           {
00677             std::string toadd( asString(*iter) );
00678             for_( ch, toadd.begin(), toadd.end() )
00679             {
00680               switch ( *ch )
00681               {
00682                 case '"':
00683                 case '\'':
00684                 case '\\':
00685                   buf.push_back( '\\' );
00686                   buf.push_back( *ch );
00687                   break;
00688                 default:
00689                   if ( *ch == sep_r )
00690                     buf.push_back( '\\' );
00691                   buf.push_back( *ch );
00692               }
00693             }
00694           }
00695         }
00696         return std::string( buf.begin(), buf.end() );
00697       }
00698 
00699 
00711       std::string escape( const C_Str & str_r, const char c = ' ' );
00712 
00714       inline void appendEscaped( std::string & str_r, const C_Str & next_r, const char sep_r = ' ' )
00715       {
00716         if ( ! str_r.empty() )
00717           str_r += sep_r;
00718         if ( next_r.empty() )
00719           str_r += "\"\"";
00720         else
00721           str_r += escape( next_r, sep_r );
00722       }
00723 
00725       std::string bEscape( const std::string & str_r, const C_Str & special_r );
00726 
00728       std::string rxEscapeStr( const std::string & str_r );
00729 
00731       std::string rxEscapeGlob( const std::string & str_r );
00732 
00734 
00736 
00737 
00738 
00746     std::string hexencode( const C_Str & str_r );
00748     std::string hexdecode( const C_Str & str_r );
00750 
00751 
00757     std::string toLower( const std::string & s );
00759     inline std::string toLower( const char * s )
00760     { return( s ? toLower( std::string(s) ) : std::string() ); }
00761 
00765     std::string toUpper( const std::string & s );
00767     inline std::string toUpper( const char * s )
00768     { return( s ? toUpper( std::string(s) ) : std::string() ); }
00770 
00771 
00774     inline int compareCI( const C_Str & lhs, const C_Str & rhs )
00775     { return ::strcasecmp( lhs, rhs ); }
00777 
00781     inline bool contains( const C_Str & str_r, const C_Str & val_r )
00782     { return ::strstr( str_r, val_r ); }
00784     inline bool containsCI( const C_Str & str_r, const C_Str & val_r )
00785     { return ::strcasestr( str_r, val_r ); }
00787 
00789 
00794     enum Trim {
00795       NO_TRIM = 0x00,
00796       L_TRIM  = 0x01,
00797       R_TRIM  = 0x02,
00798       TRIM    = (L_TRIM|R_TRIM)
00799     };
00800 
00801     std::string trim( const std::string & s, const Trim trim_r = TRIM );
00802 
00803     inline std::string ltrim( const std::string & s )
00804     { return trim( s, L_TRIM ); }
00805 
00806     inline std::string rtrim( const std::string & s )
00807     { return trim( s, R_TRIM ); }
00809 
00810     std::string stripFirstWord( std::string & line, const bool ltrim_first );
00811 
00812     std::string stripLastWord( std::string & line, const bool rtrim_first );
00813 
00817     std::string getline( std::istream & str, bool trim = false );
00818 
00822     std::string getline( std::istream & str, const Trim trim_r );
00823 
00831     std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r = false );
00832 
00834 
00839     inline bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r )
00840     { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
00841 
00843     inline std::string stripPrefix( const C_Str & str_r, const C_Str & prefix_r )
00844     { return( hasPrefix( str_r, prefix_r ) ? str_r + prefix_r.size() : str_r.c_str() ); }
00845 
00847     inline bool hasSuffix( const C_Str & str_r, const C_Str & suffix_r )
00848     { return( str_r.size() >= suffix_r.size() && ::strncmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); }
00849 
00851     inline std::string stripSuffix( const C_Str & str_r, const C_Str & suffix_r )
00852     {
00853       if ( hasSuffix( str_r, suffix_r ) )
00854         return std::string( str_r, str_r.size() - suffix_r.size() );
00855       return str_r.c_str();
00856     }
00857 
00859     inline bool startsWith( const C_Str & str_r, const C_Str & prefix_r )
00860     { return hasPrefix( str_r, prefix_r ); }
00862     inline bool endsWith( const C_Str & str_r, const C_Str & prefix_r )
00863     { return hasSuffix( str_r, prefix_r ); }
00865 
00866   } // namespace str
00869 } // namespace zypp
00871 #endif // ZYPP_BASE_STRING_H