Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / Capability.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/Capability.h
10  *
11 */
12 #ifndef ZYPP_CAPABILITY_H
13 #define ZYPP_CAPABILITY_H
14
15 #include <iosfwd>
16
17 #include "zypp/APIConfig.h"
18 #include "zypp/sat/detail/PoolMember.h"
19
20 #include "zypp/IdString.h"
21 #include "zypp/Edition.h"
22 #include "zypp/Rel.h"
23 #include "zypp/ResTraits.h"
24 #include "zypp/ResolverNamespace.h"
25 #include "zypp/CapMatch.h"
26
27 ///////////////////////////////////////////////////////////////////
28 namespace zypp
29 { /////////////////////////////////////////////////////////////////
30
31   class Capability;
32   class CapDetail;
33   class Arch;
34
35   typedef std::unordered_set<Capability> CapabilitySet;
36
37   ///////////////////////////////////////////////////////////////////
38   //
39   //    CLASS NAME : Capability
40   //
41   /** A sat capability.
42    *
43    * A Capability: <tt>"name[.arch] [op edition]"</tt>
44    *
45    * If a certain \ref ResKind is specified upon construction, the
46    * capabilities name part is prefixed, unless it already conatins a
47    * well known kind spec. If no \ref ResKind is specified, it's assumed
48    * you refer to a package or the name is already prefixed:
49    * \code
50    * Capability( "foo" )                   ==> 'foo'
51    * Capability( "foo", ResKind::package ) ==> 'foo'
52    * Capability( "foo", ResKind::pattern ) ==> 'pattern:foo'
53    * Capability( "pattern:foo" )           ==> 'pattern:foo'
54    * // in doubt an explicit name prefix wins:
55    * Capability( "pattern:foo", ResKind::package ) ==> 'pattern:foo'
56    * Capability( "package:foo", ResKind::pattern ) ==> 'foo'
57    * \endcode
58    */
59   class Capability: protected sat::detail::PoolMember
60   {
61     public:
62       enum CtorFlag { PARSED, UNPARSED };
63
64     public:
65       /** Default ctor, \ref Empty capability. */
66       Capability() : _id( sat::detail::emptyId ) {}
67
68       /** Ctor from id. */
69       explicit Capability( sat::detail::IdType id_r ) : _id( id_r ) {}
70
71       /** \name Ctors parsing a Capability: <tt>"name[.arch] [op edition]"</tt> or <tt>( arch, "name [op edition]")</tt>
72       */
73       //@{
74       /** Ctor from string.
75        * \a str_r is parsed to check whether it contains an <tt>[op edition]</tt> part,
76        * unless the \ref PARSED flag is passed to the ctor. In that case <tt>"name[.arch]"</tt>
77        * is assumed.
78       */
79       explicit Capability( const char * str_r, const ResKind & prefix_r = ResKind(), CtorFlag flag_r = UNPARSED );
80       /** \overload */
81       explicit Capability( const std::string & str_r, const ResKind & prefix_r = ResKind(), CtorFlag flag_r = UNPARSED );
82       /** \overload Explicitly specify the \c arch. */
83       Capability( const Arch & arch_r, const char * str_r, const ResKind & prefix_r = ResKind(), CtorFlag flag_r = UNPARSED );
84       /** \overload Explicitly specify the \c arch. */
85       Capability( const Arch & arch_r, const std::string & str_r, const ResKind & prefix_r = ResKind(), CtorFlag flag_r = UNPARSED );
86
87       /** \overload Convenience for parsed (name only, no <tt>"[op edition]</tt>) packages: <tt>Capability( "glibc", PARSED ); */
88       Capability( const char * str_r, CtorFlag flag_r, const ResKind & prefix_r = ResKind() );
89       /** \overload */
90       Capability( const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r = ResKind() );
91       /** \overload Explicitly specify the \c arch. */
92       Capability( const Arch & arch_r, const char * str_r, CtorFlag flag_r, const ResKind & prefix_r = ResKind() );
93       /** \overload */
94       Capability( const Arch & arch_r, const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r = ResKind() );
95       //@}
96
97
98       /** \name Ctors parsing a broken down Capability: <tt>( "name[.arch]", op, edition )</tt>
99       */
100       //@{
101       /** Ctor from <tt>name[.arch] op edition</tt>. */
102       Capability( const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() );
103       /** \overload */
104       Capability( const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() );
105       /** \overload */
106       Capability( const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r = ResKind() );
107       //@}
108
109       /** \name Ctors taking a broken down Capability: <tt>( arch, name, op, edition )</tt>
110       */
111       //@{
112       /** Ctor from <tt>arch name op edition</tt>. */
113       Capability( const std::string & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() );
114       /** \overload */
115       Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() );
116       /** \overload */
117       Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r = ResKind() );
118       /** \overload */
119       Capability( const Arch & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() );
120       /** \overload */
121       Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() );
122       /** \overload */
123       Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r = ResKind() );
124       //@}
125
126       /** \name Ctor creating a namespace: capability.
127        * An empty \a value_r (std::string or IdString) will also be mapped to IdString::Null,
128        * creating a namespace: capability which in most contexts matches all members of this namespace.
129        */
130       //@{
131       Capability( ResolverNamespace namespace_r, IdString value_r = IdString::Null );
132       Capability( ResolverNamespace namespace_r, const char * value_r )         : Capability( namespace_r, IdString(value_r) ) {}
133       Capability( ResolverNamespace namespace_r, const std::string & value_r )  : Capability( namespace_r, IdString(value_r) ) {}
134       //@}
135     public:
136       /** No or Null \ref Capability ( Id \c 0 ). */
137       static const Capability Null;
138
139       /** Empty Capability. */
140       static const Capability Empty;
141
142     public:
143       /** Evaluate in a boolean context <tt>( ! empty() )</tt>. */
144       explicit operator bool() const
145       { return ! empty(); }
146
147       /** Whether the \ref Capability is empty.
148        * This is true for \ref Null and \ref Empty.
149        */
150       bool empty() const
151       { return( _id == sat::detail::emptyId || _id == sat::detail::noId ); }
152
153     public:
154       /** Conversion to <tt>const char *</tt> */
155       const char * c_str() const;
156
157       /** \overload */
158       std::string asString() const
159       { return c_str(); }
160
161     public:
162       /** Helper providing more detailed information about a \ref Capability. */
163       CapDetail detail() const;
164
165     public:
166       /** \name Match two simple capabilities.
167        *
168        * Two simple capabilities match if they have the same \c name
169        * and their \c edition ranges overlap. Where no edition matches
170        * ANY edition. \see \ref Edition::match.
171        *
172        * If a capability expression is involved, \ref matches returns
173        * \ref CapMatch::irrelevant.
174        */
175       //@{
176       static CapMatch matches( const Capability & lhs,  const Capability & rhs )     { return _doMatch( lhs.id(), rhs.id() ); }
177       static CapMatch matches( const Capability & lhs,  const IdString & rhs )       { return _doMatch( lhs.id(), rhs.id() ); }
178       static CapMatch matches( const Capability & lhs,  const std::string & rhs )    { return _doMatch( lhs.id(), Capability(rhs).id() ); }
179       static CapMatch matches( const Capability & lhs,  const char * rhs )           { return _doMatch( lhs.id(), Capability(rhs).id() );}
180
181       static CapMatch matches( const IdString & lhs,    const Capability & rhs )     { return _doMatch( lhs.id(), rhs.id() ); }
182       static CapMatch matches( const IdString & lhs,    const IdString & rhs )       { return _doMatch( lhs.id(), rhs.id() ); }
183       static CapMatch matches( const IdString & lhs,    const std::string & rhs )    { return _doMatch( lhs.id(), Capability(rhs).id() ); }
184       static CapMatch matches( const IdString & lhs,    const char * rhs )           { return _doMatch( lhs.id(), Capability(rhs).id() ); }
185
186       static CapMatch matches( const std::string & lhs, const Capability & rhs )     { return _doMatch( Capability(lhs).id(), rhs.id() );}
187       static CapMatch matches( const std::string & lhs, const IdString & rhs )       { return _doMatch( Capability(lhs).id(), rhs.id() ); }
188       static CapMatch matches( const std::string & lhs, const std::string & rhs )    { return _doMatch( Capability(lhs).id(), Capability(rhs).id() ); }
189       static CapMatch matches( const std::string & lhs, const char * rhs )           { return _doMatch( Capability(lhs).id(), Capability(rhs).id() ); }
190
191       static CapMatch matches( const char * lhs,        const Capability & rhs )     { return _doMatch( Capability(lhs).id(), rhs.id() );}
192       static CapMatch matches( const char * lhs,        const IdString & rhs )       { return _doMatch( Capability(lhs).id(), rhs.id() ); }
193       static CapMatch matches( const char * lhs,        const std::string & rhs )    { return _doMatch( Capability(lhs).id(), Capability(rhs).id() ); }
194       static CapMatch matches( const char * lhs,        const char * rhs )           { return _doMatch( Capability(lhs).id(), Capability(rhs).id() ); }
195
196       CapMatch matches( const Capability & rhs )  const { return _doMatch( id(), rhs.id() ); }
197       CapMatch matches( const IdString & rhs )    const { return _doMatch( id(), rhs.id() ); }
198       CapMatch matches( const std::string & rhs ) const { return _doMatch( id(), Capability(rhs).id() ); }
199       CapMatch matches( const char * rhs )        const { return _doMatch( id(), Capability(rhs).id() ); }
200       //@}
201
202       /** \ref matches functor.
203        */
204       struct Matches: public std::binary_function<Capability,Capability,CapMatch>
205       {
206         CapMatch operator()( const Capability & lhs, const Capability & rhs ) const
207         { return Capability::matches( lhs, rhs ); }
208       };
209
210     public:
211       /** Test for a filename that is likely being REQUIRED.
212        * Files below \c /bin , \c /sbin ,  \c /lib etc. Scanning a
213        * packages filelist, an \e interesting filename might be worth
214        * being remembered in PROVIDES.
215        */
216       static bool isInterestingFileSpec( const IdString & name_r )    { return isInterestingFileSpec( name_r.c_str() ); }
217       static bool isInterestingFileSpec( const std::string & name_r ) { return isInterestingFileSpec( name_r.c_str() ); }
218       static bool isInterestingFileSpec( const char * name_r );
219
220       /** \ref Capability parser also guessing \c "libzypp-1.2.3-4.5.x86_64" formats.
221        *
222        * The argument might be in the form \c "libzypp-devel-1.2.3.x86_64".
223        * Passed to the Capability ctor, this would correctly be parsed as name
224        * capability, because actually the edition part had to be separated by a
225        * \c '=', and the architecture had to be appended to the name.
226        * So this is how it actually had to look like: \c "libzypp-devel.x86_64=1.2.3"
227        *
228        * Obviously we have to guess if, and where to split name and edition. In
229        * fact \c "devel" could also be the version and \c "1.2.3" would be the
230        * release then.
231        *
232        * Assuming this Capability should be provided by some package in
233        * the \ref ResPool, we check this. If unprovided, we substitute the last,
234        * (or one but last) \c '-' by a \c '='. If the name part (without version)
235        * of the resulting Capability matches a package name (not provides!) in
236        * the \ref ResPool, this Capability is returned.
237        *
238        * Otherwise we return the Capability originally created from
239        * \a str_r.
240        *
241        * \note: As this method will access the global pool, the returned
242        * result depends on the pools content.
243        */
244       static Capability guessPackageSpec( const std::string & str_r );
245       /** \overload Taking an additional bool indicating whether \c str_r made
246        * a valid \ref Capability (\c true) or the result was was guessed by
247        * rewiting a \c '-' to \c '='. (\c false).
248        */
249       static Capability guessPackageSpec( const std::string & str_r, bool & rewrote_r );
250
251     public:
252       /** Expert backdoor. */
253       sat::detail::IdType id() const
254       { return _id; }
255     private:
256       /** Match two Capabilities */
257       static CapMatch _doMatch( sat::detail::IdType lhs,  sat::detail::IdType rhs );
258     private:
259       sat::detail::IdType _id;
260   };
261   ///////////////////////////////////////////////////////////////////
262
263   /** \relates Capability Stream output */
264   std::ostream & operator<<( std::ostream & str, const Capability & obj );
265
266   /** \relates Capability Detailed stream output */
267   std::ostream & dumpOn( std::ostream & str, const Capability & obj );
268
269   /** \relates Capability */
270   inline bool operator==( const Capability & lhs, const Capability & rhs )
271   { return lhs.id() == rhs.id(); }
272
273   /** \relates Capability */
274   inline bool operator!=( const Capability & lhs, const Capability & rhs )
275   { return lhs.id() != rhs.id(); }
276
277   /** \relates Capability Arbitrary order. */
278   inline bool operator<( const Capability & lhs, const Capability & rhs )
279   { return lhs.id() < rhs.id(); }
280
281   ///////////////////////////////////////////////////////////////////
282   //
283   //    CLASS NAME : CapDetail
284   //
285   /** Helper providing more detailed information about a \ref Capability.
286    *
287    * Capabilities are classified to be either \c SIMPLE:
288    * \code
289    *   name[.arch] [op edition]
290    *   with op := <|<=|=|>=|>|!=
291    * \endcode
292    * or formed by some \c EXPRESSION:
293    * \code
294    *   left_cap op right_cap
295    *   with op := AND|OR|WITH|NAMESPACE
296    * \endcode
297    */
298   class CapDetail: protected sat::detail::PoolMember
299   {
300     public:
301       enum Kind
302       {
303         NOCAP      = 0x00,
304         NAMED      = 0x01,
305         VERSIONED  = 0x02,
306         EXPRESSION = 0x04
307       };
308
309       /** Enum values corresponding with libsolv defines.
310        * \note MPL check in PoolImpl.cc
311       */
312       enum CapRel
313       {
314         REL_NONE      = 0,
315         CAP_AND       = 16,
316         CAP_OR        = 17,
317         CAP_WITH      = 18,
318         CAP_NAMESPACE = 19,
319         CAP_ARCH      = 20
320       };
321
322     public:
323       CapDetail()
324       : _kind( NOCAP ), _lhs( 0 ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 )
325       {}
326       explicit CapDetail( const Capability & cap_r )
327       : _kind( NOCAP ), _lhs( cap_r.id() ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 )
328       { _init(); }
329       explicit CapDetail( sat::detail::IdType id_r )
330       : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 )
331       { _init(); }
332
333     public:
334       Kind kind()         const { return _kind; }
335       bool isNull()       const { return _kind == NOCAP; }
336       bool isNamed()      const { return _kind == NAMED; }
337       bool isVersioned()  const { return _kind == VERSIONED; }
338       bool isSimple()     const { return _kind & (NAMED|VERSIONED); }
339       bool isExpression() const { return _kind == EXPRESSION; }
340
341       /** \name Is simple: <tt>name[.arch] [op edition]</tt> */
342       //@{
343       bool     hasArch()  const { return _archIfSimple; }
344       IdString arch()     const { return _archIfSimple ? IdString( _archIfSimple ) : IdString(); }
345       IdString name()     const { return isSimple()    ? IdString( _lhs ) : IdString(); }
346       Rel      op()       const { return isVersioned() ? Rel( _flag )     : Rel::ANY; }
347       Edition  ed()       const { return isVersioned() ? Edition( _rhs )  : Edition(); }
348       //@}
349
350       /** \name Is expression <tt>cap op cap</tt> */
351       //@{
352       Capability lhs()    const { return isExpression() ? Capability( _lhs ) : Capability::Null; }
353       CapRel     capRel() const { return isExpression() ? CapRel(_flag)      : REL_NONE; }
354       Capability rhs()    const { return isExpression() ? Capability( _rhs ) : Capability::Null; }
355      //@}
356
357     private:
358       void _init();
359     private:
360       Kind                _kind;
361       sat::detail::IdType _lhs;
362       sat::detail::IdType _rhs;
363       unsigned            _flag;
364       sat::detail::IdType _archIfSimple;
365   };
366   ///////////////////////////////////////////////////////////////////
367
368   /** \relates CapDetail Stream output */
369   std::ostream & operator<<( std::ostream & str, const CapDetail & obj );
370
371   /** \relates CapDetail Stream output */
372   std::ostream & operator<<( std::ostream & str, CapDetail::Kind obj );
373
374   /** \relates CapDetail Stream output */
375   std::ostream & operator<<( std::ostream & str, CapDetail::CapRel obj );
376
377   ///////////////////////////////////////////////////////////////////
378
379   inline CapDetail Capability::detail() const { return CapDetail( _id ); }
380
381   /////////////////////////////////////////////////////////////////
382 } // namespace zypp
383 ///////////////////////////////////////////////////////////////////
384
385 ZYPP_DEFINE_ID_HASHABLE( ::zypp::Capability );
386
387 #endif // ZYPP_CAPABILITY_H