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
///////////////////////////////////////////////////////////////////
45
///////////////////////////////////////////////////////////////////
48
/** Request a human readable (translated) string representation of _Tp [_Tp.asUserString()]
49
* Classes may implement a default as member function.
52
std::string asUserString( const _Tp & val_r )
53
{ return val_r.asUserString(); }
56
///////////////////////////////////////////////////////////////////
58
///////////////////////////////////////////////////////////////////
60
{ /////////////////////////////////////////////////////////////////
62
/** Convenience \c char* constructible from \c std::string and \c char*,
63
* it maps \c (char*)0 to an empty string.
66
* bool hasPrefix( const std::string & str_r, const std::string & prefix_r )
67
* { return( ::strncmp( str_r.c_str(), prefix_r.c_str(), prefix_r.size() ) == 0 ); }
70
* Called with a plain \c char* as argument, the \c std::string is created form
71
* for nothing. The implementation actually does not use the \c std::string.
73
* Best would be to implement \c hasPrefix for each combination of \c char*
74
* and \c std::string arguments:
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 ); }
80
* bool hasPrefix( const std::string & str_r, const char * prefix_r )
81
* { return( !prefix_r || ::strncmp( str_r.c_str(), prefix_r, ::strlen(prefix_r) ) == 0 ); }
83
* bool hasPrefix( const char * str_r, const std::string & prefix_r )
84
* { return( str_r ? ::strncmp( str_r, prefix_r.c_str(), prefix_r.size() ) == 0 : prefix_r.empty() ); }
86
* bool hasPrefix( const char * str_r, const char * prefix_r )
87
* { return( str && prefix_r ? ::strncmp( str_r, prefix_r, ::strlen(prefix_r) ) == 0
88
* : !((str_r && *str_r) || (prefix_r && *prefix_r)); }
91
* This is where \ref C_Str can help. Constructible from \c std::string and \c char*,
92
* it \e reduces the \c std::string to it's \c char*. At the same time it converts
93
* \c (char*)0 into an \c "" string.
96
* bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r )
97
* { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
103
typedef std::string::size_type size_type;
106
C_Str() : _val( 0 ), _sze( 0 ) {}
107
C_Str( char * c_str_r ) : _val( c_str_r ), _sze( std::string::npos ) {}
108
C_Str( const char * c_str_r ) : _val( c_str_r ), _sze( std::string::npos ) {}
109
C_Str( const std::string & str_r ) : _val( str_r.c_str() ), _sze( str_r.size() ) {}
112
bool isNull() const { return !_val; }
113
bool empty() const { return !(_val && *_val); }
114
size_type size() const
116
if ( _sze == std::string::npos )
117
{ _sze = _val ? ::strlen( _val ) : 0; }
121
operator const char *() const { return c_str(); }
122
const char * c_str() const { return _val ? _val : ""; }
125
const char *const _val;
126
mutable size_type _sze;
129
/** \relates C_Str Stream output */
130
inline std::ostream & operator<<( std::ostream & str, const C_Str & obj )
131
{ return str << obj.c_str(); }
133
///////////////////////////////////////////////////////////////////
134
/** String related utilities and \ref ZYPP_STR_REGEX.
135
\see \ref ZYPP_STR_REGEX
138
{ /////////////////////////////////////////////////////////////////
140
///////////////////////////////////////////////////////////////////
142
* Global asString() that works with std::string too
144
inline std::string asString( const std::string &t )
147
#ifndef SWIG // Swig treats it as syntax error
148
inline std::string asString( std::string && t )
149
{ return std::move(t); }
152
inline std::string asString( const char * t )
155
inline std::string asString( char * t )
159
inline std::string asString( const _T &t )
160
{ return t.asString(); }
163
inline std::string asString( const intrusive_ptr<_T> &p )
164
{ return p->asString(); }
167
inline std::string asString( const weak_ptr<_T> &p )
168
{ return p->asString(); }
171
inline std::string asString( const bool &t )
172
{ return t ? "+" : "-"; }
174
///////////////////////////////////////////////////////////////////
175
/** Printf style construction of std::string. */
176
std::string form( const char * format, ... )
177
__attribute__ ((format (printf, 1, 2)));
179
///////////////////////////////////////////////////////////////////
180
/** Return string describing the \a error_r code.
181
* Like ::strerror, but the numerical value is included in
182
* the string as well.
184
std::string strerror( int errno_r );
186
///////////////////////////////////////////////////////////////////
187
/** Assert \c free called for allocated <tt>char *</tt>.
191
* vasprintf( &safe._buf, format, ap );
192
* return safe.asString();
200
SafeBuf() : _buf( 0 ) {}
201
~SafeBuf() { if ( _buf ) free( _buf ); }
202
std::string asString() const
203
{ return _buf ? std::string(_buf) : std::string(); }
206
///////////////////////////////////////////////////////////////////
207
/** Convenient building of std::string via std::ostream::operator<<.
208
* Basically this is an \ref ostringstream which is autocenvertible
209
* into a \ref string.
211
* void fnc( const std::string & txt_r );
212
* fnc( str::Str() << "Hello " << 13 );
214
* std::string txt( str::Str() << 45 );
220
Str & operator<<( const _Tp & val )
221
{ _str << val; return *this; }
223
operator std::string() const
224
{ return _str.str(); }
226
std::ostream & stream()
229
std::ostringstream _str;
232
///////////////////////////////////////////////////////////////////
233
/** \name String representation of number.
235
* Optional second argument sets the minimal string width (' ' padded).
236
* Negative values will cause the number to be left adjusted within the string.
238
* Default width is 0.
240
* numstring(42) -> "42"
241
* numstring(42, 4) -> " 42"
242
* numstring(42,-4) -> "42 "
246
inline std::string numstring( char n, int w = 0 ) { return form( "%*hhd", w, n ); }
247
inline std::string numstring( unsigned char n, int w = 0 ) { return form( "%*hhu", w, n ); }
248
inline std::string numstring( short n, int w = 0 ) { return form( "%*hd", w, n ); }
249
inline std::string numstring( unsigned short n, int w = 0 ) { return form( "%*hu", w, n ); }
250
inline std::string numstring( int n, int w = 0 ) { return form( "%*d", w, n ); }
251
inline std::string numstring( unsigned n, int w = 0 ) { return form( "%*u", w, n ); }
252
inline std::string numstring( long n, int w = 0 ) { return form( "%*ld", w, n ); }
253
inline std::string numstring( unsigned long n, int w = 0 ) { return form( "%*lu", w, n ); }
254
inline std::string numstring( long long n, int w = 0 ) { return form( "%*lld", w, n ); }
255
inline std::string numstring( unsigned long long n, int w = 0 ) { return form( "%*llu", w, n ); }
257
template<> inline std::string asString( const char & t ) { return numstring( t ); }
258
template<> inline std::string asString( const unsigned char & t ) { return numstring( t ); }
259
template<> inline std::string asString( const short & t ) { return numstring( t ); }
260
template<> inline std::string asString( const unsigned short & t ) { return numstring( t ); }
261
template<> inline std::string asString( const int & t ) { return numstring( t ); }
262
template<> inline std::string asString( const unsigned & t ) { return numstring( t ); }
263
template<> inline std::string asString( const long & t ) { return numstring( t ); }
264
template<> inline std::string asString( const unsigned long & t ) { return numstring( t ); }
265
template<> inline std::string asString( const long long & t ) { return numstring( t ); }
266
template<> inline std::string asString( const unsigned long long & t ) { return numstring( t ); }
269
///////////////////////////////////////////////////////////////////
270
/** \name String representation of number as hex value with leading '0x'.
271
* Optional second argument sets the minimal
272
* string width (0 padded). Negative values will cause the number to be left adjusted
273
* within the string. Default width is 10 (4 for char).
275
* hexstring(42) -> "0x0000002a"
276
* hexstring(42, 4) -> "0x2a"
277
* hexstring(42,-4) -> "0x2a"
281
inline std::string hexstring( char n, int w = 4 ) { return form( "%#0*hhx", w, n ); }
282
inline std::string hexstring( unsigned char n, int w = 4 ) { return form( "%#0*hhx", w, n ); }
283
inline std::string hexstring( short n, int w = 10 ){ return form( "%#0*hx", w, n ); }
284
inline std::string hexstring( unsigned short n, int w = 10 ){ return form( "%#0*hx", w, n ); }
285
inline std::string hexstring( int n, int w = 10 ){ return form( "%#0*x", w, n ); }
286
inline std::string hexstring( unsigned n, int w = 10 ){ return form( "%#0*x", w, n ); }
287
inline std::string hexstring( long n, int w = 10 ){ return form( "%#0*lx", w, n ); }
288
inline std::string hexstring( unsigned long n, int w = 10 ){ return form( "%#0*lx", w, n ); }
289
inline std::string hexstring( long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
290
inline std::string hexstring( unsigned long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
293
///////////////////////////////////////////////////////////////////
294
/** \name String representation of number as octal value with leading '0'.
295
* Optional second argument sets the minimal
296
* string width (0 padded). Negative values will cause the number to be left adjusted
297
* within the string. Default width is 5 (4 for char).
299
* octstring(42) -> "00052"
300
* octstring(42, 4) -> "0052"
301
* octstring(42,-4) -> "052 "
305
inline std::string octstring( char n, int w = 4 ) { return form( "%#0*hho", w, n ); }
306
inline std::string octstring( unsigned char n, int w = 4 ) { return form( "%#0*hho", w, n ); }
307
inline std::string octstring( short n, int w = 5 ) { return form( "%#0*ho", w, n ); }
308
inline std::string octstring( unsigned short n, int w = 5 ) { return form( "%#0*ho", w, n ); }
309
inline std::string octstring( int n, int w = 5 ) { return form( "%#0*o", w, n ); }
310
inline std::string octstring( unsigned n, int w = 5 ) { return form( "%#0*o", w, n ); }
311
inline std::string octstring( long n, int w = 5 ) { return form( "%#0*lo", w, n ); }
312
inline std::string octstring( unsigned long n, int w = 5 ) { return form( "%#0*lo", w, n ); }
313
inline std::string octstring( long long n, int w = 0 ) { return form( "%#0*llo", w, n ); }
314
inline std::string octstring( unsigned long long n, int w = 0 ) { return form( "%#0*llo", w, n ); }
317
///////////////////////////////////////////////////////////////////
318
/** Parsing numbers from string.
321
/** String to integer type determined by template arg.
322
* \note Only specializations are defined.
324
* time_t t = strtonum<time_t>( "42" );
327
template<typename _It>
328
_It strtonum( const C_Str & str );
331
inline short strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
333
inline int strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
335
inline long strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); }
337
inline long long strtonum( const C_Str & str ) { return ::strtoll ( str, NULL, 0 ); }
340
inline unsigned short strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
342
inline unsigned strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
344
inline unsigned long strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); }
346
inline unsigned long long strtonum( const C_Str & str ) { return ::strtoull( str, NULL, 0 ); }
348
/** String to integer type detemined 2nd function arg \a i.
350
* time_t t; strtonum( "42", t );
353
template<typename _It>
354
inline _It strtonum( const C_Str & str, _It & i )
355
{ return i = strtonum<_It>( str ); }
358
///////////////////////////////////////////////////////////////////
359
/** Parsing boolean from string.
362
/** Return \c true if str is <tt>1, true, yes, on</tt> (or a nonzero number). */
363
bool strToTrue( const C_Str & str );
365
/** Return \c false if str is <tt>0, false, no, off</tt>. */
366
bool strToFalse( const C_Str & str );
368
/** Parse \c str into a bool depending on the default value.
369
* If the \c default is true, look for a legal \c false string.
370
* If the \c default is false, look for a legal \c true string.
372
inline bool strToBool( const C_Str & str, bool default_r )
373
{ return( default_r ? strToFalse( str ) : strToTrue( str ) ); }
375
/** Parse \c str into a bool if it's a legal \c true or \c false string.
376
* If \c str is not a recognized \c true or \c false string, \a return_r
379
inline bool strToBoolNodefault( const C_Str & str, bool & return_r )
381
if ( strToTrue( str ) ) return (return_r = true);
382
if ( !strToFalse( str ) ) return (return_r = false);
389
* \short Return a string with all occurrences of \c from_r replaced with \c to_r.
391
std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r );
393
/** \overload A function is called on demand to compute each replacement value.
395
std::string gsubFun( const std::string & str_r, const std::string & from_r, function<std::string()> to_r );
398
* \short Replace all occurrences of \c from_r with \c to_r in \c str_r (inplace).
399
* A reference to \c str_r is also returned for convenience.
401
std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r );
403
/** \overload A function is called on demand to compute each replacement value.
405
std::string & replaceAllFun( std::string & str_r, const std::string & from_r, function<std::string()> to_r );
408
///////////////////////////////////////////////////////////////////
411
/** Split \a line_r into words.
412
* Any sequence of characters in \a sepchars_r is treated as
413
* delimiter. The words are passed to OutputIterator \a result_r.
415
* std::vector<std::string> words;
416
* str::split( "some line", std::back_inserter(words) )
420
template<class _OutputIterator>
421
unsigned split( const C_Str & line_r,
422
_OutputIterator result_r,
423
const C_Str & sepchars_r = " \t" )
425
const char * beg = line_r;
426
const char * cur = beg;
427
// skip leading sepchars
428
while ( *cur && ::strchr( sepchars_r, *cur ) )
431
for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
434
while( *cur && !::strchr( sepchars_r, *cur ) )
437
*result_r = std::string( beg, cur-beg );
439
while ( *cur && ::strchr( sepchars_r, *cur ) )
445
/** Split \a line_r into words with respect to escape delimeters.
446
* Any sequence of characters in \a sepchars_r is treated as
447
* delimiter if not inside "" or "" or escaped by \, but not \\.
448
* The words are passed to OutputIterator \a result_r.
450
* \see \ref splitEscaped
453
* std::vector<std::string> words;
454
* str::splitEscaped( "some line", std::back_inserter(words) )
458
* example splitted strings
459
* normal line -> 2 elements ( "normal", "line" )
460
* escaped\ line -> 1 element( "escaped line" )
461
* "quoted line" -> 1 element same as above
462
* 'quoted line' -> 1 element same as above
463
* "escaped quote\'" -> 1 element ( "escaped quote'" )
465
* \param line_r The string to parse.
467
* \param sepchars_r String of separator characters.
468
* \param withEmpty Whether to include empty fields between separators in the result.
472
template<class _OutputIterator>
473
unsigned splitEscaped( const C_Str & line_r,
474
_OutputIterator result_r,
475
const C_Str & sepchars_r = " \t",
476
bool withEmpty = false)
478
const char * beg = line_r;
479
const char * cur = beg;
482
// skip leading sepchars
483
while ( *cur && ::strchr( sepchars_r, *cur ) )
493
// there were only sepchars in the string
494
if (!*cur && withEmpty)
500
// after the leading sepchars
501
for ( beg = cur; *beg; beg = cur, ++result_r, ++ret )
503
if ( *cur == '"' || *cur == '\'' )
505
char closeChar = *cur;
510
while ( *cur && *cur != closeChar)
514
return ret; //TODO parsing exception no closing quote
517
const char * esc = cur-1;
518
while ( esc != beg && *esc == '\\' )
523
cont = (escCount % 2 == 1); // find some non escaped escape char
527
std::string s( beg+1, cur-beg-2 ); //without quotes
528
//transform escaped escape
529
replaceAll( s, "\\\\", "\\" );
530
//transform escaped quotes (only same as open
531
char tmpn[2] = { closeChar, 0 };
532
char tmpo[3] = { '\\', closeChar, 0 };
533
replaceAll( s, tmpo, tmpn );
540
while( *cur && !::strchr( sepchars_r, *cur ) )
542
//ignore char after backslash
550
std::string s( beg, cur-beg );
551
//transform escaped escape
552
replaceAll( s, "\\\\", "\\" );
554
const char *delimeter = sepchars_r;
557
std::string ds("\\");
558
const char tmp[2] = { *delimeter, '\0' };
559
std::string del(tmp);
561
replaceAll( s, ds, del );
568
if ( *cur && ::strchr( sepchars_r, *cur ) )
570
while ( *cur && ::strchr( sepchars_r, *cur ) )
579
// the last was a separator => one more field
580
if ( !*cur && withEmpty && ::strchr( sepchars_r, *(cur-1) ) )
589
/** Split \a line_r into fields.
590
* Any single character in \a sepchars_r is treated as a
591
* field separator. The words are passed to OutputIterator
597
* ":a" -> words 2 ||a|
598
* "a:" -> words 2 |a||
599
* ":a:" -> words 3 ||a||
604
* std::vector<std::string> words;
605
* str::split( "some line", std::back_inserter(words) )
609
template<class _OutputIterator>
610
unsigned splitFields( const C_Str & line_r,
611
_OutputIterator result_r,
612
const C_Str & sepchars_r = ":" )
614
const char * beg = line_r;
615
const char * cur = beg;
617
for ( beg = cur; *beg; beg = cur, ++result_r )
620
while( *cur && !::strchr( sepchars_r, *cur ) )
623
*result_r = std::string( beg, cur-beg );
629
if ( ! *cur ) // ending with sepchar
631
*result_r = std::string(); // add final empty field
641
* Split \a line_r into fields handling also escaped separators.
644
* \see splitEscaped()
646
template<class _OutputIterator>
647
unsigned splitFieldsEscaped( const C_Str & line_r,
648
_OutputIterator result_r,
649
const C_Str & sepchars_r = ":" )
652
splitEscaped( line_r, result_r, sepchars_r, true /* withEmpty */ );
657
///////////////////////////////////////////////////////////////////
660
/** Join strings using separator \a sep_r (defaults to BLANK). */
661
template <class _Iterator>
662
std::string join( _Iterator begin, _Iterator end,
663
const C_Str & sep_r = " " )
666
for ( _Iterator iter = begin; iter != end; ++ iter )
670
res += asString(*iter);
675
/** Join strings using separator \a sep_r (defaults to BLANK). */
676
template <class _Container>
677
std::string join( const _Container & cont_r,
678
const C_Str & sep_r = " " )
679
{ return join( cont_r.begin(), cont_r.end(), sep_r ); }
681
/** Join strings using separator \a sep_r, quoting or escaping the values.
682
* Separator defaults to BLANK. Use \ref splitEscaped to restore the
685
template <class _Iterator>
686
std::string joinEscaped( _Iterator begin, _Iterator end,
687
const char sep_r = ' ' )
689
std::vector<char> buf;
690
for ( _Iterator iter = begin; iter != end; ++ iter )
693
buf.push_back( sep_r );
697
// empty string goes ""
698
buf.push_back( '"' );
699
buf.push_back( '"' );
703
std::string toadd( asString(*iter) );
704
for_( ch, toadd.begin(), toadd.end() )
711
buf.push_back( '\\' );
712
buf.push_back( *ch );
716
buf.push_back( '\\' );
717
buf.push_back( *ch );
722
return std::string( buf.begin(), buf.end() );
727
///////////////////////////////////////////////////////////////////
731
* Escape desired character \a c using a backslash.
733
* For use when printing \a c separated values, and where
734
* \ref joinEscaped() is too heavy.
736
std::string escape( const C_Str & str_r, const char c = ' ' );
738
/** Escape \a next_r and append it to \a str_r using separator \a sep_r. */
739
inline void appendEscaped( std::string & str_r, const C_Str & next_r, const char sep_r = ' ' )
741
if ( ! str_r.empty() )
743
if ( next_r.empty() )
746
str_r += escape( next_r, sep_r );
752
///////////////////////////////////////////////////////////////////
753
///////////////////////////////////////////////////////////////////
755
* Encode all characters other than [a-zA-Z0-9] as %XX.
756
* This includes the % character itself, which becomes %25.
759
/** Encode all characters other than [a-zA-Z0-9] as %XX.
760
* This includes the % character itself, which becomes %25.
762
std::string hexencode( const C_Str & str_r );
763
/** Decode hexencoded %XX sequences. */
764
std::string hexdecode( const C_Str & str_r );
766
///////////////////////////////////////////////////////////////////
768
/** \name Case conversion. */
770
/** Return lowercase version of \a s
773
std::string toLower( const std::string & s );
775
inline std::string toLower( const char * s )
776
{ return( s ? toLower( std::string(s) ) : std::string() ); }
778
/** Return uppercase version of \a s
781
std::string toUpper( const std::string & s );
783
inline std::string toUpper( const char * s )
784
{ return( s ? toUpper( std::string(s) ) : std::string() ); }
788
/** \name Case insensitive comparison. */
790
inline int compareCI( const C_Str & lhs, const C_Str & rhs )
791
{ return ::strcasecmp( lhs, rhs ); }
794
/** \name Locate substring. */
796
/** Locate substring case sensitive. */
797
inline bool contains( const C_Str & str_r, const C_Str & val_r )
798
{ return ::strstr( str_r, val_r ); }
799
/** Locate substring case insensitive. */
800
inline bool containsCI( const C_Str & str_r, const C_Str & val_r )
801
{ return ::strcasestr( str_r, val_r ); }
804
///////////////////////////////////////////////////////////////////
805
/** \name Trimming whitepace.
806
* \todo optimize l/r trim.
809
/** To define how to trim. */
814
TRIM = (L_TRIM|R_TRIM)
817
std::string trim( const std::string & s, const Trim trim_r = TRIM );
819
inline std::string ltrim( const std::string & s )
820
{ return trim( s, L_TRIM ); }
822
inline std::string rtrim( const std::string & s )
823
{ return trim( s, R_TRIM ); }
826
std::string stripFirstWord( std::string & line, const bool ltrim_first );
828
std::string stripLastWord( std::string & line, const bool rtrim_first );
830
/** Return stream content up to (but not returning) the next newline.
831
* \see \ref receiveUpTo
833
std::string getline( std::istream & str, bool trim = false );
835
/** Return stream content up to (but not returning) the next newline.
836
* \see \ref receiveUpTo
838
std::string getline( std::istream & str, const Trim trim_r );
840
/** Return stream content up to the next ocurrence of \c delim_r or EOF
841
* \c delim_r, if found, is always read from the stream. Whether it is
842
* also returned in the string depends on \c returnDelim_r.
843
* If the stream status is \c good, \c delim_r was found in the stream.
844
* If we reached EOF while looking for \c delim_r, \c eof is set; and
845
* also \c fail, if we did not read any data before.
847
std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r = false );
849
///////////////////////////////////////////////////////////////////
851
/** \name String prefix/suffix handling.
854
/** Return whether \a str_r has prefix \a prefix_r. */
855
inline bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r )
856
{ return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
858
/** Strip a \a prefix_r from \a str_r and return the resulting string. */
859
inline std::string stripPrefix( const C_Str & str_r, const C_Str & prefix_r )
860
{ return( hasPrefix( str_r, prefix_r ) ? str_r + prefix_r.size() : str_r.c_str() ); }
862
/** Return whether \a str_r has suffix \a suffix_r. */
863
inline bool hasSuffix( const C_Str & str_r, const C_Str & suffix_r )
864
{ return( str_r.size() >= suffix_r.size() && ::strncmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); }
866
/** Strip a \a suffix_r from \a str_r and return the resulting string. */
867
inline std::string stripSuffix( const C_Str & str_r, const C_Str & suffix_r )
869
if ( hasSuffix( str_r, suffix_r ) )
870
return std::string( str_r, str_r.size() - suffix_r.size() );
871
return str_r.c_str();
873
/** Return size of the common prefix of \a lhs and \a rhs. */
874
inline std::string::size_type commonPrefix( const C_Str & lhs, const C_Str & rhs )
876
const char * lp = lhs.c_str();
877
const char * rp = rhs.c_str();
878
std::string::size_type ret = 0;
879
while ( *lp == *rp && *lp != '\0' )
880
{ ++lp, ++rp, ++ret; }
884
/** alias for \ref hasPrefix */
885
inline bool startsWith( const C_Str & str_r, const C_Str & prefix_r )
886
{ return hasPrefix( str_r, prefix_r ); }
887
/** alias for \ref hasSuffix */
888
inline bool endsWith( const C_Str & str_r, const C_Str & prefix_r )
889
{ return hasSuffix( str_r, prefix_r ); }
891
/////////////////////////////////////////////////////////////////
893
///////////////////////////////////////////////////////////////////
894
/////////////////////////////////////////////////////////////////
896
///////////////////////////////////////////////////////////////////
897
#endif // ZYPP_BASE_STRING_H