Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / base / String.h
index acff23a..285c7dd 100644 (file)
@@ -19,6 +19,7 @@
 #include <string>
 #include <sstream>
 #include <boost/format.hpp>
+#include <boost/utility/string_ref.hpp>
 
 #include "zypp/base/Easy.h"
 #include "zypp/base/PtrTypes.h"
@@ -32,11 +33,11 @@ namespace zypp { typedef boost::logic::tribool TriBool; }
 ///////////////////////////////////////////////////////////////////
 namespace zypp
 {
-  /** Request a human readable (translated) string representation of _Tp [_Tp.asUserString()]
+  /** Request a human readable (translated) string representation of Tp [Tp.asUserString()]
    * Classes may implement a default as member function.
    */
-  template <class _Tp>
-  std::string asUserString( const _Tp & val_r )
+  template <class Tp>
+  std::string asUserString( const Tp & val_r )
   { return val_r.asUserString(); }
 
 }// namespace zypp
@@ -46,16 +47,6 @@ namespace zypp
 namespace zypp
 { /////////////////////////////////////////////////////////////////
 
-  struct MessageString : public std::string
-  {
-    MessageString() {}
-    MessageString( const char * str_r )                : std::string( str_r ? str_r : "" ) {}
-    MessageString( const std::string & str_r )         : std::string( str_r ) {}
-    // boost::format, std::ostringstream, str::Str ...
-    template<class _Str>
-    MessageString( const _Str & str_r )        : std::string( str_r.str() ) {}
-  };
-
   /** Convenience \c char* constructible from \c std::string and \c char*,
    *  it maps \c (char*)0 to an empty string.
    *
@@ -93,6 +84,8 @@ namespace zypp
    * bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r )
    * { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
    * \endcode
+   *
+   * \todo Check whether to replace by boost::string_ref
    */
   class C_Str
   {
@@ -104,6 +97,7 @@ namespace zypp
       C_Str( char * c_str_r )            : _val( c_str_r ),       _sze( std::string::npos ) {}
       C_Str( const char * c_str_r )      : _val( c_str_r ),       _sze( std::string::npos ) {}
       C_Str( const std::string & str_r ) : _val( str_r.c_str() ), _sze( str_r.size() ) {}
+      C_Str( const boost::string_ref & str_r ) : _val( str_r.data() ), _sze( str_r.size() ) {}
 
     public:
       bool      isNull()       const { return !_val; }
@@ -139,11 +133,11 @@ namespace zypp
     /**
      * Global asString() that works with std::string too
      */
-    inline std::string asString( const std::string &t )
+    inline const std::string & asString( const std::string & t )
     { return t; }
 
 #ifndef SWIG // Swig treats it as syntax error
-    inline std::string asString( std::string && t )
+    inline std::string && asString( std::string && t )
     { return std::move(t); }
 #endif
 
@@ -153,16 +147,16 @@ namespace zypp
     inline std::string asString( char * t )
     { return t; }
 
-    template<class _T>
-        inline std::string asString( const _T &t )
+    template<class Tp>
+        inline std::string asString( const Tp &t )
         { return t.asString(); }
 
-    template<class _T>
-        inline std::string asString( const intrusive_ptr<_T> &p )
+    template<class Tp>
+        inline std::string asString( const intrusive_ptr<Tp> &p )
         { return p->asString(); }
 
-    template<class _T>
-        inline std::string asString( const weak_ptr<_T> &p )
+    template<class Tp>
+        inline std::string asString( const weak_ptr<Tp> &p )
         { return p->asString(); }
 
     template<>
@@ -216,8 +210,8 @@ namespace zypp
     struct Str
     {
       template<class Tp>
-      Str & operator<<( const Tp & val )
-      { _str << val; return *this; }
+      Str & operator<<( Tp && val )
+      { _str << std::forward<Tp>(val); return *this; }
 
       Str & operator<<( std::ostream& (*iomanip)( std::ostream& ) )
       { _str << iomanip; return *this; }
@@ -379,6 +373,20 @@ namespace zypp
     inline std::string octstring( unsigned long long n, int w = 0 ) { return form( "%#0*llo",  w, n ); }
     //@}
 
+
+    ///////////////////////////////////////////////////////////////////
+    /** String representation of number as bit-string with leading '0's. */
+    template <typename TInt>
+    std::string binstring( TInt val_r )
+    {
+      constexpr unsigned bits = sizeof(TInt)*8;
+      std::string ret( bits, ' ' );
+      TInt bit = 1;
+      for ( unsigned pos = bits; pos > 0; )
+      { --pos; ret[pos] = ((val_r & bit)?'1':'0'); bit = bit<<1; }
+      return ret;
+    }
+    
     ///////////////////////////////////////////////////////////////////
     /** Parsing numbers from string.
     */
@@ -389,8 +397,8 @@ namespace zypp
      * time_t t = strtonum<time_t>( "42" );
      * \endcode
     */
-    template<typename _It>
-      _It strtonum( const C_Str & str );
+    template<typename TInt>
+      TInt strtonum( const C_Str & str );
 
     template<>
       inline short              strtonum( const C_Str & str ) { return ::strtol  ( str, NULL, 0 ); }
@@ -415,9 +423,9 @@ namespace zypp
      * time_t t; strtonum( "42", t );
      * \endcode
     */
-    template<typename _It>
-      inline _It strtonum( const C_Str & str, _It & i )
-      { return i = strtonum<_It>( str ); }
+    template<typename TInt>
+      inline TInt strtonum( const C_Str & str, TInt & i )
+      { return i = strtonum<TInt>( str ); }
     //@}
 
     ///////////////////////////////////////////////////////////////////
@@ -507,10 +515,8 @@ namespace zypp
      * \endcode
      *
     */
-    template<class _OutputIterator>
-      unsigned split( const C_Str &   line_r,
-                      _OutputIterator result_r,
-                      const C_Str &   sepchars_r = " \t" )
+    template<class TOutputIterator>
+      unsigned split( const C_Str & line_r, TOutputIterator result_r, const C_Str & sepchars_r = " \t" )
       {
         const char * beg = line_r;
         const char * cur = beg;
@@ -568,11 +574,8 @@ namespace zypp
      *
      * \endcode
      */
-    template<class _OutputIterator>
-      unsigned splitEscaped( const C_Str &   line_r,
-                      _OutputIterator result_r,
-                      const C_Str &   sepchars_r = " \t",
-                      bool withEmpty = false)
+    template<class TOutputIterator>
+      unsigned splitEscaped( const C_Str & line_r, TOutputIterator result_r, const C_Str & sepchars_r = " \t", bool withEmpty = false)
       {
         const char * beg = line_r;
         const char * cur = beg;
@@ -701,10 +704,8 @@ namespace zypp
      * \endcode
      *
     */
-    template<class _OutputIterator>
-      unsigned splitFields( const C_Str &   line_r,
-                            _OutputIterator result_r,
-                            const C_Str &   sepchars_r = ":" )
+    template<class TOutputIterator>
+      unsigned splitFields( const C_Str & line_r, TOutputIterator result_r, const C_Str & sepchars_r = ":" )
       {
         const char * beg = line_r;
         const char * cur = beg;
@@ -742,13 +743,10 @@ namespace zypp
      * \see splitFields()
      * \see splitEscaped()
      */
-    template<class _OutputIterator>
-      unsigned splitFieldsEscaped( const C_Str &   line_r,
-                            _OutputIterator result_r,
-                            const C_Str &   sepchars_r = ":" )
+    template<class TOutputIterator>
+      unsigned splitFieldsEscaped( const C_Str & line_r, TOutputIterator result_r, const C_Str & sepchars_r = ":" )
       {
-        return
-          splitEscaped( line_r, result_r, sepchars_r, true /* withEmpty */ );
+        return splitEscaped( line_r, result_r, sepchars_r, true /* withEmpty */ );
       }
 
     //@}
@@ -757,12 +755,11 @@ namespace zypp
     /** \name Join. */
     //@{
     /** Join strings using separator \a sep_r (defaults to BLANK). */
-    template <class _Iterator>
-      std::string join( _Iterator begin, _Iterator end,
-                        const C_Str & sep_r = " " )
+    template <class TIterator>
+      std::string join( TIterator begin, TIterator end, const C_Str & sep_r = " " )
       {
         std::string res;
-        for ( _Iterator iter = begin; iter != end; ++ iter )
+        for ( TIterator iter = begin; iter != end; ++ iter )
           {
             if ( iter != begin )
               res += sep_r;
@@ -772,21 +769,19 @@ namespace zypp
       }
 
     /** Join strings using separator \a sep_r (defaults to BLANK). */
-    template <class _Container>
-      std::string join( const _Container & cont_r,
-                        const C_Str & sep_r = " " )
+    template <class TContainer>
+      std::string join( const TContainer & cont_r, const C_Str & sep_r = " " )
       { return join( cont_r.begin(), cont_r.end(), sep_r ); }
 
     /** Join strings using separator \a sep_r, quoting or escaping the values.
      * Separator defaults to BLANK. Use \ref splitEscaped to restore the
      * values.
      */
-    template <class _Iterator>
-      std::string joinEscaped( _Iterator begin, _Iterator end,
-                               const char sep_r = ' ' )
+    template <class TIterator>
+      std::string joinEscaped( TIterator begin, TIterator end, const char sep_r = ' ' )
       {
         std::vector<char> buf;
-        for ( _Iterator iter = begin; iter != end; ++ iter )
+        for ( TIterator iter = begin; iter != end; ++ iter )
         {
           if ( iter != begin )
             buf.push_back( sep_r );
@@ -942,6 +937,7 @@ namespace zypp
      * \todo improve
     */
     std::string toLower( const std::string & s );
+    std::string toLower( std::string && s );
     /** \overload */
     inline std::string toLower( const char * s )
     { return( s ? toLower( std::string(s) ) : std::string() ); }
@@ -950,6 +946,7 @@ namespace zypp
      * \todo improve
     */
     std::string toUpper( const std::string & s );
+    std::string toUpper( std::string && s );
     /** \overload */
     inline std::string toUpper( const char * s )
     { return( s ? toUpper( std::string(s) ) : std::string() ); }
@@ -986,12 +983,17 @@ namespace zypp
     };
 
     std::string trim( const std::string & s, const Trim trim_r = TRIM );
+    std::string trim( std::string && s, const Trim trim_r = TRIM );
 
     inline std::string ltrim( const std::string & s )
     { return trim( s, L_TRIM ); }
+    inline std::string ltrim( std::string && s )
+    { return trim( std::move(s), L_TRIM ); }
 
     inline std::string rtrim( const std::string & s )
     { return trim( s, R_TRIM ); }
+    inline std::string rtrim( std::string && s )
+    { return trim( std::move(s), R_TRIM ); }
     //@}
 
     std::string stripFirstWord( std::string & line, const bool ltrim_first = true );
@@ -1025,14 +1027,23 @@ namespace zypp
     /** Return whether \a str_r has prefix \a prefix_r. */
     inline bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r )
     { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
+    /** \overload Case insensitive */
+    inline bool hasPrefixCI( const C_Str & str_r, const C_Str & prefix_r )
+    { return( ::strncasecmp( str_r, prefix_r, prefix_r.size() ) == 0 ); }
 
     /** Strip a \a prefix_r from \a str_r and return the resulting string. */
     inline std::string stripPrefix( const C_Str & str_r, const C_Str & prefix_r )
     { return( hasPrefix( str_r, prefix_r ) ? str_r + prefix_r.size() : str_r.c_str() ); }
+    /** \overload Case insensitive */
+    inline std::string stripPrefixCI( const C_Str & str_r, const C_Str & prefix_r )
+    { return( hasPrefixCI( str_r, prefix_r ) ? str_r + prefix_r.size() : str_r.c_str() ); }
 
     /** Return whether \a str_r has suffix \a suffix_r. */
     inline bool hasSuffix( const C_Str & str_r, const C_Str & suffix_r )
     { return( str_r.size() >= suffix_r.size() && ::strncmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); }
+    /** \overload Case insensitive */
+    inline bool hasSuffixCI( const C_Str & str_r, const C_Str & suffix_r )
+    { return( str_r.size() >= suffix_r.size() && ::strncasecmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); }
 
     /** Strip a \a suffix_r from \a str_r and return the resulting string. */
     inline std::string stripSuffix( const C_Str & str_r, const C_Str & suffix_r )
@@ -1041,6 +1052,14 @@ namespace zypp
         return std::string( str_r, str_r.size() - suffix_r.size() );
       return str_r.c_str();
     }
+    /** \overload Case insensitive */
+    inline std::string stripSuffixCI( const C_Str & str_r, const C_Str & suffix_r )
+    {
+      if ( hasSuffixCI( str_r, suffix_r ) )
+        return std::string( str_r, str_r.size() - suffix_r.size() );
+      return str_r.c_str();
+    }
+
     /** Return size of the common prefix of \a lhs and \a rhs. */
     inline std::string::size_type commonPrefix( const C_Str & lhs, const C_Str & rhs )
     {
@@ -1051,13 +1070,31 @@ namespace zypp
       { ++lp, ++rp, ++ret; }
       return ret;
     }
+    /** \overload Case insensitive */
+    inline std::string::size_type commonPrefixCI( const C_Str & lhs, const C_Str & rhs )
+    {
+      const char * lp = lhs.c_str();
+      const char * rp = rhs.c_str();
+      std::string::size_type ret = 0;
+      while ( tolower(*lp) == tolower(*rp) && *lp != '\0' )
+      { ++lp, ++rp, ++ret; }
+      return ret;
+    }
+
 
     /** alias for \ref hasPrefix */
     inline bool startsWith( const C_Str & str_r, const C_Str & prefix_r )
     { return hasPrefix( str_r, prefix_r ); }
+    /** \overload Case insensitive */
+    inline bool startsWithCI( const C_Str & str_r, const C_Str & prefix_r )
+    { return hasPrefixCI( str_r, prefix_r ); }
+
     /** alias for \ref hasSuffix */
     inline bool endsWith( const C_Str & str_r, const C_Str & prefix_r )
     { return hasSuffix( str_r, prefix_r ); }
+    /** \overload Case insensitive */
+    inline bool endsWithCI( const C_Str & str_r, const C_Str & prefix_r )
+    { return hasSuffixCI( str_r, prefix_r ); }
     //@}
   } // namespace str
   ///////////////////////////////////////////////////////////////////