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