From e767764e6ede05725281dcb6713dd34183b6fca4 Mon Sep 17 00:00:00 2001 From: Michael Andres Date: Fri, 25 Nov 2005 09:40:47 +0000 Subject: [PATCH] Added Edition::Less to allow std::container on Edition using Edition::operator< as well as lexicogrophical order. Namespace for string related tools and helper functions was renamed from (zypp::)base::string to (zypp::)str. 'string' is obviously not a good choice for a namespace, and the additional base:: is superfluous and inconvenient. --- devel/devel.ma/Main.cc | 22 ++++++---- zypp/@DOXYGEN/DOXYGEN.h | 4 ++ zypp/Edition.cc | 2 +- zypp/Edition.h | 79 +++++++++++++++++++++++++++++++---- zypp/NeedAType.h | 3 +- zypp/base/KindOf.h | 36 +++++++++------- zypp/base/Logger.cc | 6 +-- zypp/base/String.cc | 108 +++++++++++++++++++++++------------------------- zypp/base/String.h | 35 ++++++---------- 9 files changed, 179 insertions(+), 116 deletions(-) diff --git a/devel/devel.ma/Main.cc b/devel/devel.ma/Main.cc index 9a37a5b..31f1e30 100644 --- a/devel/devel.ma/Main.cc +++ b/devel/devel.ma/Main.cc @@ -8,10 +8,24 @@ #include #include -using namespace std; +#include +using namespace std; +template + void outc( const _C & cont, ostream & str ) + { + copy( cont.begin(), cont.end(), + ostream_iterator(str,"\n") ); + } + +namespace zypp +{ + +} using namespace zypp; + + /****************************************************************** ** ** @@ -24,12 +38,6 @@ int main( int argc, char * argv[] ) { INT << "===[START]==========================================" << endl; - DBG << Edition( "1.0", "1a" ) << endl; - DBG << Edition( "2.0", "13" ) << endl; - DBG << Edition( "2_0", "13" ) << endl; - DBG << Edition( "3.0", "13.4" ) << endl; - - INT << "===[END]============================================" << endl; return 0; diff --git a/zypp/@DOXYGEN/DOXYGEN.h b/zypp/@DOXYGEN/DOXYGEN.h index c91f771..5370ab6 100644 --- a/zypp/@DOXYGEN/DOXYGEN.h +++ b/zypp/@DOXYGEN/DOXYGEN.h @@ -28,3 +28,7 @@ * \verbinclude g_EnumerationClass */ //////////////////////////////////////////////////////////////////////////////// +/*! \defgroup g_BackenSpecific Backend Specific + * \verbinclude g_BackenSpecific +*/ +//////////////////////////////////////////////////////////////////////////////// diff --git a/zypp/Edition.cc b/zypp/Edition.cc index a674fd6..3f42d5a 100644 --- a/zypp/Edition.cc +++ b/zypp/Edition.cc @@ -192,7 +192,7 @@ namespace zypp string ret; if ( _pimpl->_epoch ) - ret += base::string::form( "%d:", _pimpl->_epoch ); + ret += str::form( "%d:", _pimpl->_epoch ); ret += _pimpl->_version; diff --git a/zypp/Edition.h b/zypp/Edition.h index eb94cd3..73e68c2 100644 --- a/zypp/Edition.h +++ b/zypp/Edition.h @@ -13,6 +13,7 @@ #define ZYPP_EDITION_H #include +#include #include #include "zypp/base/PtrTypes.h" @@ -27,10 +28,35 @@ namespace zypp // // CLASS NAME : Edition // - /** Edition - \todo doc - \todo optimize implementation - \todo implement debian comparison and make choice backend specific + /** Edition represents [epoch:]version[-release] + * + * \li \c epoch (optional) number, Edition::noepoch if not supplied + * \li \c version (required) string, may not contain '-' + * \li \c release (optional) string, may not contain '-' + * + * Comparison is actually \reg g_BackendSpecific. + * + * \li \b RPM: Edition are ordered according to \c epoch, then \c version, + * then \c release. Version and release strings are compared by splitting + * them into segments of alpha or digit sequences. Segments are compared + * according to their type. On mixed types a string compares less than a + * number. + * \code + * compare( 1.a, 1.0 ) == -1 (<) + * compare( 1.0, 1.a ) == 1 (>) + * compare( 1.0, 1_0 ) == 0 (==) + * \endcode + * + * \attention operator< defines equivalence classes of version strings, as non + * alphanumeric chars are ignored. That' why \c 1.0 and \c 1_0 compare equal + * in the example.
+ * If Edition is used as key in a std::container, per default + * plain string comparison is used. If you want to compare by + * version, let the container use Edition::Less to compare. + * + * \ingroup g_BackendSpecific + * \todo optimize implementation + * \todo implement debian comparison and make choice backend specific */ class Edition { @@ -44,18 +70,22 @@ namespace zypp public: /** Default ctor. */ Edition(); + /** Ctor taking \a version_r, \a release_r and optional \a epoch_r */ Edition( const std::string & version_r, const std::string & release_r, epoch_t epoch_r = noepoch ); + /** Dtor */ ~Edition(); public: /** Epoch */ epoch_t epoch() const; + /** Version */ const std::string & version() const; + /** Release */ const std::string & release() const; @@ -78,6 +108,9 @@ namespace zypp */ static int compare( const Edition & lhs, const Edition & rhs ); + /* Binary operator functor comparing Edition. */ + struct Less; + private: /** Hides implementation */ struct Impl; @@ -92,7 +125,6 @@ namespace zypp /** \name Comaprison based on epoch, version, and release. */ //@{ - /** \relates Edition */ inline bool operator==( const Edition & lhs, const Edition & rhs ) { return Edition::compare( Rel::EQ, lhs, rhs ); } @@ -116,9 +148,37 @@ namespace zypp /** \relates Edition */ inline bool operator>=( const Edition & lhs, const Edition & rhs ) { return Edition::compare( Rel::GE, lhs, rhs ); } - //@} + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Edition::Less + // + /** Binary operator functor comparing Edition. + * Default order for std::container using Edition as key is based + * on plain string comparison. Use Less to compare, if + * real version comparison is desired. + * \code + * set eset; + * eset.insert( Edition("1.0","") ); + * eset.insert( Edition("1_0","") ); + * // Now: eset.size() == 2 + * \endcode + * \code + * set eset; + * eset.insert( Edition("1.0","") ); + * eset.insert( Edition("1_0","") ); + * // Now: eset.size() == 1 + * \endcode + */ + struct Edition::Less : public std::binary_function + { + /** \return lhs < rhs */ + bool operator()(const Edition & lhs, const Edition & rhs ) const + { return lhs < rhs; } + }; + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// } // namespace zypp /////////////////////////////////////////////////////////////////// @@ -126,14 +186,17 @@ namespace zypp /////////////////////////////////////////////////////////////////// namespace std { ///////////////////////////////////////////////////////////////// - /** \relates Edition Default order for std::container based on string value.*/ + + /** \relates Edition Default to lexicographical order in std::container.*/ template<> inline bool less::operator()( const zypp::Edition & lhs, const zypp::Edition & rhs ) const { return lhs.asString() < rhs.asString(); } - /** \relates Edition Equality for std::container classes based on string value. */ + + /** \relates Edition Lexicographical equal for std::container. */ template<> inline bool equal_to::operator()( const zypp::Edition & lhs, const zypp::Edition & rhs ) const { return lhs.asString() == rhs.asString(); } + ///////////////////////////////////////////////////////////////// } // namespace zypp /////////////////////////////////////////////////////////////////// diff --git a/zypp/NeedAType.h b/zypp/NeedAType.h index a2f1913..80b0d02 100644 --- a/zypp/NeedAType.h +++ b/zypp/NeedAType.h @@ -92,8 +92,7 @@ namespace zypp */ typedef std::string PackageGroup; - /** - */ + /** Candidate for string unification? */ typedef std::list PackageKeywords; /** Class representing a Date (time_t). Basically store a time_t and offer diff --git a/zypp/base/KindOf.h b/zypp/base/KindOf.h index ca3d26c..a9673c2 100644 --- a/zypp/base/KindOf.h +++ b/zypp/base/KindOf.h @@ -38,11 +38,9 @@ namespace zypp * KindOf stores a \b lowercased version of a string and uses this as * identification. * - * \todo How to make doxygen show the related ==/!= operator - * for KindOf vs std::string comarison? * \todo Unify strings and associate numerical value for more * efficient comparison and use in \c switch. - * \todo Make lowercased/uppercased/... an option. First of all + * \todo Make lowercased/uppercased/etc an option. First of all * get rid of the string::toLower calls operator. * \todo Maybe collaboration with some sort of Registry. */ @@ -58,7 +56,7 @@ namespace zypp */ explicit KindOf( const std::string & value_r ) - : _value( string::toLower(value_r) ) + : _value( str::toLower(value_r) ) {} /** Dtor */ ~KindOf() @@ -74,49 +72,55 @@ namespace zypp }; /////////////////////////////////////////////////////////////////// - /** \Relates KindOf stream output*/ + //@{ + /** \relates KindOf Stream output*/ template inline std::ostream & operator<<( std::ostream & str, const KindOf<_Tp> & obj ) { return str << obj.asString(); } + //@} /////////////////////////////////////////////////////////////////// - /** \Relates KindOf */ + //@{ + /** \relates KindOf */ template inline bool operator==( const KindOf<_Tp> & lhs, const KindOf<_Tp> & rhs ) { return lhs.asString() == rhs.asString(); } - /** \Relates KindOf */ + /** \relates KindOf */ template inline bool operator==( const KindOf<_Tp> & lhs, const std::string & rhs ) - { return lhs.asString() == string::toLower(rhs); } + { return lhs.asString() == str::toLower(rhs); } - /** \Relates KindOf */ + /** \relates KindOf */ template inline bool operator==( const std::string & lhs, const KindOf<_Tp> & rhs ) - { return string::toLower(lhs) == rhs.asString(); } + { return str::toLower(lhs) == rhs.asString(); } + //@} - - /** \Relates KindOf */ + //@{ + /** \relates KindOf */ template inline bool operator!=( const KindOf<_Tp> & lhs, const KindOf<_Tp> & rhs ) { return !( lhs == rhs ); } - /** \Relates KindOf */ + /** \relates KindOf */ template inline bool operator!=( const KindOf<_Tp> & lhs, const std::string & rhs ) { return !( lhs == rhs ); } - /** \Relates KindOf */ + /** \relates KindOf */ template inline bool operator!=( const std::string & lhs, const KindOf<_Tp> & rhs ) { return !( lhs == rhs ); } + //@} - - /** \Relates KindOf For use in std::container. */ + //@{ + /** \relates KindOf Lexicographical order. */ template inline bool operator<( const KindOf<_Tp> & lhs, const KindOf<_Tp> & rhs ) { return lhs.asString() < rhs.asString(); } + //@} ///////////////////////////////////////////////////////////////// } // namespace base diff --git a/zypp/base/Logger.cc b/zypp/base/Logger.cc index 6ae9a53..4252ffd 100644 --- a/zypp/base/Logger.cc +++ b/zypp/base/Logger.cc @@ -34,9 +34,9 @@ namespace zypp const int line_r ) { return (level_r < 0 ? std::cout : std::cerr) - << string::form( "<%d> [%s] %s(%s):%d ", - level_r, group_r, - file_r, func_r, line_r ); + << str::form( "<%d> [%s] %s(%s):%d ", + level_r, group_r, + file_r, func_r, line_r ); } ///////////////////////////////////////////////////////////////// diff --git a/zypp/base/String.cc b/zypp/base/String.cc index acc23a3..24be02d 100644 --- a/zypp/base/String.cc +++ b/zypp/base/String.cc @@ -20,81 +20,75 @@ namespace zypp { ///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// - namespace base + namespace str { ///////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////// - namespace string - { ///////////////////////////////////////////////////////////////// - - /****************************************************************** - ** - ** FUNCTION NAME : form - ** FUNCTION TYPE : std::string - */ - std::string form( const char * format, ... ) + /****************************************************************** + ** + ** FUNCTION NAME : form + ** FUNCTION TYPE : std::string + */ + std::string form( const char * format, ... ) + { + struct SafeBuf { - struct SafeBuf - { - char * _buf; - SafeBuf() : _buf( 0 ) {} - ~SafeBuf() { if ( _buf ) free( _buf ); } - std::string asString() const - { return _buf ? std::string(_buf) : std::string(); } - }; - SafeBuf safe; + char * _buf; + SafeBuf() : _buf( 0 ) {} + ~SafeBuf() { if ( _buf ) free( _buf ); } + std::string asString() const + { return _buf ? std::string(_buf) : std::string(); } + }; + SafeBuf safe; - va_list ap; - va_start( ap, format ); - vasprintf( &safe._buf, format, ap ); - va_end( ap ); + va_list ap; + va_start( ap, format ); + vasprintf( &safe._buf, format, ap ); + va_end( ap ); - return safe.asString(); - } + return safe.asString(); + } - /****************************************************************** - ** - ** FUNCTION NAME : toLower - ** FUNCTION TYPE : std::string - */ - std::string toLower( const std::string & s ) - { - if ( s.empty() ) - return s; + /****************************************************************** + ** + ** FUNCTION NAME : toLower + ** FUNCTION TYPE : std::string + */ + std::string toLower( const std::string & s ) + { + if ( s.empty() ) + return s; - std::string ret( s ); - for ( std::string::size_type i = 0; i < ret.length(); ++i ) { + std::string ret( s ); + for ( std::string::size_type i = 0; i < ret.length(); ++i ) + { if ( isupper( ret[i] ) ) ret[i] = static_cast(tolower( ret[i] )); } - return ret; - } + return ret; + } - /****************************************************************** - ** - ** FUNCTION NAME : toUpper - ** FUNCTION TYPE : std::string - */ - std::string toUpper( const std::string & s ) - { - if ( s.empty() ) - return s; + /****************************************************************** + ** + ** FUNCTION NAME : toUpper + ** FUNCTION TYPE : std::string + */ + std::string toUpper( const std::string & s ) + { + if ( s.empty() ) + return s; - std::string ret( s ); - for ( std::string::size_type i = 0; i < ret.length(); ++i ) { + std::string ret( s ); + for ( std::string::size_type i = 0; i < ret.length(); ++i ) + { if ( islower( ret[i] ) ) ret[i] = static_cast(toupper( ret[i] )); } - return ret; - } + return ret; + } ///////////////////////////////////////////////////////////////// - } // namespace string - /////////////////////////////////////////////////////////////////// - - ///////////////////////////////////////////////////////////////// - } // namespace base + } // namespace str /////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// } // namespace zypp diff --git a/zypp/base/String.h b/zypp/base/String.h index cae4a48..5683fe6 100644 --- a/zypp/base/String.h +++ b/zypp/base/String.h @@ -19,34 +19,25 @@ namespace zypp { ///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// - namespace base + namespace str { ///////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////// - namespace string - { ///////////////////////////////////////////////////////////////// + /** Printf style construction of std::string. */ + std::string form( const char * format, ... ) + __attribute__ ((format (printf, 1, 2))); - /** Printf style construction of std::string. */ - std::string form( const char * format, ... ) - __attribute__ ((format (printf, 1, 2))); + /** Return lowercase version of \a s + * \todo improve + */ + std::string toLower( const std::string & s ); - - /** Return lowercase version of \a s - * \todo improve - */ - std::string toLower( const std::string & s ); - - /** Return uppercase version of \a s - * \todo improve - */ - std::string toUpper( const std::string & s ); - - ///////////////////////////////////////////////////////////////// - } // namespace string - /////////////////////////////////////////////////////////////////// + /** Return uppercase version of \a s + * \todo improve + */ + std::string toUpper( const std::string & s ); ///////////////////////////////////////////////////////////////// - } // namespace base + } // namespace str /////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// } // namespace zypp -- 2.7.4