libzypp 8.13.6
|
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