Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / sat / LookupAttr.h
index 1d052e8..f547e22 100644 (file)
 #ifndef ZYPP_SAT_LOOKUPATTR_H
 #define ZYPP_SAT_LOOKUPATTR_H
 
-extern "C"
-{
-struct _Dataiterator;
-}
 #include <iosfwd>
 
 #include "zypp/base/PtrTypes.h"
@@ -29,6 +25,9 @@ namespace zypp
 { /////////////////////////////////////////////////////////////////
 
   class CheckSum;
+  class Match;
+  class MatchException;
+  class StrMatcher;
 
   ///////////////////////////////////////////////////////////////////
   namespace sat
@@ -56,6 +55,22 @@ namespace zypp
      *
      * Use \ref SolvAttr::allAttr to search all attributes.
      *
+     * To search for attributes located in a sub-structure (flexarray)
+     * you also have to pass the sub-structures attribute as parent.
+     * Passing \ref SolvAttr::allAttr a parent will lookup the attribute
+     * in \c any sub-structure. Few attributes are known to have a parent
+     * (\see \ref SolvAttr::parent). Setting those attributes will automatically
+     * initialize their parent value.
+     *
+     * \code
+     *    // Lookup all 'name' attributes:
+     *    sat::LookupAttr q( sat::SolvAttr::name );
+     *    // Lookup all 'name' attributes within a sub-structure 'data':
+     *    sat::LookupAttr q( sat::SolvAttr::name, sat::SolvAttr::data );
+     *    // Lookup all 'name' attributes within any sub-structure:
+     *    sat::LookupAttr q( sat::SolvAttr::name, sat::SolvAttr::allAttr );
+     * \endcode
+     *
      * \code
      *  // look for all attributes of one solvable
      *  void ditest( sat::Solvable slv_r )
@@ -92,6 +107,9 @@ namespace zypp
     class LookupAttr
     {
       public:
+        typedef MatchException Exception;
+
+      public:
         typedef unsigned size_type;
 
         /** Specify the where to look for the attribule. */
@@ -106,12 +124,18 @@ namespace zypp
 
         /** Lookup \ref SolvAttr in \ref Pool (all repositories). */
         explicit LookupAttr( SolvAttr attr_r, Location = SOLV_ATTR );
+        /** \overload SolvAttr within sub-structure \a parent_r. */
+        LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Location = SOLV_ATTR );
 
         /** Lookup \ref SolvAttr in one\ref Repository. */
-        explicit LookupAttr( SolvAttr attr_r, Repository repo_r, Location = SOLV_ATTR );
+        LookupAttr( SolvAttr attr_r, Repository repo_r, Location = SOLV_ATTR );
+        /** \overload SolvAttr within sub-structure \a parent_r. */
+        LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Repository repo_r, Location = SOLV_ATTR );
 
         /** Lookup \ref SolvAttr in one \ref Solvable. */
         LookupAttr( SolvAttr attr_r, Solvable solv_r );
+        /** \overload SolvAttr within sub-structure \a parent_r. */
+        LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Solvable solv_r );
 
       public:
         /** \name Search result. */
@@ -133,8 +157,9 @@ namespace zypp
         */
         size_type size() const;
 
-        /** TransformIterator returning an \ref iterator vaue of type \c _ResultT. */
-        template<class _ResultT, class _AttrT = _ResultT> class transformIterator;
+        /** TransformIterator returning an \ref iterator vaue of type \c TResult. */
+        template<class TResult, class TAttr = TResult>
+       class TransformIterator;
         //@}
 
       public:
@@ -147,26 +172,54 @@ namespace zypp
         void setAttr( SolvAttr attr_r );
         //@}
 
+        /** \name Restrict attributes to match a pattern. */
+        //@{
+        /** The pattern to match.
+         * You can also evaluate \ref StrMatcher in a boolean context,
+         * in order to test whether an \ref StrMatcher is set:
+         * \code
+         *   LookupAttr q;
+         *   if ( q.strMatcher() )
+         *     ...; // an StrMatcher is set
+         * \endcode
+        */
+        const StrMatcher & strMatcher() const;
+
+        /** Set the pattern to match.
+         * \throws MatchException Any of the exceptions thrown by \ref StrMatcher::compile.
+         */
+        void setStrMatcher( const StrMatcher & matcher_r );
+
+        /** Reset the pattern to match. */
+        void resetStrMatcher();
+       //@}
+
       public:
         /** \name Where to search. */
         //@{
-        /** Wheter to search in \ref Pool. */
+        /** Whether to search in \ref Pool. */
         bool pool() const;
 
         /** Set search in \ref Pool (all repositories). */
         void setPool( Location = SOLV_ATTR );
 
-        /** Wheter to search in one \ref Repository. */
+        /** Whether to search in one \ref Repository. */
         Repository repo() const;
 
         /** Set search in one \ref Repository. */
         void setRepo( Repository repo_r, Location = SOLV_ATTR );
 
-        /** Wheter to search in one \ref Solvable. */
+        /** Whether to search in one \ref Solvable. */
         Solvable solvable() const;
 
         /** Set search in one \ref Solvable. */
         void setSolvable( Solvable solv_r );
+
+        /** Whether to search within a sub-structure (\ref SolvAttr::noAttr if not) */
+        SolvAttr parent() const;
+
+        /** Set search within a sub-structure (\ref SolvAttr::noAttr for none) */
+        void setParent( SolvAttr attr_r );
         //@}
 
       private:
@@ -185,7 +238,7 @@ namespace zypp
     //
     // CLASS NAME : LookupRepoAttr
     //
-    /** Lightweight repositor attribute value lookup.
+    /** Lightweight repository attribute value lookup.
      *
      * This is just a convenience class that overloads all
      * \ref LookupAttr methods which take a \ref LookupAttr::Location
@@ -227,6 +280,65 @@ namespace zypp
     };
     ///////////////////////////////////////////////////////////////////
 
+    namespace detail
+    {
+      /** Wrapper around sat \c detail::CDataiterator.
+       *
+       * Manages copy and assign, and release of allocated
+       * resources like datamatcher inside the dataiterator.
+       * Also maintains a copy of the matchstring in order to
+       * keep the char* passed to the dataiterator valid.
+       */
+      class DIWrap
+      {
+        public:
+          /** \c NULL \c detail::CDataiterator */
+          DIWrap()
+          : _dip( 0 )
+          {}
+          /** Initializes */
+          DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r,
+                  const std::string & mstring_r = std::string(), int flags_r = 0 );
+          /** \overload to catch \c NULL \a mstring_r. */
+          DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r,
+                  const char * mstring_r, int flags_r = 0 );
+          DIWrap( const DIWrap & rhs );
+          ~DIWrap();
+        public:
+          void swap( DIWrap & rhs )
+          {
+            if ( &rhs != this ) // prevent self assign!
+            {
+              std::swap( _dip, rhs._dip );
+              std::swap( _mstring, rhs._mstring );
+            }
+          }
+          DIWrap & operator=( const DIWrap & rhs )
+          {
+            if ( &rhs != this ) // prevent self assign!
+              DIWrap( rhs ).swap( *this );
+            return *this;
+          }
+          void reset()
+          { DIWrap().swap( *this ); }
+        public:
+          /** Evaluate in a boolean context <tt>( _dip != NULL )</tt>. */
+          explicit operator bool() const
+          { return _dip; }
+
+        public:
+          detail::CDataiterator * operator->() const  { return _dip; }
+          detail::CDataiterator * get()        const  { return _dip; }
+          const std::string & getstr()   const  { return _mstring; }
+
+       private:
+          detail::CDataiterator * _dip;
+          std::string _mstring;
+      };
+      /** \relates DIWrap Stream output. */
+      std::ostream & operator<<( std::ostream & str, const DIWrap & obj );
+    }
+
     ///////////////////////////////////////////////////////////////////
     //
     // CLASS NAME : LookupAttr::iterator
@@ -237,7 +349,7 @@ namespace zypp
      */
     class LookupAttr::iterator : public boost::iterator_adaptor<
         iterator                       // Derived
-        , ::_Dataiterator *            // Base
+        , detail::CDataiterator *            // Base
         , detail::IdType               // Value
         , boost::forward_traversal_tag // CategoryOrTraversal
         , detail::IdType               // Reference
@@ -266,6 +378,12 @@ namespace zypp
         /** Immediately advance to the next \ref Repository. */
         void skipRepo()
         { nextSkipRepo(); increment(); }
+
+        /** Stop after all matches in the current \ref Solvable are processed. */
+        void stayInThisSolvable();
+
+        /** Stop after all matches in the current \ref Repository are processed. */
+        void stayInThisRepo();
         //@}
 
         /** \name Current position info. */
@@ -278,6 +396,10 @@ namespace zypp
 
         /** The current \ref SolvAttr. */
         SolvAttr inSolvAttr() const;
+
+        /** Whether this points to the end of a query (Iterator is invalid). */
+        bool atEnd() const
+        { return !_dip; }
         //@}
 
         /** \name Test attribute value type. */
@@ -291,7 +413,7 @@ namespace zypp
         /** Whether this is a string attribute. */
         bool solvAttrString() const;
 
-        /** *Whether this string attribute is available as \ref IdString. */
+        /** Whether this string attribute is available as \ref IdString. */
         bool solvAttrIdString() const;
 
         /** Whether this is a CheckSum attribute.*/
@@ -308,6 +430,13 @@ namespace zypp
          *
          * These are usable iff \ref solvAttrSubEntry is \c true.
          *
+         * \note Unfortunately the underlying libsolv dataiterator as returned
+         * by \ref subBegin and \ref subFind loses some context when being created.
+         * Thus it's not possible to invoke \ref subBegin and \ref subFind on an
+         * iterator that was previously returned by one of those methods. The result
+         * will be an \c end iterator. For the same reason it is not possible for an
+         * iterator to leave the sub-structure again.
+         *
          * \code
          * // Lookup all "update:reference" entries for a specific solvable
          * sat::LookupAttr q( sat::SolvAttr::updateReference, p->satSolvable() );
@@ -327,7 +456,7 @@ namespace zypp
          * \endcode
          */
         //@{
-        /** Wheter the sub-structure is empty. */
+        /** Whether the sub-structure is empty. */
         bool subEmpty() const;
 
         /** Ammount of attributes in the sub-structure.
@@ -366,6 +495,8 @@ namespace zypp
         unsigned asUnsigned() const;
         /** \overload */
         bool asBool() const;
+        /** \overload */
+        unsigned long long asUnsignedLL() const;
 
         /** Conversion to string types. */
         const char * c_str() const;
@@ -381,14 +512,20 @@ namespace zypp
          * via \ref c_str and \ref asString.
          */
         IdString idStr() const;
+       /** \overload Directly returning the \c Id */
+        detail::IdType id() const
+        { return idStr().id(); }
 
         /** As \ref CheckSum. */
         CheckSum asCheckSum() const;
 
         /** Templated return type.
-         * Specialized for supported types.
+         * Per default assumes an Id based type, so try to construct
+         * it from the Id.
+         *
+         * Should be specialized for supported types above.
         */
-        template<class _Tp> _Tp asType() const;
+        template<class Tp> Tp asType() const { return Tp(id()); }
         //@}
 
         ///////////////////////////////////////////////////////////////////
@@ -405,16 +542,14 @@ namespace zypp
 
       public:
         /**
-         * C-tor taking over ownership of the passed scoped _Dataiterator*
+         * C-tor taking over ownership of the passed \c detail::CDataiterator
          * and doing it's first iteration (::dataiterator_step)
          */
-        iterator( scoped_ptr< ::_Dataiterator> & dip_r );
+        iterator( detail::DIWrap & dip_r );
 
       private:
         friend class boost::iterator_core_access;
 
-        ::_Dataiterator * cloneFrom( const ::_Dataiterator * rhs );
-
         template <class OtherDerived, class OtherIterator, class V, class C, class R, class D>
         bool equal( const boost::iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> & rhs ) const
         {
@@ -422,7 +557,7 @@ namespace zypp
               && ( ! base() || dip_equal( *base(), *rhs.base() ) );
         }
 
-        bool dip_equal( const ::_Dataiterator & lhs, const ::_Dataiterator & rhs ) const;
+        bool dip_equal( const detail::CDataiterator & lhs, const detail::CDataiterator & rhs ) const;
 
         detail::IdType dereference() const;
 
@@ -430,10 +565,10 @@ namespace zypp
 
       public:
         /** Expert backdoor. */
-        ::_Dataiterator * get() const
+        detail::CDataiterator * get() const
         { return _dip.get(); }
       private:
-        scoped_ptr< ::_Dataiterator> _dip;
+        detail::DIWrap _dip;
     };
     ///////////////////////////////////////////////////////////////////
 
@@ -446,12 +581,14 @@ namespace zypp
     //@{
     template<> inline int          LookupAttr::iterator::asType<int>()          const { return asInt(); }
     template<> inline unsigned     LookupAttr::iterator::asType<unsigned>()     const { return asUnsigned(); }
+    template<> inline unsigned long long LookupAttr::iterator::asType<unsigned long long>()     const { return asUnsignedLL(); }
     template<> inline bool         LookupAttr::iterator::asType<bool>()         const { return asBool(); }
     template<> inline const char * LookupAttr::iterator::asType<const char *>() const { return c_str(); }
     template<> inline std::string  LookupAttr::iterator::asType<std::string>()  const { return asString(); }
     template<> inline IdString     LookupAttr::iterator::asType<IdString>()     const { return idStr(); }
+    template<>        CheckSum     LookupAttr::iterator::asType<CheckSum>()     const;
 
-    template<class _ResultT, class _AttrT>
+    template<class TResult, class TAttr>
     class ArrayAttr;
     //@}
 
@@ -463,10 +600,10 @@ namespace zypp
 ///////////////////////////////////////////////////////////////////
 
 /** \relates LookupAttr::iterator Stream output of the underlying iterator for debug. */
-std::ostream & operator<<( std::ostream & str, const ::_Dataiterator * obj );
+std::ostream & operator<<( std::ostream & str, const zypp::sat::detail::CDataiterator * obj );
 
 /** \relates LookupAttr::iterator Stream output of the underlying iterator for debug. */
-inline std::ostream & operator<<( std::ostream & str, const ::_Dataiterator & obj )
+inline std::ostream & operator<<( std::ostream & str, const zypp::sat::detail::CDataiterator & obj )
 { return str << &obj; }
 
 #endif // ZYPP_SAT_LOOKUPATTR_H