libzypp  15.28.6
String.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <cstdio>
13 #include <cstdarg>
14 
15 #include <iostream>
16 
17 #include "zypp/base/String.h"
18 #include "zypp/base/LogTools.h"
19 
20 #include "zypp/TriBool.h"
21 
22 using std::string;
23 
25 namespace zypp
26 {
27  namespace str
29  {
30 
31  /******************************************************************
32  **
33  ** FUNCTION NAME : form
34  ** FUNCTION TYPE : std::string
35  */
36  std::string form( const char * format, ... )
37  {
38  SafeBuf safe;
39 
40  va_list ap;
41  va_start( ap, format );
42  vasprintf( &safe._buf, format, ap );
43  va_end( ap );
44 
45  return safe.asString();
46  }
47 
48  /******************************************************************
49  **
50  ** FUNCTION NAME : strerror
51  ** FUNCTION TYPE : std::string
52  */
53  std::string strerror( int errno_r )
54  {
55  return form( "(%d)%s", errno_r, ::strerror( errno_r ) );
56  }
57 
58  /******************************************************************
59  **
60  ** FUNCTION NAME : strToTrue
61  ** FUNCTION TYPE : bool
62  */
63  bool strToTrue( const C_Str & str )
64  {
65  std::string t( toLower( str ) );
66  return( t == "1"
67  || t == "yes"
68  || t == "true"
69  || t == "on"
70  || t == "+"
71  || strtonum<long long>( str )
72  );
73  }
74 
75  /******************************************************************
76  **
77  ** FUNCTION NAME : strToFalse
78  ** FUNCTION TYPE : bool
79  */
80  bool strToFalse( const C_Str & str )
81  {
82  std::string t( toLower( str ) );
83  return ! ( t == "0"
84  || t == "no"
85  || t == "false"
86  || t == "off"
87  || t == "-"
88  );
89  }
90 
91  TriBool strToTriBool( const C_Str & str ) // from TriBool.h
92  {
93  if ( strToTrue( str ) ) return true;
94  if ( !strToFalse( str ) ) return false;
95  return indeterminate;
96  }
97 
99  // Hexencode
101  namespace {
103  inline bool heIsAlNum( char ch )
104  {
105  return ( ( 'a' <= ch && ch <= 'z' )
106  ||( 'A' <= ch && ch <= 'Z' )
107  ||( '0' <= ch && ch <= '9' ) );
108  }
110  inline int heDecodeCh( char ch )
111  {
112  if ( '0' <= ch && ch <= '9' )
113  return( ch - '0' );
114  if ( 'A' <= ch && ch <= 'F' )
115  return( ch - 'A' + 10 );
116  if ( 'a' <= ch && ch <= 'f' )
117  return( ch - 'a' + 10 );
118  return -1;
119  }
120  }
121 
122  std::string hexencode( const C_Str & str_r )
123  {
124  static const char *const hdig = "0123456789ABCDEF";
125  std::string res;
126  res.reserve( str_r.size() );
127  for ( const char * it = str_r.c_str(); *it; ++it )
128  {
129  if ( heIsAlNum( *it ) )
130  {
131  res += *it;
132  }
133  else
134  {
135  res += '%';
136  res += hdig[(unsigned char)(*it)/16];
137  res += hdig[(unsigned char)(*it)%16];
138  }
139  }
140  return res;
141  }
142 
143  std::string hexdecode( const C_Str & str_r )
144  {
145  std::string res;
146  res.reserve( str_r.size() );
147  for_( it, str_r.c_str(), str_r.c_str()+str_r.size() )
148  {
149  if ( *it == '%' )
150  {
151  int d1 = heDecodeCh( *(it+1) );
152  if ( d1 != -1 )
153  {
154  int d2 = heDecodeCh( *(it+2) );
155  if ( d2 != -1 )
156  {
157  res += (d1<<4)|d2;
158  it += 2;
159  continue;
160  }
161  }
162  }
163  // verbatim if no %XX:
164  res += *it;
165  }
166  return res;
167  }
169 
170  /******************************************************************
171  **
172  ** FUNCTION NAME : toLower
173  ** FUNCTION TYPE : std::string
174  */
175  std::string toLower( const std::string & s )
176  { return toLower( std::string(s) ); }
177 
178  std::string toLower( std::string && s )
179  {
180  std::string ret( std::move(s) );
181 
182  if ( ret.empty() )
183  return ret;
184 
185  for ( std::string::size_type i = 0; i < ret.length(); ++i )
186  {
187  if ( isupper( ret[i] ) )
188  ret[i] = static_cast<char>(tolower( ret[i] ));
189  }
190  return ret;
191  }
192 
193  /******************************************************************
194  **
195  ** FUNCTION NAME : toUpper
196  ** FUNCTION TYPE : std::string
197  */
198  std::string toUpper( const std::string & s )
199  { return toUpper( std::string(s) ); }
200 
201  std::string toUpper( std::string && s )
202  {
203  std::string ret( std::move(s) );
204 
205  if ( ret.empty() )
206  return ret;
207 
208  for ( std::string::size_type i = 0; i < ret.length(); ++i )
209  {
210  if ( islower( ret[i] ) )
211  ret[i] = static_cast<char>(toupper( ret[i] ));
212  }
213  return ret;
214  }
215 
216  /******************************************************************
217  **
218  ** FUNCTION NAME : trim
219  ** FUNCTION TYPE : std::string
220  */
221  std::string trim( const std::string & s, const Trim trim_r )
222  { return trim( std::string(s), trim_r ); }
223 
224  std::string trim( std::string && s, const Trim trim_r )
225  {
226  std::string ret( std::move(s) );
227 
228  if ( ret.empty() || trim_r == NO_TRIM )
229  return ret;
230 
231  if ( trim_r & L_TRIM )
232  {
233  std::string::size_type p = ret.find_first_not_of( " \t\n" );
234  if ( p == std::string::npos )
235  {
236  ret.clear();
237  return ret;
238  }
239  ret.erase( 0, p );
240  }
241 
242  if ( trim_r & R_TRIM )
243  {
244  std::string::size_type p = ret.find_last_not_of( " \t\n" );
245  if ( p == std::string::npos )
246  {
247  ret.clear();
248  return ret;
249  }
250  ret = ret.erase( p+1 );
251  }
252 
253  return ret;
254  }
255 
256  /******************************************************************
257  **
258  ** FUNCTION NAME : stripFirstWord
259  ** FUNCTION TYPE : std::string
260  */
261  std::string stripFirstWord( std::string & line, const bool ltrim_first )
262  {
263  if ( ltrim_first )
264  line = ltrim( line );
265 
266  if ( line.empty() )
267  return line;
268 
269  std::string ret;
270  std::string::size_type p = line.find_first_of( " \t" );
271 
272  if ( p == std::string::npos ) {
273  // no ws on line
274  ret = line;
275  line.erase();
276  } else if ( p == 0 ) {
277  // starts with ws
278  // ret remains empty
279  line = ltrim( line );
280  }
281  else {
282  // strip word and ltim line
283  ret = line.substr( 0, p );
284  line = ltrim( line.erase( 0, p ) );
285  }
286  return ret;
287  }
288 
289  /******************************************************************
290  **
291  ** FUNCTION NAME : stripLastWord
292  ** FUNCTION TYPE : std::string
293  */
294  std::string stripLastWord( std::string & line, const bool rtrim_first )
295  {
296  if ( rtrim_first )
297  line = rtrim( line );
298 
299  if ( line.empty() )
300  return line;
301 
302  std::string ret;
303  std::string::size_type p = line.find_last_of( " \t" );
304 
305  if ( p == std::string::npos ) {
306  // no ws on line
307  ret = line;
308  line.erase();
309  } else if ( p == line.size()-1 ) {
310  // ends with ws
311  // ret remains empty
312  line = rtrim( line );
313  }
314  else {
315  // strip word and rtim line
316  ret = line.substr( p+1 );
317  line = rtrim( line.erase( p ) );
318  }
319  return ret;
320  }
321 
322  std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r )
323  {
324  std::string ret( str_r );
325  return replaceAll( ret, from_r, to_r );
326  }
327 
328  std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r )
329  {
330  if ( ! from_r.empty() )
331  {
332  std::string::size_type pos = 0;
333  while ( (pos = str_r.find( from_r, pos )) != std::string::npos )
334  {
335  str_r.replace( pos, from_r.size(), to_r );
336  pos += to_r.size();
337 
338  if ( pos >= str_r.length() )
339  break;
340  }
341  }
342  return str_r;
343  }
344 
345  std::string gsubFun( const std::string & str_r, const std::string & from_r, function<std::string()> to_r )
346  {
347  std::string ret( str_r );
348  return replaceAllFun( ret, from_r, to_r );
349  }
350 
351  std::string & replaceAllFun( std::string & str_r, const std::string & from_r, function<std::string()> to_r )
352  {
353  if ( ! from_r.empty() )
354  {
355  std::string::size_type pos = 0;
356  while ( (pos = str_r.find( from_r, pos )) != std::string::npos )
357  {
358  std::string to( to_r() );
359  str_r.replace( pos, from_r.size(), to );
360  pos += to.size();
361 
362  if ( pos >= str_r.length() )
363  break;
364  }
365  }
366  return str_r;
367  }
368 
369  std::string escape( const C_Str & str_r, const char sep_r )
370  {
371  std::vector<char> buf;
372  for_( s, str_r.c_str(), s+str_r.size() )
373  {
374  switch ( *s )
375  {
376  case '"':
377  case '\'':
378  case '\\':
379  buf.push_back( '\\' );
380  buf.push_back( *s );
381  break;
382  default:
383  if ( *s == sep_r )
384  buf.push_back( '\\' );
385  buf.push_back( *s );
386  }
387  }
388  return std::string( buf.begin(), buf.end() );
389  }
390 
391 
392  std::string bEscape( std::string str_r, const C_Str & special_r )
393  {
394  if ( str_r.empty() )
395  return str_r;
396 
397  if ( str_r.find_first_of( special_r ) == std::string::npos
398  && ( ::strchr( special_r.c_str(), '\\' ) || !::strchr( str_r.c_str(), '\\' ) ) )
399  return str_r;
400 
401  Str buf;
402  for_( s, str_r.c_str(), s+str_r.size() )
403  {
404  if ( *s == '\\' || ::strchr( special_r.c_str(), *s ) )
405  buf << '\\';
406  buf << *s;
407  }
408  return buf;
409  }
410 
411  #define RXSPECIALCHARS "\\.*+?^$[()|{"
412 
413  std::string rxEscapeStr( std::string str_r )
414  {
415  return bEscape( std::move(str_r), RXSPECIALCHARS );
416  }
417 
418  std::string rxEscapeGlob( std::string str_r )
419  {
420  if ( str_r.empty() )
421  return str_r;
422 
423  if ( str_r.find_first_of( RXSPECIALCHARS ) == std::string::npos )
424  return str_r;
425 
426  Str buf;
427  for_( s, str_r.c_str(), s+str_r.size() )
428  {
429  if ( *s == '\\' ) // + next char literally
430  {
431  buf << '\\';
432  if ( *(s+1) ) { ++s; buf << *s; }
433  }
434  else if ( *s == '?' ) // translate
435  {
436  buf << '.';
437  }
438  else if ( *s == '*' ) // translate
439  {
440  buf << ".*";
441  }
442  else if ( *s == '[' ) // character class if closing ] is found, else literally
443  {
444  const char * e = s+1;
445  if ( *e == '^' || *e == '!' ) // negated cclass
446  ++e;
447  if ( *e == ']' ) // ] in cclass
448  ++e;
449  while ( *e && *e != ']' ) // ...to ] or \0
450  ++e;
451  if ( *e ) // on closing ']'
452  {
453  ++s; buf << '[' << (*s == '!' ? '^' : *s );
454  while ( ++s != e )
455  buf << *s;
456  buf << ']';
457  }
458  else
459  {
460  buf << "\\[";
461  }
462  }
463  else if ( ::strchr( RXSPECIALCHARS, *s ) ) // escape
464  {
465  buf << '\\' << *s;
466  }
467  else
468  {
469  buf << *s;
470  }
471  }
472  return buf;
473  }
474 
475 
476  std::string getline( std::istream & str, const Trim trim_r )
477  {
478  return trim( receiveUpTo( str, '\n' ), trim_r );
479  }
480 
481  std::string getline( std::istream & str, bool trim_r )
482  {
483  return trim( receiveUpTo( str, '\n' ), trim_r?TRIM:NO_TRIM );
484  }
485 
486  std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r )
487  {
488  std::ostringstream datas;
489  do {
490  char ch;
491  if ( str.get( ch ) )
492  {
493  if ( ch != delim_r )
494  {
495  datas.put( ch );
496  }
497  else
498  {
499  if ( returnDelim_r )
500  datas.put( ch );
501  break; // --> delimiter found
502  }
503  }
504  else
505  {
506  // clear fail bit if we read data before reaching EOF
507  if ( str.eof() && datas.tellp() )
508  str.clear( std::ios::eofbit );
509  break; // --> no consumable data.
510  }
511  } while ( true );
512  return datas.str();
513  }
514 
516  } // namespace str
519 } // namespace zypp
std::string bEscape(std::string str_r, const C_Str &special_r)
Return str_r with '\'-escaped chars occurring in special_r (and '\').
Definition: String.cc:392
TriBool strToTriBool(const C_Str &str)
Parse str into a bool if it's a legal true or false string; else indterminate.
Definition: String.cc:91
std::string rxEscapeStr(std::string str_r)
Escape plain STRING str_r for use in a regex (not anchored by "^" or "$").
Definition: String.cc:413
std::string escape(const C_Str &str_r, const char sep_r)
Escape desired character c using a backslash.
Definition: String.cc:369
std::string asString() const
Definition: String.h:194
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:36
Trim
To define how to trim.
Definition: String.h:986
std::string ltrim(const std::string &s)
Definition: String.h:996
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition: String.h:30
std::string & replaceAll(std::string &str_r, const std::string &from_r, const std::string &to_r)
Replace all occurrences of from_r with to_r in str_r (inplace).
Definition: String.cc:328
std::string stripFirstWord(std::string &line, const bool ltrim_first)
Definition: String.cc:261
std::string rxEscapeGlob(std::string str_r)
Escape GLOB str_r for use in a regex (not anchored by "^" or "$").
Definition: String.cc:418
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:210
std::string trim(const std::string &s, const Trim trim_r)
Definition: String.cc:221
Convenience char* constructible from std::string and char*, it maps (char*)0 to an empty string...
Definition: String.h:90
std::string getline(std::istream &str, const Trim trim_r)
Return stream content up to (but not returning) the next newline.
Definition: String.cc:476
std::string stripLastWord(std::string &line, const bool rtrim_first)
Definition: String.cc:294
bool strToFalse(const C_Str &str)
Return false if str is 0, false, no, off.
Definition: String.cc:80
std::string gsubFun(const std::string &str_r, const std::string &from_r, function< std::string()> to_r)
Definition: String.cc:345
std::string toLower(const std::string &s)
Return lowercase version of s.
Definition: String.cc:175
SolvableIdType size_type
Definition: PoolMember.h:152
std::string rtrim(const std::string &s)
Definition: String.h:1001
#define RXSPECIALCHARS
Definition: String.cc:411
bool strToTrue(const C_Str &str)
Parsing boolean from string.
Definition: String.cc:63
std::string & replaceAllFun(std::string &str_r, const std::string &from_r, function< std::string()> to_r)
Definition: String.cc:351
std::string gsub(const std::string &str_r, const std::string &from_r, const std::string &to_r)
Return a string with all occurrences of from_r replaced with to_r.
Definition: String.cc:322
std::string receiveUpTo(std::istream &str, const char delim_r, bool returnDelim_r)
Return stream content up to the next ocurrence of delim_r or EOF delim_r, if found, is always read from the stream.
Definition: String.cc:486
const char * c_str() const
Definition: String.h:113
std::string hexencode(const C_Str &str_r)
Encode all characters other than [a-zA-Z0-9] as XX.
Definition: String.cc:122
size_type size() const
Definition: String.h:105
std::string strerror(int errno_r)
Return string describing the error_r code.
Definition: String.cc:53
std::string toUpper(const std::string &s)
Return uppercase version of s.
Definition: String.cc:198
Assert free called for allocated char *.
Definition: String.h:189
std::string hexdecode(const C_Str &str_r)
Decode hexencoded XX sequences.
Definition: String.cc:143