libcamgm
String.hpp
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | |
3 | _ _ _ _ __ _ |
4 | | | | | | \_/ | / \ | | |
5 | | | | | | |_| | / /\ \ | | |
6 | | |__ | | | | | | / ____ \ | |__ |
7 | |____||_| |_| |_|/ / \ \|____| |
8 | |
9 | core library |
10 | |
11 | (C) SUSE Linux Products GmbH |
12 \----------------------------------------------------------------------/
13 
14  File: std::string.hpp
15 
16  Author: Michael Andres
17 
18 /-*/
19 #ifndef CA_MGM_STRING_HPP
20 #define CA_MGM_STRING_HPP
21 
22 #include <cstring>
23 
24 #include <iosfwd>
25 #include <vector>
26 #include <string>
27 #include <iostream>
28 
29 #include <stdlib.h>
30 
31 //#include "zypp/base/Easy.h"
32 //#include "zypp/base/PtrTypes.h"
33 #ifndef __GXX_EXPERIMENTAL_CXX0X__
34 #define for_(IT,BEG,END) for ( typeof(BEG) IT = BEG, _for_end = END; IT != _for_end; ++IT )
35 #else
36 #define for_(IT,BEG,END) for ( auto IT = BEG, _for_end = END; IT != _for_end; ++IT )
37 #endif
38 
40 namespace ca_mgm
41 {
42 
81  class C_Str
82  {
83  public:
84  typedef std::string::size_type size_type;
85 
86  public:
87  C_Str() : _val( 0 ), _sze( 0 ) {}
88  C_Str( char * c_str_r ) : _val( c_str_r ), _sze( std::string::npos ) {}
89  C_Str( const char * c_str_r ) : _val( c_str_r ), _sze( std::string::npos ) {}
90  C_Str( const std::string & str_r ) : _val( str_r.c_str() ), _sze( str_r.size() ) {}
91 
92  public:
93  bool isNull() const { return !_val; }
94  bool empty() const { return !(_val && *_val); }
95  size_type size() const
96  {
97  if ( _sze == std::string::npos )
98  { _sze = _val ? ::strlen( _val ) : 0; }
99  return _sze;
100  };
101 
102  operator const char *() const { return c_str(); }
103  const char * c_str() const { return _val ? _val : ""; }
104 
105  private:
106  const char *const _val;
107  mutable size_type _sze;
108  };
109 
111  inline std::ostream & operator<<( std::ostream & str, const C_Str & obj )
112  { return str << obj.c_str(); }
113 
115 
118  namespace str
119  {
120 
122 
125  inline std::string toString( bool b) { return (b?"true":"false"); }
126 
127  template<class _T>
128  inline std::string asString( const _T &t )
129  { return t.asString(); }
130 
131  /*
132  template<class _T>
133  inline std::string asString( const intrusive_ptr<_T> &p )
134  { return p->asString(); }
135 
136  template<class _T>
137  inline std::string asString( const weak_ptr<_T> &p )
138  { return p->asString(); }
139  */
140  template<>
141  inline std::string asString( const std::string &t )
142  { return t; }
143 
145 
146  std::string form( const char * format, ... )
147  __attribute__ ((format (printf, 1, 2)));
148 
150 
154  std::string strerror( int errno_r );
155 
157 
167  struct SafeBuf
168  {
169  char * _buf;
170  SafeBuf() : _buf( 0 ) {}
171  ~SafeBuf() { if ( _buf ) free( _buf ); }
172  std::string asString() const
173  { return _buf ? std::string(_buf) : std::string(); }
174  };
175 
177 
190  inline std::string numstring( char n, int w = 0 ) { return form( "%*hhd", w, n ); }
191  inline std::string numstring( unsigned char n, int w = 0 ) { return form( "%*hhu", w, n ); }
192  inline std::string numstring( short n, int w = 0 ) { return form( "%*hd", w, n ); }
193  inline std::string numstring( unsigned short n, int w = 0 ) { return form( "%*hu", w, n ); }
194  inline std::string numstring( int n, int w = 0 ) { return form( "%*d", w, n ); }
195  inline std::string numstring( unsigned n, int w = 0 ) { return form( "%*u", w, n ); }
196  inline std::string numstring( long n, int w = 0 ) { return form( "%*ld", w, n ); }
197  inline std::string numstring( unsigned long n, int w = 0 ) { return form( "%*lu", w, n ); }
198  inline std::string numstring( long long n, int w = 0 ) { return form( "%*lld", w, n ); }
199  inline std::string numstring( unsigned long long n, int w = 0 ) { return form( "%*llu", w, n ); }
201 
203 
214  inline std::string hexstring( char n, int w = 4 ) { return form( "%#0*hhx", w, n ); }
215  inline std::string hexstring( unsigned char n, int w = 4 ) { return form( "%#0*hhx", w, n ); }
216  inline std::string hexstring( short n, int w = 10 ){ return form( "%#0*hx", w, n ); }
217  inline std::string hexstring( unsigned short n, int w = 10 ){ return form( "%#0*hx", w, n ); }
218  inline std::string hexstring( int n, int w = 10 ){ return form( "%#0*x", w, n ); }
219  inline std::string hexstring( unsigned n, int w = 10 ){ return form( "%#0*x", w, n ); }
220  inline std::string hexstring( long n, int w = 10 ){ return form( "%#0*lx", w, n ); }
221  inline std::string hexstring( unsigned long n, int w = 10 ){ return form( "%#0*lx", w, n ); }
222  inline std::string hexstring( long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
223  inline std::string hexstring( unsigned long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
225 
227 
238  inline std::string octstring( char n, int w = 4 ) { return form( "%#0*hho", w, n ); }
239  inline std::string octstring( unsigned char n, int w = 4 ) { return form( "%#0*hho", w, n ); }
240  inline std::string octstring( short n, int w = 5 ) { return form( "%#0*ho", w, n ); }
241  inline std::string octstring( unsigned short n, int w = 5 ) { return form( "%#0*ho", w, n ); }
242  inline std::string octstring( int n, int w = 5 ) { return form( "%#0*o", w, n ); }
243  inline std::string octstring( unsigned n, int w = 5 ) { return form( "%#0*o", w, n ); }
244  inline std::string octstring( long n, int w = 5 ) { return form( "%#0*lo", w, n ); }
245  inline std::string octstring( unsigned long n, int w = 5 ) { return form( "%#0*lo", w, n ); }
246  inline std::string octstring( long long n, int w = 0 ) { return form( "%#0*llo", w, n ); }
247  inline std::string octstring( unsigned long long n, int w = 0 ) { return form( "%#0*llo", w, n ); }
249 
251 
260  template<typename _It>
261  _It strtonum( const C_Str & str );
262 
263  template<>
264  inline short strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
265  template<>
266  inline int strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
267  template<>
268  inline long strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
269  template<>
270  inline long long strtonum( const C_Str & str ) { return ::strtoll ( str, NULL, 0 ); }
271 
272  template<>
273  inline unsigned short strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
274  template<>
275  inline unsigned strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
276  template<>
277  inline unsigned long strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
278  template<>
279  inline unsigned long long strtonum( const C_Str & str ) { return ::strtoull( str, NULL, 0 ); }
280 
286  template<typename _It>
287  inline _It strtonum( const C_Str & str, _It & i )
288  { return i = strtonum<_It>( str ); }
290 
292 
296  bool strToTrue( const C_Str & str );
297 
299  bool strToFalse( const C_Str & str );
300 
305  inline bool strToBool( const C_Str & str, bool default_r )
306  { return( default_r ? strToFalse( str ) : strToTrue( str ) ); }
307 
312  inline bool strToBoolNodefault( const C_Str & str, bool & return_r )
313  {
314  if ( strToTrue( str ) ) return (return_r = true);
315  if ( !strToFalse( str ) ) return (return_r = false);
316  return return_r;
317  }
318 
320 
326  std::string gsub( const std::string& sData, const std::string& sFrom, const std::string& sTo);
327 
335  std::string& replaceAll( std::string & str, const std::string & from, const std::string & to);
336 
338 
349  template<class _OutputIterator>
350  unsigned split( const C_Str & line_r,
351  _OutputIterator result_r,
352  const C_Str & sepchars_r = " \t" )
353  {
354  const char * beg = line_r;
355  const char * cur = beg;
356  // skip leading sepchars
357  while ( *cur && ::strchr( sepchars_r, *cur ) )
358  ++cur;
359  unsigned ret = 0;
360  for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
361  {
362  // skip non sepchars
363  while( *cur && !::strchr( sepchars_r, *cur ) )
364  ++cur;
365  // build string
366  *result_r = std::string( beg, cur-beg );
367  // skip sepchars
368  while ( *cur && ::strchr( sepchars_r, *cur ) )
369  ++cur;
370  }
371  return ret;
372  }
373 
401  template<class _OutputIterator>
402  unsigned splitEscaped( const C_Str & line_r,
403  _OutputIterator result_r,
404  const C_Str & sepchars_r = " \t",
405  bool withEmpty = false)
406  {
407  const char * beg = line_r;
408  const char * cur = beg;
409  unsigned ret = 0;
410 
411  // skip leading sepchars
412  while ( *cur && ::strchr( sepchars_r, *cur ) )
413  {
414  ++cur;
415  if (withEmpty)
416  {
417  *result_r = "";
418  ++ret;
419  }
420  }
421 
422  // there were only sepchars in the string
423  if (!*cur && withEmpty)
424  {
425  *result_r = "";
426  return ++ret;
427  }
428 
429  // after the leading sepchars
430  for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
431  {
432  if ( *cur == '"' || *cur == '\'' )
433  {
434  char closeChar = *cur;
435  ++cur;
436  bool cont = true;
437  while (cont)
438  {
439  while ( *cur && *cur != closeChar)
440  ++cur;
441  if ( *cur == '\0' )
442  {
443  return ret; //TODO parsing exception no closing quote
444  }
445  int escCount = 0;
446  const char * esc = cur-1;
447  while ( esc != beg && *esc == '\\' )
448  {
449  escCount++;
450  --esc;
451  }
452  cont = (escCount % 2 == 1); // find some non escaped escape char
453  cur++; //skip quote
454  }
455 
456  std::string s( beg+1, cur-beg-2 ); //without quotes
457  //transform escaped escape
458  replaceAll( s, "\\\\", "\\" );
459  //transform escaped quotes (only same as open
460  char tmpn[2] = { closeChar, 0 };
461  char tmpo[3] = { '\\', closeChar, 0 };
462  replaceAll( s, tmpo, tmpn );
463 
464  *result_r = s;
465  }
466  else
467  {
468  // skip non sepchars
469  while( *cur && !::strchr( sepchars_r, *cur ) )
470  {
471  //ignore char after backslash
472  if ( *cur == '\\' )
473  {
474  ++cur;
475  }
476  ++cur;
477  }
478  // build string
479  std::string s( beg, cur-beg );
480  //transform escaped escape
481  replaceAll( s, "\\\\", "\\" );
482 
483  const char *delimeter = sepchars_r;
484  while ( *delimeter )
485  {
486  std::string ds("\\");
487  const char tmp[2] = { *delimeter, '\0' };
488  std::string del(tmp);
489  ds+= del;
490  replaceAll( s, ds, del );
491  ++delimeter;
492  }
493 
494  *result_r = s;
495  }
496  // skip sepchars
497  if ( *cur && ::strchr( sepchars_r, *cur ) )
498  ++cur;
499  while ( *cur && ::strchr( sepchars_r, *cur ) )
500  {
501  ++cur;
502  if (withEmpty)
503  {
504  *result_r = "";
505  ++ret;
506  }
507  }
508  // the last was a separator => one more field
509  if ( !*cur && withEmpty && ::strchr( sepchars_r, *(cur-1) ) )
510  {
511  *result_r = "";
512  ++ret;
513  }
514  }
515  return ret;
516  }
517 
538  template<class _OutputIterator>
539  unsigned splitFields( const C_Str & line_r,
540  _OutputIterator result_r,
541  const C_Str & sepchars_r = ":" )
542  {
543  const char * beg = line_r;
544  const char * cur = beg;
545  unsigned ret = 0;
546  for ( beg = cur; *beg; beg = cur, ++result_r )
547  {
548  // skip non sepchars
549  while( *cur && !::strchr( sepchars_r, *cur ) )
550  ++cur;
551  // build string
552  *result_r = std::string( beg, cur-beg );
553  ++ret;
554  // skip sepchar
555  if ( *cur )
556  {
557  ++cur;
558  if ( ! *cur ) // ending with sepchar
559  {
560  *result_r = std::string(); // add final empty field
561  ++ret;
562  break;
563  }
564  }
565  }
566  return ret;
567  }
568 
575  template<class _OutputIterator>
576  unsigned splitFieldsEscaped( const C_Str & line_r,
577  _OutputIterator result_r,
578  const C_Str & sepchars_r = ":" )
579  {
580  return
581  splitEscaped( line_r, result_r, sepchars_r, true /* withEmpty */ );
582  }
583 
585 
587 
590  template <class _Iterator>
591  std::string join( _Iterator begin, _Iterator end,
592  const C_Str & sep_r = " " )
593  {
594  std::string res;
595  for ( _Iterator iter = begin; iter != end; ++ iter )
596  {
597  if ( iter != begin )
598  res += sep_r;
599  res += asString(*iter);
600  }
601  return res;
602  }
603 
605  template <class _Container>
606  std::string join( const _Container & cont_r,
607  const C_Str & sep_r = " " )
608  { return join( cont_r.begin(), cont_r.end(), sep_r ); }
609 
614  template <class _Iterator>
615  std::string joinEscaped( _Iterator begin, _Iterator end,
616  const char sep_r = ' ' )
617  {
618  std::vector<char> buf;
619  for ( _Iterator iter = begin; iter != end; ++ iter )
620  {
621  if ( iter != begin )
622  buf.push_back( sep_r );
623 
624  if ( iter->empty() )
625  {
626  // empty string goes ""
627  buf.push_back( '"' );
628  buf.push_back( '"' );
629  }
630  else
631  {
632  std::string toadd( asString(*iter) );
633  for_( ch, toadd.begin(), toadd.end() )
634  {
635  switch ( *ch )
636  {
637  case '"':
638  case '\'':
639  case '\\':
640  buf.push_back( '\\' );
641  buf.push_back( *ch );
642  break;
643  default:
644  if ( *ch == sep_r )
645  buf.push_back( '\\' );
646  buf.push_back( *ch );
647  }
648  }
649  }
650  }
651  return std::string( buf.begin(), buf.end() );
652  }
653 
654 
666  std::string escape(const std::string & str_r, const char c = ' ' );
667 
669 
671 
681  std::string hexencode( const C_Str & str_r );
683  std::string hexdecode( const C_Str & str_r );
685 
692  std::string toLower( const std::string & s );
694  inline std::string toLower( const char * s )
695  { return( s ? toLower( std::string(s) ) : std::string() ); }
696 
700  std::string toUpper( const std::string & s );
702  inline std::string toUpper( const char * s )
703  { return( s ? toUpper( std::string(s) ) : std::string() ); }
705 
706 
709  inline int compareCI( const C_Str & lhs, const C_Str & rhs )
710  {
711  if ( lhs == rhs )
712  return 0;
713  return ::strcasecmp( lhs, rhs );
714  }
716 
720  inline bool contains( const C_Str & str_r, const C_Str & val_r )
721  { return ::strstr( str_r, val_r ); }
723  inline bool containsCI( const C_Str & str_r, const C_Str & val_r )
724  { return ::strcasestr( str_r, val_r ); }
726 
728 
733  enum Trim {
734  NO_TRIM = 0x00,
735  L_TRIM = 0x01,
736  R_TRIM = 0x02,
738  };
739 
740  std::string trim( const std::string & s, const Trim trim_r = TRIM );
741 
742  inline std::string ltrim( const std::string & s )
743  { return trim( s, L_TRIM ); }
744 
745  inline std::string rtrim( const std::string & s )
746  { return trim( s, R_TRIM ); }
748 
749  std::string stripFirstWord( std::string & line, const bool ltrim_first );
750 
751  std::string stripLastWord( std::string & line, const bool rtrim_first );
752 
753  std::string getline( std::istream & str, bool trim = false );
754 
755  std::string getline( std::istream & str, const Trim trim_r );
756 
758 
763  inline bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r )
764  { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
765 
766  inline bool hasPrefixCI( const C_Str & str_r, const C_Str & prefix_r )
767  { return( ::strncasecmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
768 
770  inline std::string stripPrefix( const C_Str & str_r, const C_Str & prefix_r )
771  { return( hasPrefix( str_r, prefix_r ) ? str_r + prefix_r.size() : str_r.c_str() ); }
772 
774  inline bool hasSuffix( const C_Str & str_r, const C_Str & suffix_r )
775  { return( str_r.size() >= suffix_r.size() && ::strncmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); }
776 
777  inline bool hasSuffixCI( const C_Str & str_r, const C_Str & suffix_r )
778  { return( str_r.size() >= suffix_r.size() && ::strncasecmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); }
779 
781  inline std::string stripSuffix( const C_Str & str_r, const C_Str & suffix_r )
782  {
783  if ( hasSuffix( str_r, suffix_r ) )
784  return std::string( str_r, str_r.size() - suffix_r.size() );
785  return str_r.c_str();
786  }
787 
789  inline bool startsWith( const C_Str & str_r, const C_Str & prefix_r )
790  { return hasPrefix( str_r, prefix_r ); }
792  inline bool startsWithCI( const C_Str & str_r, const C_Str & prefix_r )
793  { return hasPrefixCI( str_r, prefix_r ); }
794 
796  inline bool endsWith( const C_Str & str_r, const C_Str & prefix_r )
797  { return hasSuffix( str_r, prefix_r ); }
798 
799  inline bool endsWithCI( const C_Str & str_r, const C_Str & prefix_r )
800  { return hasSuffixCI( str_r, prefix_r ); }
802 
804  } // namespace str
807 } // namespace ca_mgm
809 #endif // CA_MGM_STRING_HPP
C_Str(const char *c_str_r)
Definition: String.hpp:89
_It strtonum(const C_Str &str)
Definition: String.hpp:264
SafeBuf()
Definition: String.hpp:170
size_type size() const
Definition: String.hpp:95
std::string hexstring(char n, int w=4)
Definition: String.hpp:214
std::string strerror(int errno_r)
std::string trim(const std::string &s, const Trim trim_r=TRIM)
Definition: String.hpp:167
std::string stripPrefix(const C_Str &str_r, const C_Str &prefix_r)
Definition: String.hpp:770
const char * c_str() const
Definition: String.hpp:103
std::string toLower(const std::string &s)
size_type _sze
Definition: String.hpp:107
std::string toString(bool b)
Definition: String.hpp:125
C_Str()
Definition: String.hpp:87
C_Str(char *c_str_r)
Definition: String.hpp:88
std::string escape(const std::string &str_r, const char c= ' ')
C_Str(const std::string &str_r)
Definition: String.hpp:90
bool strToBoolNodefault(const C_Str &str, bool &return_r)
Definition: String.hpp:312
std::string & replaceAll(std::string &str, const std::string &from, const std::string &to)
Looks for text in string and replaces it in place.
int compareCI(const C_Str &lhs, const C_Str &rhs)
Definition: String.hpp:709
std::string stripFirstWord(std::string &line, const bool ltrim_first)
std::string ltrim(const std::string &s)
Definition: String.hpp:742
bool strToBool(const C_Str &str, bool default_r)
Definition: String.hpp:305
std::string octstring(char n, int w=4)
Definition: String.hpp:238
bool strToFalse(const C_Str &str)
bool isNull() const
Definition: String.hpp:93
bool endsWithCI(const C_Str &str_r, const C_Str &prefix_r)
Definition: String.hpp:799
std::string hexdecode(const C_Str &str_r)
unsigned split(const C_Str &line_r, _OutputIterator result_r, const C_Str &sepchars_r=" \t")
Definition: String.hpp:350
std::string join(_Iterator begin, _Iterator end, const C_Str &sep_r=" ")
Definition: String.hpp:591
Definition: String.hpp:735
std::string toUpper(const std::string &s)
Definition: String.hpp:737
std::ostream & operator<<(std::ostream &str, const C_Str &obj)
Definition: String.hpp:111
bool containsCI(const C_Str &str_r, const C_Str &val_r)
Definition: String.hpp:723
Definition: String.hpp:736
unsigned splitFieldsEscaped(const C_Str &line_r, _OutputIterator result_r, const C_Str &sepchars_r=":")
Definition: String.hpp:576
Trim
Definition: String.hpp:733
std::string stripLastWord(std::string &line, const bool rtrim_first)
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
Definition: String.hpp:789
const char *const _val
Definition: String.hpp:106
bool endsWith(const C_Str &str_r, const C_Str &prefix_r)
Definition: String.hpp:796
bool strToTrue(const C_Str &str)
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Definition: String.hpp:763
std::string hexencode(const C_Str &str_r)
~SafeBuf()
Definition: String.hpp:171
std::string rtrim(const std::string &s)
Definition: String.hpp:745
std::string gsub(const std::string &sData, const std::string &sFrom, const std::string &sTo)
Looks for text in a string and replaces it.
#define for_(IT, BEG, END)
Definition: String.hpp:34
std::string joinEscaped(_Iterator begin, _Iterator end, const char sep_r= ' ')
Definition: String.hpp:615
std::string::size_type size_type
Definition: String.hpp:84
bool hasSuffix(const C_Str &str_r, const C_Str &suffix_r)
Definition: String.hpp:774
std::string getline(std::istream &str, bool trim=false)
bool startsWithCI(const C_Str &str_r, const C_Str &prefix_r)
Definition: String.hpp:792
std::string numstring(char n, int w=0)
Definition: String.hpp:190
bool contains(const C_Str &str_r, const C_Str &val_r)
Definition: String.hpp:720
bool empty() const
Definition: String.hpp:94
Definition: String.hpp:734
std::string asString(const _T &t)
Definition: String.hpp:128
std::string asString() const
Definition: String.hpp:172
bool hasSuffixCI(const C_Str &str_r, const C_Str &suffix_r)
Definition: String.hpp:777
unsigned splitFields(const C_Str &line_r, _OutputIterator result_r, const C_Str &sepchars_r=":")
Definition: String.hpp:539
bool hasPrefixCI(const C_Str &str_r, const C_Str &prefix_r)
Definition: String.hpp:766
std::string stripSuffix(const C_Str &str_r, const C_Str &suffix_r)
Definition: String.hpp:781
char * _buf
Definition: String.hpp:169
std::string form(const char *format,...)
Definition: String.hpp:81
unsigned splitEscaped(const C_Str &line_r, _OutputIterator result_r, const C_Str &sepchars_r=" \t", bool withEmpty=false)
Definition: String.hpp:402