00001
00002
00003
00004
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
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
00386 while( *cur && !::strchr( sepchars_r, *cur ) )
00387 ++cur;
00388
00389 *result_r = std::string( beg, cur-beg );
00390
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
00435 while ( *cur && ::strchr( sepchars_r, *cur ) )
00436 {
00437 ++cur;
00438 if (withEmpty)
00439 {
00440 *result_r = "";
00441 ++ret;
00442 }
00443 }
00444
00445
00446 if (!*cur && withEmpty)
00447 {
00448 *result_r = "";
00449 return ++ret;
00450 }
00451
00452
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;
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);
00476 cur++;
00477 }
00478
00479 std::string s( beg+1, cur-beg-2 );
00480
00481 replaceAll( s, "\\\\", "\\" );
00482
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
00492 while( *cur && !::strchr( sepchars_r, *cur ) )
00493 {
00494
00495 if ( *cur == '\\' )
00496 {
00497 ++cur;
00498 }
00499 ++cur;
00500 }
00501
00502 std::string s( beg, cur-beg );
00503
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
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
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
00572 while( *cur && !::strchr( sepchars_r, *cur ) )
00573 ++cur;
00574
00575 *result_r = std::string( beg, cur-beg );
00576 ++ret;
00577
00578 if ( *cur )
00579 {
00580 ++cur;
00581 if ( ! *cur )
00582 {
00583 *result_r = std::string();
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 );
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
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 }
00838 }
00840 #endif // ZYPP_BASE_STRING_H