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