libzypp  12.16.5
String.h
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #ifndef ZYPP_BASE_STRING_H
13 #define ZYPP_BASE_STRING_H
14 
15 #include <cstring>
16 
17 #include <iosfwd>
18 #include <vector>
19 #include <string>
20 #include <sstream>
21 
22 #include "zypp/base/Easy.h"
23 #include "zypp/base/PtrTypes.h"
24 #include "zypp/base/Function.h"
25 
27 namespace zypp
28 {
29 
68  class C_Str
69  {
70  public:
72 
73  public:
74  C_Str() : _val( 0 ), _sze( 0 ) {}
75  C_Str( char * c_str_r ) : _val( c_str_r ), _sze( std::string::npos ) {}
76  C_Str( const char * c_str_r ) : _val( c_str_r ), _sze( std::string::npos ) {}
77  C_Str( const std::string & str_r ) : _val( str_r.c_str() ), _sze( str_r.size() ) {}
78 
79  public:
80  bool isNull() const { return !_val; }
81  bool empty() const { return !(_val && *_val); }
82  size_type size() const
83  {
84  if ( _sze == std::string::npos )
85  { _sze = _val ? ::strlen( _val ) : 0; }
86  return _sze;
87  };
88 
89  operator const char *() const { return c_str(); }
90  const char * c_str() const { return _val ? _val : ""; }
91 
92  private:
93  const char *const _val;
94  mutable size_type _sze;
95  };
96 
98  inline std::ostream & operator<<( std::ostream & str, const C_Str & obj )
99  { return str << obj.c_str(); }
100 
102 
105  namespace str
106  {
107 
109 
112  inline std::string asString( const std::string &t )
113  { return t; }
114 
115  inline std::string asString( const char * t )
116  { return t; }
117 
118  inline std::string asString( char * t )
119  { return t; }
120 
121  template<class _T>
122  inline std::string asString( const _T &t )
123  { return t.asString(); }
124 
125  template<class _T>
126  inline std::string asString( const intrusive_ptr<_T> &p )
127  { return p->asString(); }
128 
129  template<class _T>
130  inline std::string asString( const weak_ptr<_T> &p )
131  { return p->asString(); }
132 
133  template<>
134  inline std::string asString( const bool &t )
135  { return t ? "+" : "-"; }
136 
138 
139  std::string form( const char * format, ... )
140  __attribute__ ((format (printf, 1, 2)));
141 
143 
147  std::string strerror( int errno_r );
148 
150 
160  struct SafeBuf
161  {
162  char * _buf;
163  SafeBuf() : _buf( 0 ) {}
164  ~SafeBuf() { if ( _buf ) free( _buf ); }
165  std::string asString() const
166  { return _buf ? std::string(_buf) : std::string(); }
167  };
168 
170 
180  struct Str
181  {
182  template<class _Tp>
183  Str & operator<<( const _Tp & val )
184  { _str << val; return *this; }
185 
186  operator std::string() const
187  { return _str.str(); }
188 
189  std::ostringstream _str;
190  };
191 
193 
206  inline std::string numstring( char n, int w = 0 ) { return form( "%*hhd", w, n ); }
207  inline std::string numstring( unsigned char n, int w = 0 ) { return form( "%*hhu", w, n ); }
208  inline std::string numstring( short n, int w = 0 ) { return form( "%*hd", w, n ); }
209  inline std::string numstring( unsigned short n, int w = 0 ) { return form( "%*hu", w, n ); }
210  inline std::string numstring( int n, int w = 0 ) { return form( "%*d", w, n ); }
211  inline std::string numstring( unsigned n, int w = 0 ) { return form( "%*u", w, n ); }
212  inline std::string numstring( long n, int w = 0 ) { return form( "%*ld", w, n ); }
213  inline std::string numstring( unsigned long n, int w = 0 ) { return form( "%*lu", w, n ); }
214  inline std::string numstring( long long n, int w = 0 ) { return form( "%*lld", w, n ); }
215  inline std::string numstring( unsigned long long n, int w = 0 ) { return form( "%*llu", w, n ); }
216 
217  template<> inline std::string asString( const char & t ) { return numstring( t ); }
218  template<> inline std::string asString( const unsigned char & t ) { return numstring( t ); }
219  template<> inline std::string asString( const short & t ) { return numstring( t ); }
220  template<> inline std::string asString( const unsigned short & t ) { return numstring( t ); }
221  template<> inline std::string asString( const int & t ) { return numstring( t ); }
222  template<> inline std::string asString( const unsigned & t ) { return numstring( t ); }
223  template<> inline std::string asString( const long & t ) { return numstring( t ); }
224  template<> inline std::string asString( const unsigned long & t ) { return numstring( t ); }
225  template<> inline std::string asString( const long long & t ) { return numstring( t ); }
226  template<> inline std::string asString( const unsigned long long & t ) { return numstring( t ); }
228 
230 
241  inline std::string hexstring( char n, int w = 4 ) { return form( "%#0*hhx", w, n ); }
242  inline std::string hexstring( unsigned char n, int w = 4 ) { return form( "%#0*hhx", w, n ); }
243  inline std::string hexstring( short n, int w = 10 ){ return form( "%#0*hx", w, n ); }
244  inline std::string hexstring( unsigned short n, int w = 10 ){ return form( "%#0*hx", w, n ); }
245  inline std::string hexstring( int n, int w = 10 ){ return form( "%#0*x", w, n ); }
246  inline std::string hexstring( unsigned n, int w = 10 ){ return form( "%#0*x", w, n ); }
247  inline std::string hexstring( long n, int w = 10 ){ return form( "%#0*lx", w, n ); }
248  inline std::string hexstring( unsigned long n, int w = 10 ){ return form( "%#0*lx", w, n ); }
249  inline std::string hexstring( long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
250  inline std::string hexstring( unsigned long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
252 
254 
265  inline std::string octstring( char n, int w = 4 ) { return form( "%#0*hho", w, n ); }
266  inline std::string octstring( unsigned char n, int w = 4 ) { return form( "%#0*hho", w, n ); }
267  inline std::string octstring( short n, int w = 5 ) { return form( "%#0*ho", w, n ); }
268  inline std::string octstring( unsigned short n, int w = 5 ) { return form( "%#0*ho", w, n ); }
269  inline std::string octstring( int n, int w = 5 ) { return form( "%#0*o", w, n ); }
270  inline std::string octstring( unsigned n, int w = 5 ) { return form( "%#0*o", w, n ); }
271  inline std::string octstring( long n, int w = 5 ) { return form( "%#0*lo", w, n ); }
272  inline std::string octstring( unsigned long n, int w = 5 ) { return form( "%#0*lo", w, n ); }
273  inline std::string octstring( long long n, int w = 0 ) { return form( "%#0*llo", w, n ); }
274  inline std::string octstring( unsigned long long n, int w = 0 ) { return form( "%#0*llo", w, n ); }
276 
278 
287  template<typename _It>
288  _It strtonum( const C_Str & str );
289 
290  template<>
291  inline short strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
292  template<>
293  inline int strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
294  template<>
295  inline long strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
296  template<>
297  inline long long strtonum( const C_Str & str ) { return ::strtoll ( str, NULL, 0 ); }
298 
299  template<>
300  inline unsigned short strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
301  template<>
302  inline unsigned strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
303  template<>
304  inline unsigned long strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
305  template<>
306  inline unsigned long long strtonum( const C_Str & str ) { return ::strtoull( str, NULL, 0 ); }
307 
313  template<typename _It>
314  inline _It strtonum( const C_Str & str, _It & i )
315  { return i = strtonum<_It>( str ); }
317 
319 
323  bool strToTrue( const C_Str & str );
324 
326  bool strToFalse( const C_Str & str );
327 
332  inline bool strToBool( const C_Str & str, bool default_r )
333  { return( default_r ? strToFalse( str ) : strToTrue( str ) ); }
334 
339  inline bool strToBoolNodefault( const C_Str & str, bool & return_r )
340  {
341  if ( strToTrue( str ) ) return (return_r = true);
342  if ( !strToFalse( str ) ) return (return_r = false);
343  return return_r;
344  }
345 
347 
351  std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r );
352 
355  std::string gsubFun( const std::string & str_r, const std::string & from_r, function<std::string()> to_r );
356 
361  std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r );
362 
365  std::string & replaceAllFun( std::string & str_r, const std::string & from_r, function<std::string()> to_r );
366 
367 
369 
380  template<class _OutputIterator>
381  unsigned split( const C_Str & line_r,
382  _OutputIterator result_r,
383  const C_Str & sepchars_r = " \t" )
384  {
385  const char * beg = line_r;
386  const char * cur = beg;
387  // skip leading sepchars
388  while ( *cur && ::strchr( sepchars_r, *cur ) )
389  ++cur;
390  unsigned ret = 0;
391  for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
392  {
393  // skip non sepchars
394  while( *cur && !::strchr( sepchars_r, *cur ) )
395  ++cur;
396  // build string
397  *result_r = std::string( beg, cur-beg );
398  // skip sepchars
399  while ( *cur && ::strchr( sepchars_r, *cur ) )
400  ++cur;
401  }
402  return ret;
403  }
404 
432  template<class _OutputIterator>
433  unsigned splitEscaped( const C_Str & line_r,
434  _OutputIterator result_r,
435  const C_Str & sepchars_r = " \t",
436  bool withEmpty = false)
437  {
438  const char * beg = line_r;
439  const char * cur = beg;
440  unsigned ret = 0;
441 
442  // skip leading sepchars
443  while ( *cur && ::strchr( sepchars_r, *cur ) )
444  {
445  ++cur;
446  if (withEmpty)
447  {
448  *result_r = "";
449  ++ret;
450  }
451  }
452 
453  // there were only sepchars in the string
454  if (!*cur && withEmpty)
455  {
456  *result_r = "";
457  return ++ret;
458  }
459 
460  // after the leading sepchars
461  for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
462  {
463  if ( *cur == '"' || *cur == '\'' )
464  {
465  char closeChar = *cur;
466  ++cur;
467  bool cont = true;
468  while (cont)
469  {
470  while ( *cur && *cur != closeChar)
471  ++cur;
472  if ( *cur == '\0' )
473  {
474  return ret; //TODO parsing exception no closing quote
475  }
476  int escCount = 0;
477  const char * esc = cur-1;
478  while ( esc != beg && *esc == '\\' )
479  {
480  escCount++;
481  --esc;
482  }
483  cont = (escCount % 2 == 1); // find some non escaped escape char
484  cur++; //skip quote
485  }
486 
487  std::string s( beg+1, cur-beg-2 ); //without quotes
488  //transform escaped escape
489  replaceAll( s, "\\\\", "\\" );
490  //transform escaped quotes (only same as open
491  char tmpn[2] = { closeChar, 0 };
492  char tmpo[3] = { '\\', closeChar, 0 };
493  replaceAll( s, tmpo, tmpn );
494 
495  *result_r = s;
496  }
497  else
498  {
499  // skip non sepchars
500  while( *cur && !::strchr( sepchars_r, *cur ) )
501  {
502  //ignore char after backslash
503  if ( *cur == '\\' )
504  {
505  ++cur;
506  }
507  ++cur;
508  }
509  // build string
510  std::string s( beg, cur-beg );
511  //transform escaped escape
512  replaceAll( s, "\\\\", "\\" );
513 
514  const char *delimeter = sepchars_r;
515  while ( *delimeter )
516  {
517  std::string ds("\\");
518  const char tmp[2] = { *delimeter, '\0' };
519  std::string del(tmp);
520  ds+= del;
521  replaceAll( s, ds, del );
522  ++delimeter;
523  }
524 
525  *result_r = s;
526  }
527  // skip sepchars
528  if ( *cur && ::strchr( sepchars_r, *cur ) )
529  ++cur;
530  while ( *cur && ::strchr( sepchars_r, *cur ) )
531  {
532  ++cur;
533  if (withEmpty)
534  {
535  *result_r = "";
536  ++ret;
537  }
538  }
539  // the last was a separator => one more field
540  if ( !*cur && withEmpty && ::strchr( sepchars_r, *(cur-1) ) )
541  {
542  *result_r = "";
543  ++ret;
544  }
545  }
546  return ret;
547  }
548 
569  template<class _OutputIterator>
570  unsigned splitFields( const C_Str & line_r,
571  _OutputIterator result_r,
572  const C_Str & sepchars_r = ":" )
573  {
574  const char * beg = line_r;
575  const char * cur = beg;
576  unsigned ret = 0;
577  for ( beg = cur; *beg; beg = cur, ++result_r )
578  {
579  // skip non sepchars
580  while( *cur && !::strchr( sepchars_r, *cur ) )
581  ++cur;
582  // build string
583  *result_r = std::string( beg, cur-beg );
584  ++ret;
585  // skip sepchar
586  if ( *cur )
587  {
588  ++cur;
589  if ( ! *cur ) // ending with sepchar
590  {
591  *result_r = std::string(); // add final empty field
592  ++ret;
593  break;
594  }
595  }
596  }
597  return ret;
598  }
599 
606  template<class _OutputIterator>
607  unsigned splitFieldsEscaped( const C_Str & line_r,
608  _OutputIterator result_r,
609  const C_Str & sepchars_r = ":" )
610  {
611  return
612  splitEscaped( line_r, result_r, sepchars_r, true /* withEmpty */ );
613  }
614 
616 
618 
621  template <class _Iterator>
622  std::string join( _Iterator begin, _Iterator end,
623  const C_Str & sep_r = " " )
624  {
625  std::string res;
626  for ( _Iterator iter = begin; iter != end; ++ iter )
627  {
628  if ( iter != begin )
629  res += sep_r;
630  res += asString(*iter);
631  }
632  return res;
633  }
634 
636  template <class _Container>
637  std::string join( const _Container & cont_r,
638  const C_Str & sep_r = " " )
639  { return join( cont_r.begin(), cont_r.end(), sep_r ); }
640 
645  template <class _Iterator>
646  std::string joinEscaped( _Iterator begin, _Iterator end,
647  const char sep_r = ' ' )
648  {
649  std::vector<char> buf;
650  for ( _Iterator iter = begin; iter != end; ++ iter )
651  {
652  if ( iter != begin )
653  buf.push_back( sep_r );
654 
655  if ( iter->empty() )
656  {
657  // empty string goes ""
658  buf.push_back( '"' );
659  buf.push_back( '"' );
660  }
661  else
662  {
663  std::string toadd( asString(*iter) );
664  for_( ch, toadd.begin(), toadd.end() )
665  {
666  switch ( *ch )
667  {
668  case '"':
669  case '\'':
670  case '\\':
671  buf.push_back( '\\' );
672  buf.push_back( *ch );
673  break;
674  default:
675  if ( *ch == sep_r )
676  buf.push_back( '\\' );
677  buf.push_back( *ch );
678  }
679  }
680  }
681  }
682  return std::string( buf.begin(), buf.end() );
683  }
685 
686 
688 
696  std::string escape( const C_Str & str_r, const char c = ' ' );
697 
699  inline void appendEscaped( std::string & str_r, const C_Str & next_r, const char sep_r = ' ' )
700  {
701  if ( ! str_r.empty() )
702  str_r += sep_r;
703  if ( next_r.empty() )
704  str_r += "\"\"";
705  else
706  str_r += escape( next_r, sep_r );
707  }
708 
710 
712 
713 
714 
722  std::string hexencode( const C_Str & str_r );
724  std::string hexdecode( const C_Str & str_r );
726 
727 
733  std::string toLower( const std::string & s );
735  inline std::string toLower( const char * s )
736  { return( s ? toLower( std::string(s) ) : std::string() ); }
737 
741  std::string toUpper( const std::string & s );
743  inline std::string toUpper( const char * s )
744  { return( s ? toUpper( std::string(s) ) : std::string() ); }
746 
747 
750  inline int compareCI( const C_Str & lhs, const C_Str & rhs )
751  { return ::strcasecmp( lhs, rhs ); }
753 
757  inline bool contains( const C_Str & str_r, const C_Str & val_r )
758  { return ::strstr( str_r, val_r ); }
760  inline bool containsCI( const C_Str & str_r, const C_Str & val_r )
761  { return ::strcasestr( str_r, val_r ); }
763 
765 
770  enum Trim {
771  NO_TRIM = 0x00,
772  L_TRIM = 0x01,
773  R_TRIM = 0x02,
775  };
776 
777  std::string trim( const std::string & s, const Trim trim_r = TRIM );
778 
779  inline std::string ltrim( const std::string & s )
780  { return trim( s, L_TRIM ); }
781 
782  inline std::string rtrim( const std::string & s )
783  { return trim( s, R_TRIM ); }
785 
786  std::string stripFirstWord( std::string & line, const bool ltrim_first );
787 
788  std::string stripLastWord( std::string & line, const bool rtrim_first );
789 
793  std::string getline( std::istream & str, bool trim = false );
794 
798  std::string getline( std::istream & str, const Trim trim_r );
799 
807  std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r = false );
808 
810 
815  inline bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r )
816  { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
817 
819  inline std::string stripPrefix( const C_Str & str_r, const C_Str & prefix_r )
820  { return( hasPrefix( str_r, prefix_r ) ? str_r + prefix_r.size() : str_r.c_str() ); }
821 
823  inline bool hasSuffix( const C_Str & str_r, const C_Str & suffix_r )
824  { return( str_r.size() >= suffix_r.size() && ::strncmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); }
825 
827  inline std::string stripSuffix( const C_Str & str_r, const C_Str & suffix_r )
828  {
829  if ( hasSuffix( str_r, suffix_r ) )
830  return std::string( str_r, str_r.size() - suffix_r.size() );
831  return str_r.c_str();
832  }
834  inline std::string::size_type commonPrefix( const C_Str & lhs, const C_Str & rhs )
835  {
836  const char * lp = lhs.c_str();
837  const char * rp = rhs.c_str();
838  std::string::size_type ret = 0;
839  while ( *lp == *rp && *lp != '\0' )
840  { ++lp, ++rp, ++ret; }
841  return ret;
842  }
843 
845  inline bool startsWith( const C_Str & str_r, const C_Str & prefix_r )
846  { return hasPrefix( str_r, prefix_r ); }
848  inline bool endsWith( const C_Str & str_r, const C_Str & prefix_r )
849  { return hasSuffix( str_r, prefix_r ); }
851 
852  } // namespace str
855 } // namespace zypp
857 #endif // ZYPP_BASE_STRING_H