1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/base/String.h
12 #ifndef ZYPP_BASE_STRING_H
13 #define ZYPP_BASE_STRING_H
21 #include <boost/format.hpp>
23 #include "zypp/base/Easy.h"
24 #include "zypp/base/PtrTypes.h"
25 #include "zypp/base/Function.h"
28 ///////////////////////////////////////////////////////////////////
31 /** A formater with (N)o (A)rgument (C)heck.
32 * It won't complain about missing or excess arguments. Sometimes
33 * usefull when dealing with translations or classes providing a
36 inline format formatNAC( const std::string & string_r ) {
37 using namespace boost::io;
38 format fmter( string_r );
39 fmter.exceptions( all_error_bits ^ ( too_many_args_bit | too_few_args_bit ) );
43 namespace zypp { using boost::formatNAC; }
44 ///////////////////////////////////////////////////////////////////
46 ///////////////////////////////////////////////////////////////////
49 /** Request a human readable (translated) string representation of _Tp [_Tp.asUserString()]
50 * Classes may implement a default as member function.
53 std::string asUserString( const _Tp & val_r )
54 { return val_r.asUserString(); }
57 ///////////////////////////////////////////////////////////////////
59 ///////////////////////////////////////////////////////////////////
61 { /////////////////////////////////////////////////////////////////
63 struct MessageString : public std::string
66 MessageString( const char * str_r ) : std::string( str_r ? str_r : "" ) {}
67 MessageString( const std::string & str_r ) : std::string( str_r ) {}
68 // boost::format, std::ostringstream, str::Str ...
70 MessageString( const _Str & str_r ) : std::string( str_r.str() ) {}
73 /** Convenience \c char* constructible from \c std::string and \c char*,
74 * it maps \c (char*)0 to an empty string.
77 * bool hasPrefix( const std::string & str_r, const std::string & prefix_r )
78 * { return( ::strncmp( str_r.c_str(), prefix_r.c_str(), prefix_r.size() ) == 0 ); }
81 * Called with a plain \c char* as argument, the \c std::string is created form
82 * for nothing. The implementation actually does not use the \c std::string.
84 * Best would be to implement \c hasPrefix for each combination of \c char*
85 * and \c std::string arguments:
88 * bool hasPrefix( const std::string & str_r, const std::string & prefix_r )
89 * { return( ::strncmp( str_r.c_str(), prefix_r.c_str(), prefix_r.size() ) == 0 ); }
91 * bool hasPrefix( const std::string & str_r, const char * prefix_r )
92 * { return( !prefix_r || ::strncmp( str_r.c_str(), prefix_r, ::strlen(prefix_r) ) == 0 ); }
94 * bool hasPrefix( const char * str_r, const std::string & prefix_r )
95 * { return( str_r ? ::strncmp( str_r, prefix_r.c_str(), prefix_r.size() ) == 0 : prefix_r.empty() ); }
97 * bool hasPrefix( const char * str_r, const char * prefix_r )
98 * { return( str && prefix_r ? ::strncmp( str_r, prefix_r, ::strlen(prefix_r) ) == 0
99 * : !((str_r && *str_r) || (prefix_r && *prefix_r)); }
102 * This is where \ref C_Str can help. Constructible from \c std::string and \c char*,
103 * it \e reduces the \c std::string to it's \c char*. At the same time it converts
104 * \c (char*)0 into an \c "" string.
107 * bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r )
108 * { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
114 typedef std::string::size_type size_type;
117 C_Str() : _val( 0 ), _sze( 0 ) {}
118 C_Str( char * c_str_r ) : _val( c_str_r ), _sze( std::string::npos ) {}
119 C_Str( const char * c_str_r ) : _val( c_str_r ), _sze( std::string::npos ) {}
120 C_Str( const std::string & str_r ) : _val( str_r.c_str() ), _sze( str_r.size() ) {}
123 bool isNull() const { return !_val; }
124 bool empty() const { return !(_val && *_val); }
125 size_type size() const
127 if ( _sze == std::string::npos )
128 { _sze = _val ? ::strlen( _val ) : 0; }
132 operator const char *() const { return c_str(); }
133 const char * c_str() const { return _val ? _val : ""; }
136 const char *const _val;
137 mutable size_type _sze;
140 /** \relates C_Str Stream output */
141 inline std::ostream & operator<<( std::ostream & str, const C_Str & obj )
142 { return str << obj.c_str(); }
144 ///////////////////////////////////////////////////////////////////
145 /** String related utilities and \ref ZYPP_STR_REGEX.
146 \see \ref ZYPP_STR_REGEX
150 { /////////////////////////////////////////////////////////////////
152 ///////////////////////////////////////////////////////////////////
154 * Global asString() that works with std::string too
156 inline std::string asString( const std::string &t )
159 #ifndef SWIG // Swig treats it as syntax error
160 inline std::string asString( std::string && t )
161 { return std::move(t); }
164 inline std::string asString( const char * t )
167 inline std::string asString( char * t )
171 inline std::string asString( const _T &t )
172 { return t.asString(); }
175 inline std::string asString( const intrusive_ptr<_T> &p )
176 { return p->asString(); }
179 inline std::string asString( const weak_ptr<_T> &p )
180 { return p->asString(); }
183 inline std::string asString( const bool &t )
184 { return t ? "true" : "false"; }
186 ///////////////////////////////////////////////////////////////////
187 /** Printf style construction of std::string. */
188 std::string form( const char * format, ... )
189 __attribute__ ((format (printf, 1, 2)));
191 ///////////////////////////////////////////////////////////////////
192 /** Return string describing the \a error_r code.
193 * Like ::strerror, but the numerical value is included in
194 * the string as well.
196 std::string strerror( int errno_r );
198 ///////////////////////////////////////////////////////////////////
199 /** Assert \c free called for allocated <tt>char *</tt>.
203 * vasprintf( &safe._buf, format, ap );
204 * return safe.asString();
212 SafeBuf() : _buf( 0 ) {}
213 ~SafeBuf() { if ( _buf ) free( _buf ); }
214 std::string asString() const
215 { return _buf ? std::string(_buf) : std::string(); }
218 ///////////////////////////////////////////////////////////////////
219 /** Convenient building of std::string via std::ostream::operator<<.
220 * Basically this is an \ref ostringstream which is autocenvertible
221 * into a \ref string.
223 * void fnc( const std::string & txt_r );
224 * fnc( str::Str() << "Hello " << 13 );
226 * std::string txt( str::Str() << 45 );
232 Str & operator<<( const _Tp & val )
233 { _str << val; return *this; }
235 operator std::string() const
236 { return _str.str(); }
238 std::string str() const
239 { return _str.str(); }
241 std::ostream & stream()
245 { _str.str( std::string() ); }
247 std::ostringstream _str;
250 inline std::ostream & operator<<( std::ostream & str, const Str & obj )
251 { return str << (std::string)obj; }
253 ///////////////////////////////////////////////////////////////////
254 /** \name String representation of number.
256 * Optional second argument sets the minimal string width (' ' padded).
257 * Negative values will cause the number to be left adjusted within the string.
259 * Default width is 0.
261 * numstring(42) -> "42"
262 * numstring(42, 4) -> " 42"
263 * numstring(42,-4) -> "42 "
267 inline std::string numstring( char n, int w = 0 ) { return form( "%*hhd", w, n ); }
268 inline std::string numstring( unsigned char n, int w = 0 ) { return form( "%*hhu", w, n ); }
269 inline std::string numstring( short n, int w = 0 ) { return form( "%*hd", w, n ); }
270 inline std::string numstring( unsigned short n, int w = 0 ) { return form( "%*hu", w, n ); }
271 inline std::string numstring( int n, int w = 0 ) { return form( "%*d", w, n ); }
272 inline std::string numstring( unsigned n, int w = 0 ) { return form( "%*u", w, n ); }
273 inline std::string numstring( long n, int w = 0 ) { return form( "%*ld", w, n ); }
274 inline std::string numstring( unsigned long n, int w = 0 ) { return form( "%*lu", w, n ); }
275 inline std::string numstring( long long n, int w = 0 ) { return form( "%*lld", w, n ); }
276 inline std::string numstring( unsigned long long n, int w = 0 ) { return form( "%*llu", w, n ); }
278 template<> inline std::string asString( const char & t ) { return numstring( t ); }
279 template<> inline std::string asString( const unsigned char & t ) { return numstring( t ); }
280 template<> inline std::string asString( const short & t ) { return numstring( t ); }
281 template<> inline std::string asString( const unsigned short & t ) { return numstring( t ); }
282 template<> inline std::string asString( const int & t ) { return numstring( t ); }
283 template<> inline std::string asString( const unsigned & t ) { return numstring( t ); }
284 template<> inline std::string asString( const long & t ) { return numstring( t ); }
285 template<> inline std::string asString( const unsigned long & t ) { return numstring( t ); }
286 template<> inline std::string asString( const long long & t ) { return numstring( t ); }
287 template<> inline std::string asString( const unsigned long long & t ) { return numstring( t ); }
290 ///////////////////////////////////////////////////////////////////
291 /** \name String representation of number as hex value with leading '0x'.
292 * Optional second argument sets the minimal
293 * string width (0 padded). Negative values will cause the number to be left adjusted
294 * within the string. Default width is 10 (4 for char).
296 * hexstring(42) -> "0x0000002a"
297 * hexstring(42, 4) -> "0x2a"
298 * hexstring(42,-4) -> "0x2a"
302 inline std::string hexstring( char n, int w = 4 ) { return form( "%#0*hhx", w, n ); }
303 inline std::string hexstring( unsigned char n, int w = 4 ) { return form( "%#0*hhx", w, n ); }
304 inline std::string hexstring( short n, int w = 10 ){ return form( "%#0*hx", w, n ); }
305 inline std::string hexstring( unsigned short n, int w = 10 ){ return form( "%#0*hx", w, n ); }
306 inline std::string hexstring( int n, int w = 10 ){ return form( "%#0*x", w, n ); }
307 inline std::string hexstring( unsigned n, int w = 10 ){ return form( "%#0*x", w, n ); }
308 inline std::string hexstring( long n, int w = 10 ){ return form( "%#0*lx", w, n ); }
309 inline std::string hexstring( unsigned long n, int w = 10 ){ return form( "%#0*lx", w, n ); }
310 inline std::string hexstring( long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
311 inline std::string hexstring( unsigned long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
314 ///////////////////////////////////////////////////////////////////
315 /** \name String representation of number as octal value with leading '0'.
316 * Optional second argument sets the minimal
317 * string width (0 padded). Negative values will cause the number to be left adjusted
318 * within the string. Default width is 5 (4 for char).
320 * octstring(42) -> "00052"
321 * octstring(42, 4) -> "0052"
322 * octstring(42,-4) -> "052 "
326 inline std::string octstring( char n, int w = 4 ) { return form( "%#0*hho", w, n ); }
327 inline std::string octstring( unsigned char n, int w = 4 ) { return form( "%#0*hho", w, n ); }
328 inline std::string octstring( short n, int w = 5 ) { return form( "%#0*ho", w, n ); }
329 inline std::string octstring( unsigned short n, int w = 5 ) { return form( "%#0*ho", w, n ); }
330 inline std::string octstring( int n, int w = 5 ) { return form( "%#0*o", w, n ); }
331 inline std::string octstring( unsigned n, int w = 5 ) { return form( "%#0*o", w, n ); }
332 inline std::string octstring( long n, int w = 5 ) { return form( "%#0*lo", w, n ); }
333 inline std::string octstring( unsigned long n, int w = 5 ) { return form( "%#0*lo", w, n ); }
334 inline std::string octstring( long long n, int w = 0 ) { return form( "%#0*llo", w, n ); }
335 inline std::string octstring( unsigned long long n, int w = 0 ) { return form( "%#0*llo", w, n ); }
338 ///////////////////////////////////////////////////////////////////
339 /** Parsing numbers from string.
342 /** String to integer type determined by template arg.
343 * \note Only specializations are defined.
345 * time_t t = strtonum<time_t>( "42" );
348 template<typename _It>
349 _It strtonum( const C_Str & str );
352 inline short strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
354 inline int strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
356 inline long strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
358 inline long long strtonum( const C_Str & str ) { return ::strtoll ( str, NULL, 0 ); }
361 inline unsigned short strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
363 inline unsigned strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
365 inline unsigned long strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
367 inline unsigned long long strtonum( const C_Str & str ) { return ::strtoull( str, NULL, 0 ); }
369 /** String to integer type detemined 2nd function arg \a i.
371 * time_t t; strtonum( "42", t );
374 template<typename _It>
375 inline _It strtonum( const C_Str & str, _It & i )
376 { return i = strtonum<_It>( str ); }
379 ///////////////////////////////////////////////////////////////////
380 /** Parsing boolean from string.
383 /** Return \c true if str is <tt>1, true, yes, on</tt> (or a nonzero number). */
384 bool strToTrue( const C_Str & str );
386 /** Return \c false if str is <tt>0, false, no, off</tt>. */
387 bool strToFalse( const C_Str & str );
389 /** Parse \c str into a bool depending on the default value.
390 * If the \c default is true, look for a legal \c false string.
391 * If the \c default is false, look for a legal \c true string.
393 inline bool strToBool( const C_Str & str, bool default_r )
394 { return( default_r ? strToFalse( str ) : strToTrue( str ) ); }
396 /** Parse \c str into a bool if it's a legal \c true or \c false string.
397 * If \c str is not a recognized \c true or \c false string, \a return_r
400 inline bool strToBoolNodefault( const C_Str & str, bool & return_r )
402 if ( strToTrue( str ) ) return (return_r = true);
403 if ( !strToFalse( str ) ) return (return_r = false);
410 * \short Return a string with all occurrences of \c from_r replaced with \c to_r.
412 std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r );
414 /** \overload A function is called on demand to compute each replacement value.
416 std::string gsubFun( const std::string & str_r, const std::string & from_r, function<std::string()> to_r );
419 * \short Replace all occurrences of \c from_r with \c to_r in \c str_r (inplace).
420 * A reference to \c str_r is also returned for convenience.
422 std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r );
424 /** \overload A function is called on demand to compute each replacement value.
426 std::string & replaceAllFun( std::string & str_r, const std::string & from_r, function<std::string()> to_r );
428 /** Enhance readability: insert gaps at regular distance
431 * Key Fingerprint: 22C07BA534178CD02EFE22AAB88B2FD43DBDC284
433 * Key Fingerprint: 22C07BA5 34178CD0 2EFE22AA B88B2FD4 3DBDC284
435 * Key Fingerprint: 22C0 7BA5 3417 8CD0 2EFE 22AA B88B 2FD4 3DBD C284
437 * Key Fingerprint: 22C0-7BA5-3417-8CD0-2EFE-22AA-B88B-2FD4-3DBD-C284
440 inline std::string gapify( std::string inp_r, std::string::size_type gap_r = 1, char gapchar = ' ' )
442 if ( gap_r && inp_r.size() > gap_r )
444 inp_r.reserve( inp_r.size() + (inp_r.size()-1)/gap_r );
445 for ( std::string::size_type pos = gap_r; pos < inp_r.size(); pos += gap_r+1 )
446 inp_r.insert( pos, 1, gapchar );
451 ///////////////////////////////////////////////////////////////////
454 /** Split \a line_r into words.
455 * Any sequence of characters in \a sepchars_r is treated as
456 * delimiter. The words are passed to OutputIterator \a result_r.
458 * std::vector<std::string> words;
459 * str::split( "some line", std::back_inserter(words) )
463 template<class _OutputIterator>
464 unsigned split( const C_Str & line_r,
465 _OutputIterator result_r,
466 const C_Str & sepchars_r = " \t" )
468 const char * beg = line_r;
469 const char * cur = beg;
470 // skip leading sepchars
471 while ( *cur && ::strchr( sepchars_r, *cur ) )
474 for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
477 while( *cur && !::strchr( sepchars_r, *cur ) )
480 *result_r = std::string( beg, cur-beg );
482 while ( *cur && ::strchr( sepchars_r, *cur ) )
488 /** Split \a line_r into words with respect to escape delimeters.
489 * Any sequence of characters in \a sepchars_r is treated as
490 * delimiter if not inside \c "" or \c '' or escaped by \c \.
492 * \li A non-quoted backslash (\) preserves the literal value of the next character.
493 * \li Enclosing characters in single quotes preserves the literal value of each
494 * character within the quotes. A single quote may not occur between single
495 * quotes, even when preceded by a backslash.
496 * \li Enclosing characters in double quotes preserves the literal value of all
497 * characters within the quotes, with the exception of \c \. The backslash
498 * retains its special meaning only when followed by \c " or \c \.
500 * The words are passed to OutputIterator \a result_r.
502 * \see \ref splitEscaped
505 * std::vector<std::string> words;
506 * str::splitEscaped( "some line", std::back_inserter(words) )
510 * example splitted strings
511 * normal line -> 2 elements ( "normal", "line" )
512 * escaped\ line -> 1 element(escaped line)
513 * "quoted line" -> 1 element same as above
514 * 'quoted line' -> 1 element same as above
515 * "escaped quote\"" -> 1 element (escaped quote")
517 * \param line_r The string to parse.
519 * \param sepchars_r String of separator characters.
520 * \param withEmpty Whether to include empty fields between separators in the result.
524 template<class _OutputIterator>
525 unsigned splitEscaped( const C_Str & line_r,
526 _OutputIterator result_r,
527 const C_Str & sepchars_r = " \t",
528 bool withEmpty = false)
530 const char * beg = line_r;
531 const char * cur = beg;
534 // skip leading sepchars
535 while ( *cur && ::strchr( sepchars_r, *cur ) )
545 // there were only sepchars in the string
546 if (!*cur && withEmpty)
552 // after the leading sepchars
553 enum class Quote { None, Slash, Single, Double, DoubleSlash };
554 std::vector<char> buf;
555 Quote quoting = Quote::None;
556 for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
558 // read next value until unquoted sepchar
560 quoting = Quote::None;
567 case '\\': quoting = Quote::Slash; break;
568 case '\'': quoting = Quote::Single; break;
569 case '"': quoting = Quote::Double; break;
570 default: buf.push_back( *cur ); break;
575 buf.push_back( *cur );
576 quoting = Quote::None;
582 case '\'': quoting = Quote::None; break;
583 default: buf.push_back( *cur ); break;
590 case '\"': quoting = Quote::None; break;
591 case '\\': quoting = Quote::DoubleSlash; break;
592 default: buf.push_back( *cur ); break;
596 case Quote::DoubleSlash:
599 case '\"': /*fallthrough*/
600 case '\\': buf.push_back( *cur ); break;
602 buf.push_back( '\\' );
603 buf.push_back( *cur );
606 quoting = Quote::Double;
610 } while ( *cur && ( quoting != Quote::None || !::strchr( sepchars_r, *cur ) ) );
611 *result_r = std::string( buf.begin(), buf.end() );
615 if ( *cur && ::strchr( sepchars_r, *cur ) )
617 while ( *cur && ::strchr( sepchars_r, *cur ) )
626 // the last was a separator => one more field
627 if ( !*cur && withEmpty && ::strchr( sepchars_r, *(cur-1) ) )
636 /** Split \a line_r into fields.
637 * Any single character in \a sepchars_r is treated as a
638 * field separator unless \-escaped. The words are passed
645 * ":a" -> words 2 ||a|
646 * "a:" -> words 2 |a||
647 * ":a:" -> words 3 ||a||
652 * std::vector<std::string> words;
653 * str::split( "some line", std::back_inserter(words) )
657 template<class _OutputIterator>
658 unsigned splitFields( const C_Str & line_r,
659 _OutputIterator result_r,
660 const C_Str & sepchars_r = ":" )
662 const char * beg = line_r;
663 const char * cur = beg;
665 for ( beg = cur; *beg; beg = cur, ++result_r )
668 while( *cur && !::strchr( sepchars_r, *cur ) )
670 if ( *cur == '\\' && *(cur+1) )
675 *result_r = std::string( beg, cur-beg );
681 if ( ! *cur ) // ending with sepchar
683 *result_r = std::string(); // add final empty field
693 * Split \a line_r into fields handling also escaped separators.
696 * \see splitEscaped()
698 template<class _OutputIterator>
699 unsigned splitFieldsEscaped( const C_Str & line_r,
700 _OutputIterator result_r,
701 const C_Str & sepchars_r = ":" )
704 splitEscaped( line_r, result_r, sepchars_r, true /* withEmpty */ );
709 ///////////////////////////////////////////////////////////////////
712 /** Join strings using separator \a sep_r (defaults to BLANK). */
713 template <class _Iterator>
714 std::string join( _Iterator begin, _Iterator end,
715 const C_Str & sep_r = " " )
718 for ( _Iterator iter = begin; iter != end; ++ iter )
722 res += asString(*iter);
727 /** Join strings using separator \a sep_r (defaults to BLANK). */
728 template <class _Container>
729 std::string join( const _Container & cont_r,
730 const C_Str & sep_r = " " )
731 { return join( cont_r.begin(), cont_r.end(), sep_r ); }
733 /** Join strings using separator \a sep_r, quoting or escaping the values.
734 * Separator defaults to BLANK. Use \ref splitEscaped to restore the
737 template <class _Iterator>
738 std::string joinEscaped( _Iterator begin, _Iterator end,
739 const char sep_r = ' ' )
741 std::vector<char> buf;
742 for ( _Iterator iter = begin; iter != end; ++ iter )
745 buf.push_back( sep_r );
749 // empty string goes ""
750 buf.push_back( '"' );
751 buf.push_back( '"' );
755 std::string toadd( asString(*iter) );
756 for_( ch, toadd.begin(), toadd.end() )
763 buf.push_back( '\\' );
764 buf.push_back( *ch );
768 buf.push_back( '\\' );
769 buf.push_back( *ch );
774 return std::string( buf.begin(), buf.end() );
779 ///////////////////////////////////////////////////////////////////
782 /** Indent by string [" "] optionally wrap.
783 * Prints nothing for an empty string. Asserts a trainling '\n' on
784 * the last line. Optionally wrap lines at ' ' at a given length.
786 inline std::ostream & printIndented( std::ostream & str, const std::string & text_r, const std::string & indent_r = " ", unsigned maxWitdh_r = 0 )
790 if ( indent_r.size() >= maxWitdh_r )
791 maxWitdh_r = 0; // nonsense: indent larger than line witdh
793 maxWitdh_r -= indent_r.size();
796 for ( const char * e = text_r.c_str(), * s = e; *e; s = ++e )
798 for ( ; *e && *e != '\n'; ++e ) ;/*searching*/
800 if ( maxWitdh_r && width > maxWitdh_r )
804 for ( e = s+width; e > s && *e != ' '; --e ) ;/*searching*/
806 width = e-s; // on a ' ', replaced by '\n'
808 e = s+width-1; // cut line;
811 str.write( s, width );
813 if ( !*e ) // on '\0'
818 /** \overload Indent by number of chars [' '] optionally wrap. */
819 inline std::ostream & printIndented( std::ostream & str, const std::string & text_r, unsigned indent_r, char indentch_r = ' ', unsigned maxWitdh_r = 0 )
820 { return printIndented( str, text_r, std::string( indent_r, indentch_r ), maxWitdh_r ); }
821 /** \overload Indent by number of chars [' '] wrap. */
822 inline std::ostream & printIndented( std::ostream & str, const std::string & text_r, unsigned indent_r, unsigned maxWitdh_r, char indentch_r = ' ' )
823 { return printIndented( str, text_r, std::string( indent_r, indentch_r ), maxWitdh_r ); }
825 /** Prefix lines by string computed by function taking line begin/end [std::string(const char*, const char*)]
826 * Prints nothing for an empty string. Asserts a trainling '\n' on the last line.
828 inline std::ostream & autoPrefix( std::ostream & str, const std::string & text_r, function<std::string(const char*, const char*)> fnc_r )
830 for ( const char * e = text_r.c_str(); *e; ++e )
833 for ( ; *e && *e != '\n'; ++e ) /*searching*/;
834 str << fnc_r( s, e );
837 if ( !*e ) // on '\0'
842 /** \overload Prefix lines by string generated by function [std::string()] */
843 inline std::ostream & autoPrefix0( std::ostream & str, const std::string & text_r, function<std::string()> fnc_r )
845 auto wrap = [&fnc_r]( const char*, const char* )-> std::string {
848 return autoPrefix( str, text_r, wrap );
851 ///////////////////////////////////////////////////////////////////
855 * Escape desired character \a c using a backslash.
857 * For use when printing \a c separated values, and where
858 * \ref joinEscaped() is too heavy.
860 std::string escape( const C_Str & str_r, const char c = ' ' );
862 /** Escape \a next_r and append it to \a str_r using separator \a sep_r. */
863 inline void appendEscaped( std::string & str_r, const C_Str & next_r, const char sep_r = ' ' )
865 if ( ! str_r.empty() )
867 if ( next_r.empty() )
870 str_r += escape( next_r, sep_r );
876 ///////////////////////////////////////////////////////////////////
877 ///////////////////////////////////////////////////////////////////
879 * Encode all characters other than [a-zA-Z0-9] as %XX.
880 * This includes the % character itself, which becomes %25.
883 /** Encode all characters other than [a-zA-Z0-9] as %XX.
884 * This includes the % character itself, which becomes %25.
886 std::string hexencode( const C_Str & str_r );
887 /** Decode hexencoded %XX sequences. */
888 std::string hexdecode( const C_Str & str_r );
890 ///////////////////////////////////////////////////////////////////
892 /** \name Case conversion. */
894 /** Return lowercase version of \a s
897 std::string toLower( const std::string & s );
899 inline std::string toLower( const char * s )
900 { return( s ? toLower( std::string(s) ) : std::string() ); }
902 /** Return uppercase version of \a s
905 std::string toUpper( const std::string & s );
907 inline std::string toUpper( const char * s )
908 { return( s ? toUpper( std::string(s) ) : std::string() ); }
912 /** \name Case insensitive comparison. */
914 inline int compareCI( const C_Str & lhs, const C_Str & rhs )
915 { return ::strcasecmp( lhs, rhs ); }
918 /** \name Locate substring. */
920 /** Locate substring case sensitive. */
921 inline bool contains( const C_Str & str_r, const C_Str & val_r )
922 { return ::strstr( str_r, val_r ); }
923 /** Locate substring case insensitive. */
924 inline bool containsCI( const C_Str & str_r, const C_Str & val_r )
925 { return ::strcasestr( str_r, val_r ); }
928 ///////////////////////////////////////////////////////////////////
929 /** \name Trimming whitepace.
930 * \todo optimize l/r trim.
933 /** To define how to trim. */
938 TRIM = (L_TRIM|R_TRIM)
941 std::string trim( const std::string & s, const Trim trim_r = TRIM );
943 inline std::string ltrim( const std::string & s )
944 { return trim( s, L_TRIM ); }
946 inline std::string rtrim( const std::string & s )
947 { return trim( s, R_TRIM ); }
950 std::string stripFirstWord( std::string & line, const bool ltrim_first = true );
952 std::string stripLastWord( std::string & line, const bool rtrim_first = true );
954 /** Return stream content up to (but not returning) the next newline.
955 * \see \ref receiveUpTo
957 std::string getline( std::istream & str, bool trim = false );
959 /** Return stream content up to (but not returning) the next newline.
960 * \see \ref receiveUpTo
962 std::string getline( std::istream & str, const Trim trim_r );
964 /** Return stream content up to the next ocurrence of \c delim_r or EOF
965 * \c delim_r, if found, is always read from the stream. Whether it is
966 * also returned in the string depends on \c returnDelim_r.
967 * If the stream status is \c good, \c delim_r was found in the stream.
968 * If we reached EOF while looking for \c delim_r, \c eof is set; and
969 * also \c fail, if we did not read any data before.
971 std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r = false );
973 ///////////////////////////////////////////////////////////////////
975 /** \name String prefix/suffix handling.
978 /** Return whether \a str_r has prefix \a prefix_r. */
979 inline bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r )
980 { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
982 /** Strip a \a prefix_r from \a str_r and return the resulting string. */
983 inline std::string stripPrefix( const C_Str & str_r, const C_Str & prefix_r )
984 { return( hasPrefix( str_r, prefix_r ) ? str_r + prefix_r.size() : str_r.c_str() ); }
986 /** Return whether \a str_r has suffix \a suffix_r. */
987 inline bool hasSuffix( const C_Str & str_r, const C_Str & suffix_r )
988 { return( str_r.size() >= suffix_r.size() && ::strncmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); }
990 /** Strip a \a suffix_r from \a str_r and return the resulting string. */
991 inline std::string stripSuffix( const C_Str & str_r, const C_Str & suffix_r )
993 if ( hasSuffix( str_r, suffix_r ) )
994 return std::string( str_r, str_r.size() - suffix_r.size() );
995 return str_r.c_str();
997 /** Return size of the common prefix of \a lhs and \a rhs. */
998 inline std::string::size_type commonPrefix( const C_Str & lhs, const C_Str & rhs )
1000 const char * lp = lhs.c_str();
1001 const char * rp = rhs.c_str();
1002 std::string::size_type ret = 0;
1003 while ( *lp == *rp && *lp != '\0' )
1004 { ++lp, ++rp, ++ret; }
1008 /** alias for \ref hasPrefix */
1009 inline bool startsWith( const C_Str & str_r, const C_Str & prefix_r )
1010 { return hasPrefix( str_r, prefix_r ); }
1011 /** alias for \ref hasSuffix */
1012 inline bool endsWith( const C_Str & str_r, const C_Str & prefix_r )
1013 { return hasSuffix( str_r, prefix_r ); }
1016 ///////////////////////////////////////////////////////////////////
1018 // drag into zypp:: namespace
1019 using str::asString;
1022 ///////////////////////////////////////////////////////////////////
1023 #endif // ZYPP_BASE_STRING_H