Added Exceptions (Exception.h)
authorMichael Andres <ma@suse.de>
Mon, 28 Nov 2005 09:28:33 +0000 (09:28 +0000)
committerMichael Andres <ma@suse.de>
Mon, 28 Nov 2005 09:28:33 +0000 (09:28 +0000)
Provide regular expressions in namespace (zypp::)str (String.h)
Added Edition constructor taking epoch as string (doing conversion
into number), and one parsing complete edition spec. from string
"[epoch:]version[-release]".

devel/devel.ma/Main.cc
devel/devel.ma/Makefile.am
zypp/Edition.cc
zypp/Edition.h
zypp/base/Exception.cc [new file with mode: 0644]
zypp/base/Exception.h [new file with mode: 0644]
zypp/base/Makefile.am
zypp/base/ReferenceCounted.h
zypp/base/String.cc
zypp/base/String.h

index 31f1e300c173d911743f39d600a2c5f528f1ddb8..4f510c0ecb93fbf913642fcdc6aba91a6507f821 100644 (file)
@@ -4,13 +4,12 @@
 #include <set>
 #include <algorithm>
 #include <zypp/base/Logger.h>
+#include <zypp/base/String.h>
+#include <zypp/base/ReferenceCounted.h>
 #include <zypp/Arch.h>
 #include <zypp/Edition.h>
 #include <zypp/Rel.h>
 
-#include <boost/regex.hpp>
-
-
 using namespace std;
 template<class _C>
   void outc( const _C & cont, ostream & str )
@@ -21,10 +20,14 @@ template<class _C>
 
 namespace zypp
 {
-
 }
 using namespace zypp;
 
+void chk( const std::string & ed )
+{
+  Edition e( ed );
+  MIL << e << endl;
+}
 
 /******************************************************************
 **
@@ -38,6 +41,16 @@ int main( int argc, char * argv[] )
 {
   INT << "===[START]==========================================" << endl;
 
+  DBG << Edition() << endl;
+  DBG << Edition("") << endl;
+
+  DBG << Edition("","","") << endl;
+
+  chk( "1.2.3-4.5.6" );
+  chk( "3:1.2.3-4.5.6" );
+
+  chk( "3:1.2.3-4.5.6-3" );
+
 
   INT << "===[END]============================================" << endl;
   return 0;
index a889df70bd73508f674a30f9117381c4273c9529..47552f83ccb8f3dbbce36cfcd996cb8cdeefd75a 100644 (file)
@@ -12,7 +12,7 @@ AM_LDFLAGS =
 AM_CXXFLAGS =
 # gperf:       -pg
 
-LDADD =                $(top_srcdir)/zypp/lib@PACKAGE@.la
+LDADD =                $(top_srcdir)/zypp/lib@PACKAGE@.la  -lboost_regex
 
 ## ##################################################
 
index 3f42d5a2141e5408065a6dd39d5e65824674eef6..6445fb1a88ef982addc463041cf0f8058cb69f59 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "zypp/base/Logger.h"
 #include "base/String.h"
+#include "base/Exception.h"
 
 #include "zypp/Edition.h"
 
@@ -141,6 +142,29 @@ namespace zypp
     : _epoch( 0 )
     {}
 
+    Impl( const std::string & edition_r )
+    : _epoch( 0 )
+    {
+      str::smatch what;
+      if( str::regex_match( edition_r.begin(), edition_r.end(),
+                            what, _rxEdition ) )
+        {
+          // what[2] contains the epoch
+          // what[3] contains the version
+          // what[5] contains the release
+          if ( what[2].matched )
+            _epoch = strtoul( what[2].str().c_str(), NULL, 10 );
+          if ( what[3].matched )
+            _version = what[3].str();
+          if ( what[5].matched )
+            _release = what[5].str();
+        }
+      else
+        {
+          ZYPP_THROW( string("Invalid Edition: ")+edition_r );
+        }
+    }
+
     Impl( const std::string & version_r,
           const std::string & release_r,
           epoch_t epoch_r )
@@ -149,6 +173,16 @@ namespace zypp
     , _release( release_r )
     {}
 
+    Impl( const std::string & version_r,
+          const std::string & release_r,
+          const std::string & epoch_r )
+    : _epoch( strtoul( epoch_r.c_str(), NULL, 10 ) )
+    , _version( version_r )
+    , _release( release_r )
+    {
+#warning check legal VR
+    }
+
     /** Dtor */
     ~Impl()
     {}
@@ -156,9 +190,21 @@ namespace zypp
     epoch_t      _epoch;
     std::string _version;
     std::string _release;
+
+    static const std::string _rxE;
+    static const std::string _rxVR;
+    static const str::regex _rxEdition;
   };
   ///////////////////////////////////////////////////////////////////
 
+  const std::string Edition::Impl::_rxE( "([0-9]+):" );
+  const std::string Edition::Impl::_rxVR( "([^-]*)" );
+  const str::regex Edition::Impl::_rxEdition( str::form( "(%s)?%s(-%s)?",
+                                                         _rxE.c_str(),
+                                                         _rxVR.c_str(), _rxVR.c_str() ) );
+
+  ///////////////////////////////////////////////////////////////////
+
   ///////////////////////////////////////////////////////////////////
   //
   //   CLASS NAME : Edition
@@ -169,12 +215,22 @@ namespace zypp
   : _pimpl( new Impl )
   {}
 
+  Edition::Edition( const std::string & edition_r )
+  : _pimpl( new Impl( edition_r ) )
+  {}
+
   Edition::Edition( const std::string & version_r,
                     const std::string & release_r,
                     epoch_t epoch_r )
   : _pimpl( new Impl( version_r, release_r, epoch_r ) )
   {}
 
+  Edition::Edition( const std::string & version_r,
+                    const std::string & release_r,
+                    const std::string & epoch_r )
+  : _pimpl( new Impl( version_r, release_r, epoch_r ) )
+  {}
+
   Edition::~Edition()
   {}
 
index 73e68c249af8a1ce05b7c9754e0ba6c52e5e7439..1fa1036cdbbdea3bb5d3c01bacc8a4e7e678fd94 100644 (file)
@@ -55,7 +55,8 @@ namespace zypp
    * version, let the container use Edition::Less to compare.
    *
    * \ingroup g_BackendSpecific
-   * \todo optimize implementation
+   * \todo Define exceptions.
+   * \todo optimize implementation(e.g don't store epoch if noepoch)
    * \todo implement debian comparison and make choice backend specific
   */
   class Edition
@@ -71,11 +72,26 @@ namespace zypp
     /** Default ctor. */
     Edition();
 
-    /** Ctor taking \a version_r, \a release_r and optional \a epoch_r */
+    /** Ctor taking edition as string.
+     * \throw INTERNAL if \a edition_r does not make a valid Edition.
+    */
+    Edition( const std::string & edition_r );
+
+    /** Ctor taking \a version_r, \a release_r and optional \a epoch_r
+     * \throw INTERNAL if \a version_r or \a release_r are not valid.
+    */
     Edition( const std::string & version_r,
              const std::string & release_r,
              epoch_t epoch_r = noepoch );
 
+    /** Ctor taking \a version_r, \a release_r and optional \a epoch_r as string.
+     * \throw INTERNAL if \a version_r or \a release_r \a epoch_r are
+     * not valid.
+    */
+    Edition( const std::string & version_r,
+             const std::string & release_r,
+             const std::string & epoch_r );
+
     /** Dtor */
     ~Edition();
 
diff --git a/zypp/base/Exception.cc b/zypp/base/Exception.cc
new file mode 100644 (file)
index 0000000..c7f1b7e
--- /dev/null
@@ -0,0 +1,80 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file zypp/base/Exception.cc
+ *
+*/
+#include <iostream>
+
+#include "zypp/base/Logger.h"
+#include "zypp/base/String.h"
+#include "zypp/base/Exception.h"
+
+using std::endl;
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{ /////////////////////////////////////////////////////////////////
+  ///////////////////////////////////////////////////////////////////
+  namespace exceptinon_detail
+  { /////////////////////////////////////////////////////////////////
+
+    std::string CodeLocation::asString() const
+    {
+      return str::form( "%s(%s):%u",
+                        _file.c_str(),
+                        _func.c_str(),
+                        _line );
+    }
+
+    std::ostream & operator<<( std::ostream & str, const CodeLocation & obj )
+    { return str << obj.asString(); }
+
+    /////////////////////////////////////////////////////////////////
+  } // namespace exceptinon_detail
+  ///////////////////////////////////////////////////////////////////
+
+  Exception::Exception( const CodeLocation & where_r, const std::string & msg_r )
+  : _where( where_r ), _msg( msg_r )
+  {
+    INT << asString() << endl;
+  }
+
+  Exception::~Exception() throw()
+  {}
+
+  std::string Exception::asString() const
+  {
+    std::string ret( _where.asString() );
+    ret += ": ";
+    return ret += _msg;
+  }
+
+  std::string Exception::strErrno( int errno_r )
+  {
+    return str::strerror( errno_r );
+  }
+
+  std::string Exception::strErrno( int errno_r, const std::string & msg_r )
+  {
+    std::string ret( msg_r );
+    ret += ": ";
+    return ret += strErrno( errno_r );
+  }
+
+  void Exception::caught() const
+  {
+    INT << "Caught: " << asString() << endl;
+  }
+
+  std::ostream & operator<<( std::ostream & str, const Exception & obj )
+  { return str << obj.asString(); }
+
+  /////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
diff --git a/zypp/base/Exception.h b/zypp/base/Exception.h
new file mode 100644 (file)
index 0000000..5ce4c59
--- /dev/null
@@ -0,0 +1,154 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file zypp/base/Exception.h
+ *
+*/
+#ifndef ZYPP_BASE_EXCEPTION_H
+#define ZYPP_BASE_EXCEPTION_H
+
+#include <iosfwd>
+#include <stdexcept>
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{ /////////////////////////////////////////////////////////////////
+  ///////////////////////////////////////////////////////////////////
+  namespace exceptinon_detail
+  { /////////////////////////////////////////////////////////////////
+
+    /** Keep _FILE_, _FUNCTION_ and _LINE_.
+     * Construct it using the \ref ZYPP_EX_CODELOCATION macro.
+    */
+    struct CodeLocation
+    {
+      friend std::ostream & operator<<( std::ostream & str, const CodeLocation & obj );
+
+      /** Ctor */
+      CodeLocation( const std::string & file_r,
+                    const std::string & func_r,
+                    unsigned            line_r )
+      : _file( file_r ), _func( func_r ), _line( line_r )
+      {}
+
+      /** Location as string */
+      std::string asString() const;
+
+    private:
+      std::string _file;
+      std::string _func;
+      unsigned    _line;
+    };
+    ///////////////////////////////////////////////////////////////////
+
+    /** Create CodeLocation object storing the current location. */
+    #define ZYPP_EX_CODELOCATION ::zypp::exceptinon_detail::CodeLocation(__FILE__,__FUNCTION__,__LINE__)
+
+    /** \relates CodeLocation Stream output */
+    std::ostream & operator<<( std::ostream & str, const CodeLocation & obj );
+
+    /////////////////////////////////////////////////////////////////
+  } // namespace exceptinon_detail
+  ///////////////////////////////////////////////////////////////////
+
+  ///////////////////////////////////////////////////////////////////
+  //
+  //   CLASS NAME : Exception
+  /** Exception stores message and \ref CodeLocation.
+   *
+   * Use \ref ZYPP_THROW to throw exceptions. Assuming this,
+   * the ctor logs it's creation, as it't the point where the
+   * exception is thrown. If you catch the Excetion, you may
+   * call \ref caught, to drop a logling telling so.
+   *
+   * \todo That's a draft to have a common way of throwing exceptions.
+   * Most probabely we'll finally use blocxx exceptions. Here, but not
+   * in the remaining code of zypp. If we can we should try to wrap
+   * the blocxx macros and typedef the classes in here.
+   **/
+  class Exception : public std::exception
+  {
+    friend std::ostream & operator<<( std::ostream & str, const Exception & obj );
+    typedef exceptinon_detail::CodeLocation CodeLocation;
+  public:
+
+    /** Ctor taking CodeLocation and message.
+     * Use \ref ZYPP_THROW to throw exceptions.
+    */
+    Exception( const CodeLocation & where_r, const std::string & msg_r );
+
+    /** Dtor. */
+    virtual ~Exception() throw();
+
+    /** Return CodeLocation. */
+    const CodeLocation & where() const
+    { return _where; }
+
+    /** Return message string. */
+    const std::string & msg() const
+    { return _msg; }
+
+    /** Return message string. */
+    virtual const char * what() const throw()
+    { return _msg.c_str(); }
+
+    /** Exception as string */
+    std::string asString() const;
+
+    /** Simply drops a log line. */
+    void caught() const;
+
+  public:
+     /** Make a string from \a errno_r. */
+    static std::string strErrno( int errno_r );
+     /** Make a string from \a errno_r and \a msg_r. */
+    static std::string strErrno( int errno_r, const std::string & msg_r );
+
+  private:
+    CodeLocation _where;
+    std::string _msg;
+  };
+  ///////////////////////////////////////////////////////////////////
+
+  /** \relates Exception Stream output */
+  std::ostream & operator<<( std::ostream & str, const Exception & obj );
+
+  ///////////////////////////////////////////////////////////////////
+
+  /** Actually throw an Exception. */
+#define ZYPP_DOTHROW(EXCPT) throw( EXCPT )
+
+  /** \defgroup ZYPP_THROW ZYPP_THROW macros
+   * Macros for throwing Exception.
+  */
+  //@{
+  /** Throw a message string. */
+#define ZYPP_THROW(MSG)\
+  ZYPP_DOTHROW( ::zypp::Exception( ZYPP_EX_CODELOCATION, MSG ) )
+
+  /** Throw errno. */
+#define ZYPP_THROW_ERRNO\
+  ZYPP_DOTHROW( ::zypp::Exception( ZYPP_EX_CODELOCATION, ::zypp::Exception::strErrno(errno) ) )
+
+  /** Throw errno provided as argument. */
+#define ZYPP_THROW_ERRNO1(ERRNO)\
+  ZYPP_DOTHROW( ::zypp::Exception( ZYPP_EX_CODELOCATION, ::zypp::Exception::strErrno(ERRNO) ) )
+
+  /** Throw errno and a message string. */
+#define ZYPP_THROW_ERRNO_MSG(MSG)\
+  ZYPP_DOTHROW( ::zypp::Exception( ZYPP_EX_CODELOCATION, ::zypp::Exception::strErrno(errno,MSG) ) )
+
+  /** Throw errno provided as argument and a message string */
+#define ZYPP_THROW_ERRNO_MSG1(ERRNO,MSG)\
+  ZYPP_DOTHROW( ::zypp::Exception( ZYPP_EX_CODELOCATION, ::zypp::Exception::strErrno(ERRNO,MSG) ) )
+  //@}
+
+  /////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+#endif // ZYPP_BASE_EXCEPTION_H
index a4cf911be8e5bad271668d888f9c79de2decd4e0..4c45b1a67d8c91e5f0a230aaf55d0c9a78da9792 100644 (file)
@@ -8,6 +8,7 @@ SUBDIRS =
 include_HEADERS =      \
        KindOf.h        \
        Logger.h        \
+       Exception.h     \
        NonCopyable.h   \
        PtrTypes.h      \
        ReferenceCounted.h      \
@@ -21,6 +22,7 @@ noinst_LTLIBRARIES =  lib@PACKAGE@_base.la
 
 lib@PACKAGE@_base_la_SOURCES = \
        Logger.cc       \
+       Exception.cc    \
        String.cc       \
        StringVal.cc
 
index 86f4e8876dd02787035c5e23182cefb094747196..44b31d946e165f1336dcd6f42b93d76b03bfc960 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <iosfwd>
 
+#include "zypp/base/Exception.h"
 #include "zypp/base/PtrTypes.h"
 
 ///////////////////////////////////////////////////////////////////
@@ -53,7 +54,7 @@ namespace zypp
        * \throw INTERNAL if reference count is not zero.
       */
       virtual ~ReferenceCounted()
-      { if ( _counter ) throw( "~ReferenceCounted: nonzero reference count" ); }
+      { if ( _counter ) ZYPP_THROW( "~ReferenceCounted: nonzero reference count" ); }
 
       /** Assignment.
        * Reference count remains untouched.
@@ -77,7 +78,7 @@ namespace zypp
       void unref() const
       {
         if ( !_counter )
-          throw( "ReferenceCounted::unref: zero reference count" );
+          ZYPP_THROW( "ReferenceCounted::unref: zero reference count" );
         if ( --_counter == 0 )
           delete this;
       }
index 24be02dba9311fc6d1c9d94bc9bc8a6fd80ab99c..8f7e73fc4cc1499b3980826de5d5cd1e77ea18dd 100644 (file)
@@ -48,6 +48,16 @@ namespace zypp
       return safe.asString();
     }
 
+    /******************************************************************
+     **
+     **      FUNCTION NAME : toLower
+     **      FUNCTION TYPE : std::string
+    */
+    std::string strerror( int errno_r )
+    {
+      return form( "(%d)%s", errno_r, ::strerror( errno_r ) );
+    }
+
     /******************************************************************
      **
      **      FUNCTION NAME : toLower
index 5683fe6b0e2fa079184695899f3c525c856d241c..0c9a2a65d360ba2b45faa1cf16263ee62405be3c 100644 (file)
 
 #include <iosfwd>
 #include <string>
+#include <boost/regex.hpp>
 
 ///////////////////////////////////////////////////////////////////
 namespace zypp
 { /////////////////////////////////////////////////////////////////
   ///////////////////////////////////////////////////////////////////
+  /** String related utilities and \ref ZYPP_STR_REGEX.
+   \see \ref ZYPP_STR_REGEX
+  */
   namespace str
   { /////////////////////////////////////////////////////////////////
 
@@ -26,6 +30,42 @@ namespace zypp
     std::string form( const char * format, ... )
     __attribute__ ((format (printf, 1, 2)));
 
+    /** Return string describing the \a error_r code.
+     * Like ::strerror, but the numerical value is included in
+     * the string as well.
+    */
+    std::string strerror( int errno_r );
+
+    /** \defgroup ZYPP_STR_REGEX Regular expressions
+     *
+     * Namespace zypp::str regular expressions \b using the
+     * boost regex library
+     * \url http://www.boost.org/libs/regex/doc/index.html.
+     *
+     * \li \c regex
+     * \li \c regex_match
+     * \li \c regex_search
+     * \li \c regex_replace
+     * \li \c match_results
+     * \li \c cmatch
+     * \li \c wcmatch
+     * \li \c smatch
+     * \li \c wsmatch
+    */
+
+    //@{
+    /** regex */
+    using boost::regex;
+    using boost::regex_match;
+    using boost::regex_search;
+    using boost::regex_replace;
+    using boost::match_results;
+    using boost::cmatch;
+    using boost::wcmatch;
+    using boost::smatch;
+    using boost::wsmatch;
+    //@}
+
     /** Return lowercase version of \a s
      * \todo improve
     */