1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/Edition.h
12 #ifndef ZYPP_EDITION_H
13 #define ZYPP_EDITION_H
19 #include "zypp/base/PtrTypes.h"
21 #include "zypp/RelCompare.h"
22 #include "zypp/Range.h"
24 ///////////////////////////////////////////////////////////////////
26 { /////////////////////////////////////////////////////////////////
28 ///////////////////////////////////////////////////////////////////
30 // CLASS NAME : Edition
32 /** Edition represents <code>[epoch:]version[-release]</code>
34 * \li \c epoch (optional) number, Edition::noepoch if not supplied
35 * \li \c version (required) string, may not contain '-'
36 * \li \c release (optional) string, may not contain '-'
38 * Comparison is actually \reg g_BackendSpecific.
40 * \li \b RPM: Edition are ordered according to \c epoch, then \c version,
41 * then \c release. Version and release strings are compared by splitting
42 * them into segments of alpha or digit sequences. Segments are compared
43 * according to their type. On mixed types a string compares less than a
46 * compare( 1.a, 1.0 ) == -1 (<)
47 * compare( 1.0, 1.a ) == 1 (>)
48 * compare( 1.0, 1_0 ) == 0 (==)
51 * \attention operator< defines equivalence classes of version strings, as non
52 * alphanumeric chars are ignored. That' why \c 1.0 and \c 1_0 compare equal
54 * If Edition is used as key in a std::container, per default
55 * <em>plain string comparison</em> is used. If you want to compare by
56 * version, let the container use \ref CompareByLT<Edition> to compare.
58 * \attention Edition::match compares two editions, treating empty
59 * version or release strings as wildcard. Thus match is not transitive,
60 * and you don't want to use it to order keys in a a std::container.
62 * \ingroup g_BackendSpecific
63 * \todo Define exceptions.
64 * \todo optimize implementation(e.g don't store epoch if noepoch)
65 * \todo implement debian comparison and make choice backend specific
66 * \todo optimize noedition. unified Impl and quick check in compare.
71 /** Type of an epoch. */
72 typedef unsigned epoch_t;
74 /** Value representing \c noepoch. */
75 static const epoch_t noepoch = 0;
77 /** Value representing \c noedition.
78 * This is in fact a valid Edition. It's what the default ctor
79 * creates or will be parsed from an empty string.
81 static const Edition noedition;
84 /** Default ctor: \ref noedition. */
87 /** Ctor taking edition as string.
88 * \throw INTERNAL if \a edition_r does not make a valid Edition.
90 Edition( const std::string & edition_r );
92 /** Ctor taking \a version_r, \a release_r and optional \a epoch_r
93 * \throw INTERNAL if \a version_r or \a release_r are not valid.
95 Edition( const std::string & version_r,
96 const std::string & release_r,
97 epoch_t epoch_r = noepoch );
99 /** Ctor taking \a version_r, \a release_r and optional \a epoch_r as string.
100 * \throw INTERNAL if \a version_r or \a release_r \a epoch_r are
103 Edition( const std::string & version_r,
104 const std::string & release_r,
105 const std::string & epoch_r );
112 epoch_t epoch() const;
115 const std::string & version() const;
118 const std::string & release() const;
120 /** String representation of Edition. */
121 std::string asString() const;
124 /** Compare two Editions returning <tt>-1,0,1</tt>.
125 * \return <tt>-1,0,1</tt> if editions are <tt>\<,==,\></tt>.
127 * \attention An empty version or release string is not treated
128 * specialy. It's the least possible value. If you want an empty
129 * string treated as \c ANY, use \ref match.
131 static int compare( const Edition & lhs, const Edition & rhs );
134 int compare( const Edition & rhs ) const
135 { return compare( *this, rhs ); }
137 /** \ref compare functor.
138 * \see \ref RelCompare.
140 typedef Compare<Edition> CompareEd;
142 /** \ref Edition \ref Range based on \ref Compare.
143 * \see \ref RelCompare.
145 typedef Range<Edition> CompareRange;
148 /** Match two Editions returning <tt>-1,0,1</tt>, treating empty
150 * \return <tt>-1,0,1</tt> if editions match <tt>\<,==,\></tt>.
152 static int match( const Edition & lhs, const Edition & rhs );
155 int match( const Edition & rhs ) const
156 { return match( *this, rhs ); }
158 /** \ref match functor.
159 * \see \ref RelCompare.
161 struct Match: public std::binary_function<Edition,Edition,int>
163 int operator()( const Edition & lhs, const Edition & rhs ) const
164 { return Edition::match( lhs, rhs ); }
167 /** \ref Edition \ref Range based on \ref Match.
168 * \see \ref RelCompare.
170 typedef Range<Edition, Match> MatchRange;
173 /** Hides implementation */
175 /** Pointer to implementation */
176 RW_pointer<Impl> _pimpl;
178 ///////////////////////////////////////////////////////////////////
180 /** \relates Edition Stream output. */
181 inline std::ostream & operator<<( std::ostream & str, const Edition & obj )
182 { return str << obj.asString(); }
184 /** \name Comaprison based on epoch, version, and release. */
186 /** \relates Edition */
187 inline bool operator==( const Edition & lhs, const Edition & rhs )
188 { return compareByRel( Rel::EQ, lhs, rhs ); }
190 /** \relates Edition */
191 inline bool operator!=( const Edition & lhs, const Edition & rhs )
192 { return compareByRel( Rel::NE, lhs, rhs ); }
194 /** \relates Edition */
195 inline bool operator<( const Edition & lhs, const Edition & rhs )
196 { return compareByRel( Rel::LT, lhs, rhs ); }
198 /** \relates Edition */
199 inline bool operator<=( const Edition & lhs, const Edition & rhs )
200 { return compareByRel( Rel::LE, lhs, rhs ); }
202 /** \relates Edition */
203 inline bool operator>( const Edition & lhs, const Edition & rhs )
204 { return compareByRel( Rel::GT, lhs, rhs ); }
206 /** \relates Edition */
207 inline bool operator>=( const Edition & lhs, const Edition & rhs )
208 { return compareByRel( Rel::GE, lhs, rhs ); }
211 /////////////////////////////////////////////////////////////////
213 ///////////////////////////////////////////////////////////////////
215 ///////////////////////////////////////////////////////////////////
217 { /////////////////////////////////////////////////////////////////
219 /** \relates zypp::Edition Default to lexicographical order in std::container.*/
221 inline bool less<zypp::Edition>::operator()( const zypp::Edition & lhs, const zypp::Edition & rhs ) const
222 { return lhs.asString() < rhs.asString(); }
224 /** \relates zypp::Edition Lexicographical equal for std::container. */
226 inline bool equal_to<zypp::Edition>::operator()( const zypp::Edition & lhs, const zypp::Edition & rhs ) const
227 { return lhs.asString() == rhs.asString(); }
229 /////////////////////////////////////////////////////////////////
231 ///////////////////////////////////////////////////////////////////
233 #endif // ZYPP_EDITION_H