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