From 8e1ed5b505d812648ff48efede2ebca9ec0b80ad Mon Sep 17 00:00:00 2001 From: Michael Andres Date: Mon, 28 Nov 2005 09:28:33 +0000 Subject: [PATCH] Added Exceptions (Exception.h) 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 | 21 ++++- devel/devel.ma/Makefile.am | 2 +- zypp/Edition.cc | 56 +++++++++++++ zypp/Edition.h | 20 ++++- zypp/base/Exception.cc | 80 ++++++++++++++++++ zypp/base/Exception.h | 154 +++++++++++++++++++++++++++++++++++ zypp/base/Makefile.am | 2 + zypp/base/ReferenceCounted.h | 5 +- zypp/base/String.cc | 10 +++ zypp/base/String.h | 40 +++++++++ 10 files changed, 381 insertions(+), 9 deletions(-) create mode 100644 zypp/base/Exception.cc create mode 100644 zypp/base/Exception.h diff --git a/devel/devel.ma/Main.cc b/devel/devel.ma/Main.cc index 31f1e300c..4f510c0ec 100644 --- a/devel/devel.ma/Main.cc +++ b/devel/devel.ma/Main.cc @@ -4,13 +4,12 @@ #include #include #include +#include +#include #include #include #include -#include - - using namespace std; template void outc( const _C & cont, ostream & str ) @@ -21,10 +20,14 @@ template 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; diff --git a/devel/devel.ma/Makefile.am b/devel/devel.ma/Makefile.am index a889df70b..47552f83c 100644 --- a/devel/devel.ma/Makefile.am +++ b/devel/devel.ma/Makefile.am @@ -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 ## ################################################## diff --git a/zypp/Edition.cc b/zypp/Edition.cc index 3f42d5a21..6445fb1a8 100644 --- a/zypp/Edition.cc +++ b/zypp/Edition.cc @@ -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() {} diff --git a/zypp/Edition.h b/zypp/Edition.h index 73e68c249..1fa1036cd 100644 --- a/zypp/Edition.h +++ b/zypp/Edition.h @@ -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 index 000000000..c7f1b7e64 --- /dev/null +++ b/zypp/base/Exception.cc @@ -0,0 +1,80 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Exception.cc + * +*/ +#include + +#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 index 000000000..5ce4c5965 --- /dev/null +++ b/zypp/base/Exception.h @@ -0,0 +1,154 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Exception.h + * +*/ +#ifndef ZYPP_BASE_EXCEPTION_H +#define ZYPP_BASE_EXCEPTION_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +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 diff --git a/zypp/base/Makefile.am b/zypp/base/Makefile.am index a4cf911be..4c45b1a67 100644 --- a/zypp/base/Makefile.am +++ b/zypp/base/Makefile.am @@ -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 diff --git a/zypp/base/ReferenceCounted.h b/zypp/base/ReferenceCounted.h index 86f4e8876..44b31d946 100644 --- a/zypp/base/ReferenceCounted.h +++ b/zypp/base/ReferenceCounted.h @@ -14,6 +14,7 @@ #include +#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; } diff --git a/zypp/base/String.cc b/zypp/base/String.cc index 24be02dba..8f7e73fc4 100644 --- a/zypp/base/String.cc +++ b/zypp/base/String.cc @@ -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 diff --git a/zypp/base/String.h b/zypp/base/String.h index 5683fe6b0..0c9a2a65d 100644 --- a/zypp/base/String.h +++ b/zypp/base/String.h @@ -14,11 +14,15 @@ #include #include +#include /////////////////////////////////////////////////////////////////// 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 */ -- 2.34.1