Fix RepoVariables*Replacer to compute substitution values on demand only
authorMichael Andres <ma@suse.de>
Tue, 18 Oct 2011 09:25:03 +0000 (11:25 +0200)
committerMichael Andres <ma@suse.de>
Tue, 18 Oct 2011 14:47:19 +0000 (16:47 +0200)
zypp/base/String.h
zypp/repo/RepoVariables.cc
zypp/repo/RepoVariables.h

index 8de02b3b2bfcd18ada95cd6d2b8e1ad6fae5242c..67ab68f1cf1e6481a85bc50835ae901ea165bb7a 100644 (file)
@@ -343,26 +343,21 @@ namespace zypp
     //@}
 
     /**
-     * \short Looks for text in a string and replaces it.
-     *
-     * \note It only perform substtution in one pass
+     * \short Return a string with all occurrences of \c from_r replaced with \c to_r.
      */
     std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r );
 
-    /** \overload
-     * On each replacement a function is called to get the value to replace.
+    /** \overload A function is called on demand to compute each replacement value.
      */
     std::string gsubFun( const std::string & str_r, const std::string & from_r, function<std::string()> to_r );
 
     /**
-     * \short Looks for text in string and replaces it in place
-     *
-     * \note It only perform substtution in one pass
+     * \short Replace all occurrences of \c from_r with \c to_r in \c str_r (inplace).
+     * A reference to \c str_r is also returned for convenience.
      */
     std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r );
 
-    /** \overload
-     * On each replacement a function is called to get the value to replaces.
+    /** \overload A function is called on demand to compute each replacement value.
      */
     std::string & replaceAllFun( std::string & str_r, const std::string & from_r, function<std::string()> to_r );
 
index 83ec70b02eea92d54e01954eec3033e17d9c3c01..9fe4eefbaa7606ec118c3fd243aee390b039ed85 100644 (file)
@@ -7,95 +7,95 @@
 |                                                                      |
 \---------------------------------------------------------------------*/
 
-#include <iostream>
-#include <map>
-#include <algorithm>
+#include "zypp/base/LogTools.h"
 #include "zypp/base/String.h"
-#include "zypp/repo/RepoException.h"
-#include "zypp/ZConfig.h"
-#include "zypp/ZYppFactory.h"
-#include "RepoVariables.h"
 
-using namespace std;
+#include "zypp/ZConfig.h"
+#include "zypp/Target.h"
+#include "zypp/Arch.h"
+#include "zypp/repo/RepoVariables.h"
+#include "zypp/base/NonCopyable.h"
 
+///////////////////////////////////////////////////////////////////
 namespace zypp
 {
-namespace repo
-{
-
-RepoVariablesStringReplacer::RepoVariablesStringReplacer()
-{
-  sysarch = Arch_empty;
-  basearch = Arch_empty;
-}
-
-RepoVariablesStringReplacer::~RepoVariablesStringReplacer()
-{}
-
-void RepoVariablesStringReplacer::resetVarCache( void )
-{
-  sysarch = Arch_empty;
-  basearch = Arch_empty;
-  releasever = "";
-}
-
-std::string RepoVariablesStringReplacer::operator()( const std::string &value ) const
-{
-  string newvalue(value);
-
-  // $arch
-  if( sysarch.empty() )
-    sysarch = ZConfig::instance().systemArchitecture();
-
-  newvalue = str::gsub( newvalue, "$arch", sysarch.asString() );
-
-  // $basearch
-  if( basearch.empty() )
-    basearch = sysarch.baseArch();
-
-  newvalue = str::gsub( newvalue, "$basearch", basearch.asString() );
-
-  // $releasever (Target::distributionVersion assumes root=/ if target not initialized)
-  if ( newvalue.find("$releasever") != string::npos ) {
-    if( releasever.empty() )
-      releasever = Target::distributionVersion(Pathname()/*guess*/);
-
-    newvalue = str::gsub( newvalue, "$releasever", releasever );
-  } 
-
-  return newvalue;
-}
-
-//////////////////////////////////////////////////////////////////////
-
-RepoVariablesUrlReplacer::RepoVariablesUrlReplacer()
-{}
-
-RepoVariablesUrlReplacer::~RepoVariablesUrlReplacer()
-{}
-
-void RepoVariablesUrlReplacer::resetVarCache( void )
-{
-  replacer.resetVarCache();
-}
-
-/*
- * Replaces '$arch' and '$basearch' in the path and query part of the URL
- * with the global ZYpp values. Examples:
- *
- * ftp://user:secret@site.net/$arch/ -> ftp://user:secret@site.net/i686/
- * http://site.net/?basearch=$basearch -> http://site.net/?basearch=i386
- */
-Url RepoVariablesUrlReplacer::operator()( const Url &value ) const
-{
-  Url newurl = value;
-  newurl.setPathData(replacer(value.getPathData()));
-  newurl.setQueryString(replacer(value.getQueryString()));
-
-  return newurl;
-}
-
-} // ns repo
-} // ns zypp
-
-// vim: set ts=2 sts=2 sw=2 et ai:
+  ///////////////////////////////////////////////////////////////////
+  namespace repo
+  {
+    ///////////////////////////////////////////////////////////////////
+    namespace
+    {
+      /** \brief Provide lazy initialized repo variables
+       */
+      struct ReplacerData : private zypp::base::NonCopyable
+      {
+       const std::string & sysarch() const
+       {
+         if ( _sysarch.empty() )
+           initArchStr();
+         return _sysarch;
+       }
+
+       const std::string & basearch() const
+       {
+         if ( _basearch.empty() )
+           initArchStr();
+         return _basearch;
+       }
+
+       const std::string & releasever() const
+       {
+         if( _releasever.empty() )
+           _releasever = Target::distributionVersion( Pathname()/*guess*/ );
+         return _releasever;
+       }
+
+      private:
+       void initArchStr() const
+       {
+         Arch arch( ZConfig::instance().systemArchitecture() );
+         _sysarch = arch.asString();
+         _basearch = arch.baseArch().asString();
+       }
+      private:
+       mutable std::string _sysarch;
+       mutable std::string _basearch;
+       mutable std::string _releasever;
+      };
+
+      /** \brief Replace repo variables on demand
+       *
+       * Initialisation of repo variables is delayed until they actually occur in
+       * a string.
+       */
+      std::string replacer( const std::string & value_r )
+      {
+       static ReplacerData _data;
+
+       std::string ret( value_r );
+       ret = str::replaceAllFun( ret, "$arch",         [&_data]()-> std::string { return _data.sysarch(); } );
+       ret = str::replaceAllFun( ret, "$basearch",     [&_data]()-> std::string { return _data.basearch(); } );
+       ret = str::replaceAllFun( ret, "$releasever",   [&_data]()-> std::string { return _data.releasever(); } );
+       return ret;
+      }
+
+    } // namespace
+    ///////////////////////////////////////////////////////////////////
+
+    std::string RepoVariablesStringReplacer::operator()( const std::string & value ) const
+    {
+      return replacer( value );
+    }
+
+    Url RepoVariablesUrlReplacer::operator()( const Url & value ) const
+    {
+      Url newurl( value );
+      newurl.setPathData( replacer( value.getPathData() ) );
+      newurl.setQueryString( replacer( value.getQueryString() ) );
+      return newurl;
+    }
+
+  } // namespace repo
+  ///////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
index 012ba73d2b8d2b4c036c8544ac636110cca6e658..bec57b50e8863b2ce7dcb8eccf563f6848ee2012 100644 (file)
 #ifndef ZYPP_REPO_VARIABLES_H_
 #define ZYPP_REPO_VARIABLES_H_
 
-#include <iosfwd>
 #include <string>
-
 #include "zypp/Url.h"
-#include "zypp/Arch.h"
 
+///////////////////////////////////////////////////////////////////
 namespace zypp
 {
+  ///////////////////////////////////////////////////////////////////
   namespace repo
   {
 
-  /**
-   * \short Repository variables
-   *
-   * ...
-   */
-  struct RepoVariablesStringReplacer : public std::unary_function<std::string, std::string>
-  {
-    RepoVariablesStringReplacer();
-
-    std::string operator()( const std::string &value ) const;
-
-    ~RepoVariablesStringReplacer();
-
-    void resetVarCache( void );
-
-    private:
-      mutable Arch sysarch;
-      mutable Arch basearch;
-      mutable std::string releasever;
-  };
-
-  /**
-   * \short Repository variables
-   *
-   * ...
-   */
-  struct RepoVariablesUrlReplacer : public std::unary_function<Url, Url>
-  {
-    RepoVariablesUrlReplacer();
-
-    Url operator()( const Url &url ) const;
-
-    ~RepoVariablesUrlReplacer();
-
-    void resetVarCache( void );
-
-    private:
-      RepoVariablesStringReplacer replacer;
-  };
-
-  } // ns repo
-} // ns zypp
+    /**
+     * \short Functor replacing repository variables
+     *
+     * Replaces '$arch', '$basearch' and $releasever in a string
+     * with the global ZYpp values.
+     * \code
+     * Example:
+     * ftp://user:secret@site.net/$arch/ -> ftp://user:secret@site.net/i686/
+     * http://site.net/?basearch=$basearch -> http://site.net/?basearch=i386
+     * \endcode
+     */
+    struct RepoVariablesStringReplacer : public std::unary_function<const std::string &, std::string>
+    {
+      std::string operator()( const std::string & value_r ) const;
+    };
+
+    /**
+     * \short Functor replacing repository variables
+     *
+     * Replaces repository variables in the path and query part of the URL.
+     * \see RepoVariablesStringReplacer
+     */
+    struct RepoVariablesUrlReplacer : public std::unary_function<const Url &, Url>
+    {
+      Url operator()( const Url & url_r ) const;
+    };
+
+  } // namespace repo
+  ///////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
 
 #endif
-
-// vim: set ts=2 sts=2 sw=2 et ai: