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