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