Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / zypp / base / String.cc
index 55fb39c..fb7bd35 100644 (file)
@@ -15,6 +15,9 @@
 #include <iostream>
 
 #include "zypp/base/String.h"
+#include "zypp/base/LogTools.h"
+
+#include "zypp/TriBool.h"
 
 using std::string;
 
@@ -64,6 +67,7 @@ namespace zypp
               || t == "yes"
               || t == "true"
               || t == "on"
+              || t == "+"
               || strtonum<long long>( str )
             );
     }
@@ -80,9 +84,89 @@ namespace zypp
                  || t == "no"
                  || t == "false"
                  || t == "off"
+                 || t == "-"
                );
     }
 
+    TriBool strToTriBool( const C_Str & str )  // from TriBool.h
+    {
+      if ( strToTrue( str ) )  return true;
+      if ( !strToFalse( str ) )        return false;
+      return indeterminate;
+    }
+
+    ///////////////////////////////////////////////////////////////////
+    // Hexencode
+    ///////////////////////////////////////////////////////////////////
+    namespace {
+      /** What's not decoded. */
+      inline bool heIsAlNum( char ch )
+      {
+        return ( ( 'a' <= ch && ch <= 'z' )
+               ||( 'A' <= ch && ch <= 'Z' )
+               ||( '0' <= ch && ch <= '9' ) );
+      }
+      /** Hex-digit to number or -1. */
+      inline int heDecodeCh( char ch )
+      {
+        if ( '0' <= ch && ch <= '9' )
+          return( ch - '0' );
+        if ( 'A' <= ch && ch <= 'F' )
+          return( ch - 'A' + 10 );
+        if ( 'a' <= ch && ch <= 'f' )
+          return( ch - 'a' + 10 );
+        return -1;
+      }
+    }
+
+    std::string hexencode( const C_Str & str_r )
+    {
+      static const char *const hdig = "0123456789ABCDEF";
+      std::string res;
+      res.reserve( str_r.size() );
+      for ( const char * it = str_r.c_str(); *it; ++it )
+      {
+        if ( heIsAlNum( *it ) )
+        {
+          res += *it;
+        }
+        else
+        {
+          res += '%';
+          res += hdig[(unsigned char)(*it)/16];
+          res += hdig[(unsigned char)(*it)%16];
+        }
+      }
+      return res;
+    }
+
+    std::string hexdecode( const C_Str & str_r )
+    {
+      std::string res;
+      res.reserve( str_r.size() );
+      for_( it, str_r.c_str(), str_r.c_str()+str_r.size() )
+      {
+        if ( *it == '%' )
+        {
+          int d1 = heDecodeCh( *(it+1) );
+          if ( d1 != -1 )
+          {
+            int d2 = heDecodeCh( *(it+2) );
+            if ( d2 != -1 )
+            {
+              res += (d1<<4)|d2;
+              it += 2;
+              continue;
+            }
+          }
+        }
+        // verbatim if no %XX:
+        res += *it;
+      }
+      return res;
+    }
+    ///////////////////////////////////////////////////////////////////
+
     /******************************************************************
      **
      **      FUNCTION NAME : toLower
@@ -220,52 +304,57 @@ namespace zypp
       return ret;
     }
 
-    string gsub(const string& sData, const string& sFrom, const string& sTo)
+    std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r )
     {
-      string sNew;
-      sNew.reserve(sData.size());
+      std::string ret( str_r );
+      return replaceAll( ret, from_r, to_r );
+    }
 
-      if (! sData.empty())
+    std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r )
+    {
+      if ( ! from_r.empty() )
       {
-        string::size_type frLen = sFrom.length();
-        string::size_type loc = 0;
-        string::size_type oldLoc = 0;
-
-        while (string::npos != (loc = sData.find(sFrom, loc)))
-        {
-          sNew.append(sData,oldLoc,loc-oldLoc);
-          sNew.append(sTo);
-          loc += frLen;
-          oldLoc = loc;
-          if (loc >= sData.length())
-            break;
-        }
-        if (oldLoc!=sData.size())
-            sNew.append(sData,oldLoc,sData.size()-oldLoc);
+       std::string::size_type pos = 0;
+       while ( (pos = str_r.find( from_r, pos )) != std::string::npos )
+       {
+         str_r.replace( pos, from_r.size(), to_r );
+         pos += to_r.size();
+
+         if ( pos >= str_r.length() )
+           break;
+       }
       }
+      return str_r;
+    }
 
-      return sNew;
+    std::string gsubFun( const std::string & str_r, const std::string & from_r, function<std::string()> to_r )
+    {
+      std::string ret( str_r );
+      return replaceAllFun( ret, from_r, to_r );
     }
 
-    string & replaceAll(string & str, const string & from, const string & to)
+    std::string & replaceAllFun( std::string & str_r, const std::string & from_r, function<std::string()> to_r )
     {
-      string::size_type pos = 0;
-      while((pos = str.find(from, pos)) != string::npos)
+      if ( ! from_r.empty() )
       {
-        str.replace(pos, from.size(), to);
-        pos += to.size();
-
-        if (pos >= str.length())
-          break;
+       std::string::size_type pos = 0;
+       while ( (pos = str_r.find( from_r, pos )) != std::string::npos )
+       {
+         std::string to( to_r() );
+         str_r.replace( pos, from_r.size(), to );
+         pos += to.size();
+
+         if ( pos >= str_r.length() )
+           break;
+       }
       }
-      return str;
+      return str_r;
     }
 
-
-    std::string escape( const std::string & str_r, const char sep_r )
+    std::string escape( const C_Str & str_r, const char sep_r )
     {
       std::vector<char> buf;
-      for_( s, str_r.begin(), str_r.end() )
+      for_( s, str_r.c_str(), s+str_r.size() )
       {
         switch ( *s )
         {
@@ -284,38 +373,43 @@ namespace zypp
       return std::string( buf.begin(), buf.end() );
     }
 
-
-    /******************************************************************
-    **
-    **
-    **      FUNCTION NAME : getline
-    **      FUNCTION TYPE : std::string
-    **
-    **      DESCRIPTION :
-    */
-    static inline std::string _getline( std::istream & str, const Trim trim_r )
+    std::string getline( std::istream & str, const Trim trim_r )
     {
-      const unsigned tmpBuffLen = 1024;
-      char           tmpBuff[tmpBuffLen];
-
-      std::string ret;
-      do {
-        str.clear();
-        str.getline( tmpBuff, tmpBuffLen ); // always writes '\0' terminated
-        ret += tmpBuff;
-      } while( str.rdstate() == std::ios::failbit );
-
-      return trim( ret, trim_r );
+      return trim( receiveUpTo( str, '\n' ), trim_r );
     }
 
-    std::string getline( std::istream & str, const Trim trim_r )
+    std::string getline( std::istream & str, bool trim_r )
     {
-      return _getline(str, trim_r);
+      return trim( receiveUpTo( str, '\n' ), trim_r?TRIM:NO_TRIM );
     }
 
-    std::string getline( std::istream & str, bool trim )
+    std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r )
     {
-      return _getline(str, trim?TRIM:NO_TRIM);
+      std::ostringstream datas;
+      do {
+       char ch;
+       if ( str.get( ch ) )
+       {
+         if ( ch != delim_r )
+         {
+           datas.put( ch );
+         }
+         else
+         {
+           if ( returnDelim_r )
+             datas.put( ch );
+           break;      // --> delimiter found
+         }
+       }
+       else
+       {
+         // clear fail bit if we read data before reaching EOF
+         if ( str.eof() && datas.tellp() )
+           str.clear( std::ios::eofbit );
+         break;        // --> no consumable data.
+       }
+      } while ( true );
+      return datas.str();
     }
 
     /////////////////////////////////////////////////////////////////