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.
#include <zypp/Edition.h>
#include <zypp/Rel.h>
-using namespace std;
+#include <boost/regex.hpp>
+using namespace std;
+template<class _C>
+ void outc( const _C & cont, ostream & str )
+ {
+ copy( cont.begin(), cont.end(),
+ ostream_iterator<typename _C::value_type>(str,"\n") );
+ }
+
+namespace zypp
+{
+
+}
using namespace zypp;
+
+
/******************************************************************
**
**
{
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;
* \verbinclude g_EnumerationClass
*/
////////////////////////////////////////////////////////////////////////////////
+/*! \defgroup g_BackenSpecific Backend Specific
+ * \verbinclude g_BackenSpecific
+*/
+////////////////////////////////////////////////////////////////////////////////
string ret;
if ( _pimpl->_epoch )
- ret += base::string::form( "%d:", _pimpl->_epoch );
+ ret += str::form( "%d:", _pimpl->_epoch );
ret += _pimpl->_version;
#define ZYPP_EDITION_H
#include <iosfwd>
+#include <functional>
#include <string>
#include "zypp/base/PtrTypes.h"
//
// CLASS NAME : Edition
//
- /** Edition
- \todo doc
- \todo optimize implementation
- \todo implement debian comparison and make choice backend specific
+ /** Edition represents <code>[epoch:]version[-release]</code>
+ *
+ * \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.<BR>
+ * If Edition is used as key in a std::container, per default
+ * <em>plain string comparison</em> 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
{
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;
*/
static int compare( const Edition & lhs, const Edition & rhs );
+ /* Binary operator functor comparing Edition. */
+ struct Less;
+
private:
/** Hides implementation */
struct Impl;
/** \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 ); }
/** \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 <em>plain string comparison</em>. Use Less to compare, if
+ * real version comparison is desired.
+ * \code
+ * set<Edition> eset;
+ * eset.insert( Edition("1.0","") );
+ * eset.insert( Edition("1_0","") );
+ * // Now: eset.size() == 2
+ * \endcode
+ * \code
+ * set<Edition,Edition::Less> eset;
+ * eset.insert( Edition("1.0","") );
+ * eset.insert( Edition("1_0","") );
+ * // Now: eset.size() == 1
+ * \endcode
+ */
+ struct Edition::Less : public std::binary_function<Edition,Edition,bool>
+ {
+ /** \return <tt>lhs < rhs</tt> */
+ bool operator()(const Edition & lhs, const Edition & rhs ) const
+ { return lhs < rhs; }
+ };
+ ///////////////////////////////////////////////////////////////////
+
/////////////////////////////////////////////////////////////////
} // 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<zypp::Edition>::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<zypp::Edition>::operator()( const zypp::Edition & lhs, const zypp::Edition & rhs ) const
{ return lhs.asString() == rhs.asString(); }
+
/////////////////////////////////////////////////////////////////
} // namespace zypp
///////////////////////////////////////////////////////////////////
*/
typedef std::string PackageGroup;
- /**
- */
+ /** Candidate for string unification? */
typedef std::list<std::string> PackageKeywords;
/** Class representing a Date (time_t). Basically store a time_t and offer
* 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.
*/
*/
explicit
KindOf( const std::string & value_r )
- : _value( string::toLower(value_r) )
+ : _value( str::toLower(value_r) )
{}
/** Dtor */
~KindOf()
};
///////////////////////////////////////////////////////////////////
- /** \Relates KindOf stream output*/
+ //@{
+ /** \relates KindOf Stream output*/
template<class _Tp>
inline std::ostream & operator<<( std::ostream & str, const KindOf<_Tp> & obj )
{ return str << obj.asString(); }
+ //@}
///////////////////////////////////////////////////////////////////
- /** \Relates KindOf */
+ //@{
+ /** \relates KindOf */
template<class _Tp>
inline bool operator==( const KindOf<_Tp> & lhs, const KindOf<_Tp> & rhs )
{ return lhs.asString() == rhs.asString(); }
- /** \Relates KindOf */
+ /** \relates KindOf */
template<class _Tp>
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<class _Tp>
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<class _Tp>
inline bool operator!=( const KindOf<_Tp> & lhs, const KindOf<_Tp> & rhs )
{ return !( lhs == rhs ); }
- /** \Relates KindOf */
+ /** \relates KindOf */
template<class _Tp>
inline bool operator!=( const KindOf<_Tp> & lhs, const std::string & rhs )
{ return !( lhs == rhs ); }
- /** \Relates KindOf */
+ /** \relates KindOf */
template<class _Tp>
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<class _Tp>
inline bool operator<( const KindOf<_Tp> & lhs, const KindOf<_Tp> & rhs )
{ return lhs.asString() < rhs.asString(); }
+ //@}
/////////////////////////////////////////////////////////////////
} // namespace base
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 );
}
/////////////////////////////////////////////////////////////////
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<char>(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<char>(toupper( ret[i] ));
}
- return ret;
- }
+ return ret;
+ }
/////////////////////////////////////////////////////////////////
- } // namespace string
- ///////////////////////////////////////////////////////////////////
-
- /////////////////////////////////////////////////////////////////
- } // namespace base
+ } // namespace str
///////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
} // namespace zypp
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