libzypp  14.48.5
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  {
177  if ( s.empty() )
178  return s;
179 
180  std::string ret( s );
181  for ( std::string::size_type i = 0; i < ret.length(); ++i )
182  {
183  if ( isupper( ret[i] ) )
184  ret[i] = static_cast<char>(tolower( ret[i] ));
185  }
186  return ret;
187  }
188 
189  /******************************************************************
190  **
191  ** FUNCTION NAME : toUpper
192  ** FUNCTION TYPE : std::string
193  */
194  std::string toUpper( const std::string & s )
195  {
196  if ( s.empty() )
197  return s;
198 
199  std::string ret( s );
200  for ( std::string::size_type i = 0; i < ret.length(); ++i )
201  {
202  if ( islower( ret[i] ) )
203  ret[i] = static_cast<char>(toupper( ret[i] ));
204  }
205  return ret;
206  }
207 
208  /******************************************************************
209  **
210  ** FUNCTION NAME : trim
211  ** FUNCTION TYPE : std::string
212  */
213  std::string trim( const std::string & s, const Trim trim_r )
214  {
215  if ( s.empty() || trim_r == NO_TRIM )
216  return s;
217 
218  std::string ret( s );
219 
220  if ( trim_r & L_TRIM )
221  {
222  std::string::size_type p = ret.find_first_not_of( " \t\n" );
223  if ( p == std::string::npos )
224  return std::string();
225 
226  ret = ret.substr( p );
227  }
228 
229  if ( trim_r & R_TRIM )
230  {
231  std::string::size_type p = ret.find_last_not_of( " \t\n" );
232  if ( p == std::string::npos )
233  return std::string();
234 
235  ret = ret.substr( 0, p+1 );
236  }
237 
238  return ret;
239  }
240 
241  /******************************************************************
242  **
243  ** FUNCTION NAME : stripFirstWord
244  ** FUNCTION TYPE : std::string
245  */
246  std::string stripFirstWord( std::string & line, const bool ltrim_first )
247  {
248  if ( ltrim_first )
249  line = ltrim( line );
250 
251  if ( line.empty() )
252  return line;
253 
254  std::string ret;
255  std::string::size_type p = line.find_first_of( " \t" );
256 
257  if ( p == std::string::npos ) {
258  // no ws on line
259  ret = line;
260  line.erase();
261  } else if ( p == 0 ) {
262  // starts with ws
263  // ret remains empty
264  line = ltrim( line );
265  }
266  else {
267  // strip word and ltim line
268  ret = line.substr( 0, p );
269  line = ltrim( line.erase( 0, p ) );
270  }
271  return ret;
272  }
273 
274  /******************************************************************
275  **
276  ** FUNCTION NAME : stripLastWord
277  ** FUNCTION TYPE : std::string
278  */
279  std::string stripLastWord( std::string & line, const bool rtrim_first )
280  {
281  if ( rtrim_first )
282  line = rtrim( line );
283 
284  if ( line.empty() )
285  return line;
286 
287  std::string ret;
288  std::string::size_type p = line.find_last_of( " \t" );
289 
290  if ( p == std::string::npos ) {
291  // no ws on line
292  ret = line;
293  line.erase();
294  } else if ( p == line.size()-1 ) {
295  // ends with ws
296  // ret remains empty
297  line = rtrim( line );
298  }
299  else {
300  // strip word and rtim line
301  ret = line.substr( p+1 );
302  line = rtrim( line.erase( p ) );
303  }
304  return ret;
305  }
306 
307  std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r )
308  {
309  std::string ret( str_r );
310  return replaceAll( ret, from_r, to_r );
311  }
312 
313  std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r )
314  {
315  if ( ! from_r.empty() )
316  {
317  std::string::size_type pos = 0;
318  while ( (pos = str_r.find( from_r, pos )) != std::string::npos )
319  {
320  str_r.replace( pos, from_r.size(), to_r );
321  pos += to_r.size();
322 
323  if ( pos >= str_r.length() )
324  break;
325  }
326  }
327  return str_r;
328  }
329 
330  std::string gsubFun( const std::string & str_r, const std::string & from_r, function<std::string()> to_r )
331  {
332  std::string ret( str_r );
333  return replaceAllFun( ret, from_r, to_r );
334  }
335 
336  std::string & replaceAllFun( std::string & str_r, const std::string & from_r, function<std::string()> to_r )
337  {
338  if ( ! from_r.empty() )
339  {
340  std::string::size_type pos = 0;
341  while ( (pos = str_r.find( from_r, pos )) != std::string::npos )
342  {
343  std::string to( to_r() );
344  str_r.replace( pos, from_r.size(), to );
345  pos += to.size();
346 
347  if ( pos >= str_r.length() )
348  break;
349  }
350  }
351  return str_r;
352  }
353 
354  std::string escape( const C_Str & str_r, const char sep_r )
355  {
356  std::vector<char> buf;
357  for_( s, str_r.c_str(), s+str_r.size() )
358  {
359  switch ( *s )
360  {
361  case '"':
362  case '\'':
363  case '\\':
364  buf.push_back( '\\' );
365  buf.push_back( *s );
366  break;
367  default:
368  if ( *s == sep_r )
369  buf.push_back( '\\' );
370  buf.push_back( *s );
371  }
372  }
373  return std::string( buf.begin(), buf.end() );
374  }
375 
376 
377  std::string bEscape( std::string str_r, const C_Str & special_r )
378  {
379  if ( str_r.empty() )
380  return str_r;
381 
382  if ( str_r.find_first_of( special_r ) == std::string::npos
383  && ( ::strchr( special_r.c_str(), '\\' ) || !::strchr( str_r.c_str(), '\\' ) ) )
384  return str_r;
385 
386  Str buf;
387  for_( s, str_r.c_str(), s+str_r.size() )
388  {
389  if ( *s == '\\' || ::strchr( special_r.c_str(), *s ) )
390  buf << '\\';
391  buf << *s;
392  }
393  return buf;
394  }
395 
396  #define RXSPECIALCHARS "\\.*+?^$[()|{"
397 
398  std::string rxEscapeStr( std::string str_r )
399  {
400  return bEscape( std::move(str_r), RXSPECIALCHARS );
401  }
402 
403  std::string rxEscapeGlob( std::string str_r )
404  {
405  if ( str_r.empty() )
406  return str_r;
407 
408  if ( str_r.find_first_of( RXSPECIALCHARS ) == std::string::npos )
409  return str_r;
410 
411  Str buf;
412  for_( s, str_r.c_str(), s+str_r.size() )
413  {
414  if ( *s == '\\' ) // + next char literally
415  {
416  buf << '\\';
417  if ( *(s+1) ) { ++s; buf << *s; }
418  }
419  else if ( *s == '?' ) // translate
420  {
421  buf << '.';
422  }
423  else if ( *s == '*' ) // translate
424  {
425  buf << ".*";
426  }
427  else if ( *s == '[' ) // character class if closing ] is found, else literally
428  {
429  const char * e = s+1;
430  if ( *e == '^' || *e == '!' ) // negated cclass
431  ++e;
432  if ( *e == ']' ) // ] in cclass
433  ++e;
434  while ( *e && *e != ']' ) // ...to ] or \0
435  ++e;
436  if ( *e ) // on closing ']'
437  {
438  ++s; buf << '[' << (*s == '!' ? '^' : *s );
439  while ( ++s != e )
440  buf << *s;
441  buf << ']';
442  }
443  else
444  {
445  buf << "\\[";
446  }
447  }
448  else if ( ::strchr( RXSPECIALCHARS, *s ) ) // escape
449  {
450  buf << '\\' << *s;
451  }
452  else
453  {
454  buf << *s;
455  }
456  }
457  return buf;
458  }
459 
460 
461  std::string getline( std::istream & str, const Trim trim_r )
462  {
463  return trim( receiveUpTo( str, '\n' ), trim_r );
464  }
465 
466  std::string getline( std::istream & str, bool trim_r )
467  {
468  return trim( receiveUpTo( str, '\n' ), trim_r?TRIM:NO_TRIM );
469  }
470 
471  std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r )
472  {
473  std::ostringstream datas;
474  do {
475  char ch;
476  if ( str.get( ch ) )
477  {
478  if ( ch != delim_r )
479  {
480  datas.put( ch );
481  }
482  else
483  {
484  if ( returnDelim_r )
485  datas.put( ch );
486  break; // --> delimiter found
487  }
488  }
489  else
490  {
491  // clear fail bit if we read data before reaching EOF
492  if ( str.eof() && datas.tellp() )
493  str.clear( std::ios::eofbit );
494  break; // --> no consumable data.
495  }
496  } while ( true );
497  return datas.str();
498  }
499 
501  } // namespace str
504 } // 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:377
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:398
std::string escape(const C_Str &str_r, const char sep_r)
Escape desired character c using a backslash.
Definition: String.cc:354
std::string asString() const
Definition: String.h:200
#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:990
std::string ltrim(const std::string &s)
Definition: String.h:999
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition: String.h:29
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:313
std::string stripFirstWord(std::string &line, const bool ltrim_first)
Definition: String.cc:246
std::string rxEscapeGlob(std::string str_r)
Escape GLOB str_r for use in a regex (not anchored by "^" or "$").
Definition: String.cc:403
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:216
std::string trim(const std::string &s, const Trim trim_r)
Definition: String.cc:213
Convenience char* constructible from std::string and char*, it maps (char*)0 to an empty string...
Definition: String.h:97
std::string getline(std::istream &str, const Trim trim_r)
Return stream content up to (but not returning) the next newline.
Definition: String.cc:461
std::string stripLastWord(std::string &line, const bool rtrim_first)
Definition: String.cc:279
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:330
std::string toLower(const std::string &s)
Return lowercase version of s.
Definition: String.cc:175
SolvableIdType size_type
Definition: PoolMember.h:147
std::string rtrim(const std::string &s)
Definition: String.h:1002
#define RXSPECIALCHARS
Definition: String.cc:396
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:336
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:307
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:471
const char * c_str() const
Definition: String.h:119
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:111
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:194
Assert free called for allocated char *.
Definition: String.h:195
std::string hexdecode(const C_Str &str_r)
Decode hexencoded XX sequences.
Definition: String.cc:143