libzypp  11.13.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  template<class _T>
119  inline std::string asString( const _T &t )
120  { return t.asString(); }
121 
122  template<class _T>
123  inline std::string asString( const intrusive_ptr<_T> &p )
124  { return p->asString(); }
125 
126  template<class _T>
127  inline std::string asString( const weak_ptr<_T> &p )
128  { return p->asString(); }
129 
130  template<>
131  inline std::string asString( const bool &t )
132  { return t ? "+" : "-"; }
133 
135 
136  std::string form( const char * format, ... )
137  __attribute__ ((format (printf, 1, 2)));
138 
140 
144  std::string strerror( int errno_r );
145 
147 
157  struct SafeBuf
158  {
159  char * _buf;
160  SafeBuf() : _buf( 0 ) {}
161  ~SafeBuf() { if ( _buf ) free( _buf ); }
162  std::string asString() const
163  { return _buf ? std::string(_buf) : std::string(); }
164  };
165 
167 
177  struct Str
178  {
179  template<class _Tp>
180  Str & operator<<( const _Tp & val )
181  { _str << val; return *this; }
182 
183  operator std::string() const
184  { return _str.str(); }
185 
186  std::ostringstream _str;
187  };
188 
190 
203  inline std::string numstring( char n, int w = 0 ) { return form( "%*hhd", w, n ); }
204  inline std::string numstring( unsigned char n, int w = 0 ) { return form( "%*hhu", w, n ); }
205  inline std::string numstring( short n, int w = 0 ) { return form( "%*hd", w, n ); }
206  inline std::string numstring( unsigned short n, int w = 0 ) { return form( "%*hu", w, n ); }
207  inline std::string numstring( int n, int w = 0 ) { return form( "%*d", w, n ); }
208  inline std::string numstring( unsigned n, int w = 0 ) { return form( "%*u", w, n ); }
209  inline std::string numstring( long n, int w = 0 ) { return form( "%*ld", w, n ); }
210  inline std::string numstring( unsigned long n, int w = 0 ) { return form( "%*lu", w, n ); }
211  inline std::string numstring( long long n, int w = 0 ) { return form( "%*lld", w, n ); }
212  inline std::string numstring( unsigned long long n, int w = 0 ) { return form( "%*llu", w, n ); }
213 
214  template<> inline std::string asString( const char & t ) { return numstring( t ); }
215  template<> inline std::string asString( const unsigned char & t ) { return numstring( t ); }
216  template<> inline std::string asString( const short & t ) { return numstring( t ); }
217  template<> inline std::string asString( const unsigned short & t ) { return numstring( t ); }
218  template<> inline std::string asString( const int & t ) { return numstring( t ); }
219  template<> inline std::string asString( const unsigned & t ) { return numstring( t ); }
220  template<> inline std::string asString( const long & t ) { return numstring( t ); }
221  template<> inline std::string asString( const unsigned long & t ) { return numstring( t ); }
222  template<> inline std::string asString( const long long & t ) { return numstring( t ); }
223  template<> inline std::string asString( const unsigned long long & t ) { return numstring( t ); }
225 
227 
238  inline std::string hexstring( char n, int w = 4 ) { return form( "%#0*hhx", w, n ); }
239  inline std::string hexstring( unsigned char n, int w = 4 ) { return form( "%#0*hhx", w, n ); }
240  inline std::string hexstring( short n, int w = 10 ){ return form( "%#0*hx", w, n ); }
241  inline std::string hexstring( unsigned short n, int w = 10 ){ return form( "%#0*hx", w, n ); }
242  inline std::string hexstring( int n, int w = 10 ){ return form( "%#0*x", w, n ); }
243  inline std::string hexstring( unsigned n, int w = 10 ){ return form( "%#0*x", w, n ); }
244  inline std::string hexstring( long n, int w = 10 ){ return form( "%#0*lx", w, n ); }
245  inline std::string hexstring( unsigned long n, int w = 10 ){ return form( "%#0*lx", w, n ); }
246  inline std::string hexstring( long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
247  inline std::string hexstring( unsigned long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
249 
251 
262  inline std::string octstring( char n, int w = 4 ) { return form( "%#0*hho", w, n ); }
263  inline std::string octstring( unsigned char n, int w = 4 ) { return form( "%#0*hho", w, n ); }
264  inline std::string octstring( short n, int w = 5 ) { return form( "%#0*ho", w, n ); }
265  inline std::string octstring( unsigned short n, int w = 5 ) { return form( "%#0*ho", w, n ); }
266  inline std::string octstring( int n, int w = 5 ) { return form( "%#0*o", w, n ); }
267  inline std::string octstring( unsigned n, int w = 5 ) { return form( "%#0*o", w, n ); }
268  inline std::string octstring( long n, int w = 5 ) { return form( "%#0*lo", w, n ); }
269  inline std::string octstring( unsigned long n, int w = 5 ) { return form( "%#0*lo", w, n ); }
270  inline std::string octstring( long long n, int w = 0 ) { return form( "%#0*llo", w, n ); }
271  inline std::string octstring( unsigned long long n, int w = 0 ) { return form( "%#0*llo", w, n ); }
273 
275 
284  template<typename _It>
285  _It strtonum( const C_Str & str );
286 
287  template<>
288  inline short strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
289  template<>
290  inline int strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
291  template<>
292  inline long strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
293  template<>
294  inline long long strtonum( const C_Str & str ) { return ::strtoll ( str, NULL, 0 ); }
295 
296  template<>
297  inline unsigned short strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
298  template<>
299  inline unsigned strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
300  template<>
301  inline unsigned long strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
302  template<>
303  inline unsigned long long strtonum( const C_Str & str ) { return ::strtoull( str, NULL, 0 ); }
304 
310  template<typename _It>
311  inline _It strtonum( const C_Str & str, _It & i )
312  { return i = strtonum<_It>( str ); }
314 
316 
320  bool strToTrue( const C_Str & str );
321 
323  bool strToFalse( const C_Str & str );
324 
329  inline bool strToBool( const C_Str & str, bool default_r )
330  { return( default_r ? strToFalse( str ) : strToTrue( str ) ); }
331 
336  inline bool strToBoolNodefault( const C_Str & str, bool & return_r )
337  {
338  if ( strToTrue( str ) ) return (return_r = true);
339  if ( !strToFalse( str ) ) return (return_r = false);
340  return return_r;
341  }
342 
344 
348  std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r );
349 
352  std::string gsubFun( const std::string & str_r, const std::string & from_r, function<std::string()> to_r );
353 
358  std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r );
359 
362  std::string & replaceAllFun( std::string & str_r, const std::string & from_r, function<std::string()> to_r );
363 
364 
366 
377  template<class _OutputIterator>
378  unsigned split( const C_Str & line_r,
379  _OutputIterator result_r,
380  const C_Str & sepchars_r = " \t" )
381  {
382  const char * beg = line_r;
383  const char * cur = beg;
384  // skip leading sepchars
385  while ( *cur && ::strchr( sepchars_r, *cur ) )
386  ++cur;
387  unsigned ret = 0;
388  for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
389  {
390  // skip non sepchars
391  while( *cur && !::strchr( sepchars_r, *cur ) )
392  ++cur;
393  // build string
394  *result_r = std::string( beg, cur-beg );
395  // skip sepchars
396  while ( *cur && ::strchr( sepchars_r, *cur ) )
397  ++cur;
398  }
399  return ret;
400  }
401 
429  template<class _OutputIterator>
430  unsigned splitEscaped( const C_Str & line_r,
431  _OutputIterator result_r,
432  const C_Str & sepchars_r = " \t",
433  bool withEmpty = false)
434  {
435  const char * beg = line_r;
436  const char * cur = beg;
437  unsigned ret = 0;
438 
439  // skip leading sepchars
440  while ( *cur && ::strchr( sepchars_r, *cur ) )
441  {
442  ++cur;
443  if (withEmpty)
444  {
445  *result_r = "";
446  ++ret;
447  }
448  }
449 
450  // there were only sepchars in the string
451  if (!*cur && withEmpty)
452  {
453  *result_r = "";
454  return ++ret;
455  }
456 
457  // after the leading sepchars
458  for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
459  {
460  if ( *cur == '"' || *cur == '\'' )
461  {
462  char closeChar = *cur;
463  ++cur;
464  bool cont = true;
465  while (cont)
466  {
467  while ( *cur && *cur != closeChar)
468  ++cur;
469  if ( *cur == '\0' )
470  {
471  return ret; //TODO parsing exception no closing quote
472  }
473  int escCount = 0;
474  const char * esc = cur-1;
475  while ( esc != beg && *esc == '\\' )
476  {
477  escCount++;
478  --esc;
479  }
480  cont = (escCount % 2 == 1); // find some non escaped escape char
481  cur++; //skip quote
482  }
483 
484  std::string s( beg+1, cur-beg-2 ); //without quotes
485  //transform escaped escape
486  replaceAll( s, "\\\\", "\\" );
487  //transform escaped quotes (only same as open
488  char tmpn[2] = { closeChar, 0 };
489  char tmpo[3] = { '\\', closeChar, 0 };
490  replaceAll( s, tmpo, tmpn );
491 
492  *result_r = s;
493  }
494  else
495  {
496  // skip non sepchars
497  while( *cur && !::strchr( sepchars_r, *cur ) )
498  {
499  //ignore char after backslash
500  if ( *cur == '\\' )
501  {
502  ++cur;
503  }
504  ++cur;
505  }
506  // build string
507  std::string s( beg, cur-beg );
508  //transform escaped escape
509  replaceAll( s, "\\\\", "\\" );
510 
511  const char *delimeter = sepchars_r;
512  while ( *delimeter )
513  {
514  std::string ds("\\");
515  const char tmp[2] = { *delimeter, '\0' };
516  std::string del(tmp);
517  ds+= del;
518  replaceAll( s, ds, del );
519  ++delimeter;
520  }
521 
522  *result_r = s;
523  }
524  // skip sepchars
525  if ( *cur && ::strchr( sepchars_r, *cur ) )
526  ++cur;
527  while ( *cur && ::strchr( sepchars_r, *cur ) )
528  {
529  ++cur;
530  if (withEmpty)
531  {
532  *result_r = "";
533  ++ret;
534  }
535  }
536  // the last was a separator => one more field
537  if ( !*cur && withEmpty && ::strchr( sepchars_r, *(cur-1) ) )
538  {
539  *result_r = "";
540  ++ret;
541  }
542  }
543  return ret;
544  }
545 
566  template<class _OutputIterator>
567  unsigned splitFields( const C_Str & line_r,
568  _OutputIterator result_r,
569  const C_Str & sepchars_r = ":" )
570  {
571  const char * beg = line_r;
572  const char * cur = beg;
573  unsigned ret = 0;
574  for ( beg = cur; *beg; beg = cur, ++result_r )
575  {
576  // skip non sepchars
577  while( *cur && !::strchr( sepchars_r, *cur ) )
578  ++cur;
579  // build string
580  *result_r = std::string( beg, cur-beg );
581  ++ret;
582  // skip sepchar
583  if ( *cur )
584  {
585  ++cur;
586  if ( ! *cur ) // ending with sepchar
587  {
588  *result_r = std::string(); // add final empty field
589  ++ret;
590  break;
591  }
592  }
593  }
594  return ret;
595  }
596 
603  template<class _OutputIterator>
604  unsigned splitFieldsEscaped( const C_Str & line_r,
605  _OutputIterator result_r,
606  const C_Str & sepchars_r = ":" )
607  {
608  return
609  splitEscaped( line_r, result_r, sepchars_r, true /* withEmpty */ );
610  }
611 
613 
615 
618  template <class _Iterator>
619  std::string join( _Iterator begin, _Iterator end,
620  const C_Str & sep_r = " " )
621  {
622  std::string res;
623  for ( _Iterator iter = begin; iter != end; ++ iter )
624  {
625  if ( iter != begin )
626  res += sep_r;
627  res += asString(*iter);
628  }
629  return res;
630  }
631 
633  template <class _Container>
634  std::string join( const _Container & cont_r,
635  const C_Str & sep_r = " " )
636  { return join( cont_r.begin(), cont_r.end(), sep_r ); }
637 
642  template <class _Iterator>
643  std::string joinEscaped( _Iterator begin, _Iterator end,
644  const char sep_r = ' ' )
645  {
646  std::vector<char> buf;
647  for ( _Iterator iter = begin; iter != end; ++ iter )
648  {
649  if ( iter != begin )
650  buf.push_back( sep_r );
651 
652  if ( iter->empty() )
653  {
654  // empty string goes ""
655  buf.push_back( '"' );
656  buf.push_back( '"' );
657  }
658  else
659  {
660  std::string toadd( asString(*iter) );
661  for_( ch, toadd.begin(), toadd.end() )
662  {
663  switch ( *ch )
664  {
665  case '"':
666  case '\'':
667  case '\\':
668  buf.push_back( '\\' );
669  buf.push_back( *ch );
670  break;
671  default:
672  if ( *ch == sep_r )
673  buf.push_back( '\\' );
674  buf.push_back( *ch );
675  }
676  }
677  }
678  }
679  return std::string( buf.begin(), buf.end() );
680  }
681 
682 
694  std::string escape( const C_Str & str_r, const char c = ' ' );
695 
697  inline void appendEscaped( std::string & str_r, const C_Str & next_r, const char sep_r = ' ' )
698  {
699  if ( ! str_r.empty() )
700  str_r += sep_r;
701  if ( next_r.empty() )
702  str_r += "\"\"";
703  else
704  str_r += escape( next_r, sep_r );
705  }
706 
708 
710 
711 
712 
720  std::string hexencode( const C_Str & str_r );
722  std::string hexdecode( const C_Str & str_r );
724 
725 
731  std::string toLower( const std::string & s );
733  inline std::string toLower( const char * s )
734  { return( s ? toLower( std::string(s) ) : std::string() ); }
735 
739  std::string toUpper( const std::string & s );
741  inline std::string toUpper( const char * s )
742  { return( s ? toUpper( std::string(s) ) : std::string() ); }
744 
745 
748  inline int compareCI( const C_Str & lhs, const C_Str & rhs )
749  { return ::strcasecmp( lhs, rhs ); }
751 
755  inline bool contains( const C_Str & str_r, const C_Str & val_r )
756  { return ::strstr( str_r, val_r ); }
758  inline bool containsCI( const C_Str & str_r, const C_Str & val_r )
759  { return ::strcasestr( str_r, val_r ); }
761 
763 
768  enum Trim {
769  NO_TRIM = 0x00,
770  L_TRIM = 0x01,
771  R_TRIM = 0x02,
773  };
774 
775  std::string trim( const std::string & s, const Trim trim_r = TRIM );
776 
777  inline std::string ltrim( const std::string & s )
778  { return trim( s, L_TRIM ); }
779 
780  inline std::string rtrim( const std::string & s )
781  { return trim( s, R_TRIM ); }
783 
784  std::string stripFirstWord( std::string & line, const bool ltrim_first );
785 
786  std::string stripLastWord( std::string & line, const bool rtrim_first );
787 
791  std::string getline( std::istream & str, bool trim = false );
792 
796  std::string getline( std::istream & str, const Trim trim_r );
797 
805  std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r = false );
806 
808 
813  inline bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r )
814  { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
815 
817  inline std::string stripPrefix( const C_Str & str_r, const C_Str & prefix_r )
818  { return( hasPrefix( str_r, prefix_r ) ? str_r + prefix_r.size() : str_r.c_str() ); }
819 
821  inline bool hasSuffix( const C_Str & str_r, const C_Str & suffix_r )
822  { return( str_r.size() >= suffix_r.size() && ::strncmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); }
823 
825  inline std::string stripSuffix( const C_Str & str_r, const C_Str & suffix_r )
826  {
827  if ( hasSuffix( str_r, suffix_r ) )
828  return std::string( str_r, str_r.size() - suffix_r.size() );
829  return str_r.c_str();
830  }
831 
833  inline bool startsWith( const C_Str & str_r, const C_Str & prefix_r )
834  { return hasPrefix( str_r, prefix_r ); }
836  inline bool endsWith( const C_Str & str_r, const C_Str & prefix_r )
837  { return hasSuffix( str_r, prefix_r ); }
839 
840  } // namespace str
843 } // namespace zypp
845 #endif // ZYPP_BASE_STRING_H