- Linking libexpat required to support loading helix files.
[platform/upstream/libzypp.git] / zypp / Glob.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/Glob.h
10  *
11 */
12 #ifndef ZYPP_GLOB_H
13 #define ZYPP_GLOB_H
14
15 extern "C"
16 {
17 #include <glob.h>
18 }
19
20 #include <iosfwd>
21
22 #include "zypp/base/Easy.h"
23 #include "zypp/base/Flags.h"
24 #include "zypp/base/Iterator.h"
25 #include "zypp/base/NonCopyable.h"
26 #include "zypp/base/DefaultIntegral.h"
27
28 ///////////////////////////////////////////////////////////////////
29 namespace zypp
30 { /////////////////////////////////////////////////////////////////
31
32   ///////////////////////////////////////////////////////////////////
33   namespace filesystem
34   { /////////////////////////////////////////////////////////////////
35
36     ///////////////////////////////////////////////////////////////////
37     //
38     //  CLASS NAME : Glob
39     //
40     /** Find pathnames matching a pattern.
41      * \code
42      * Glob glob( Glob::_BRACE );
43      * glob.add( "/somewherre/solverTestcase/ *{.xml,.xml.gz}" );
44      * \endcode
45      * \code
46      * std::list<Pathname> plist;
47      * Glob::collect( "/somewherre/solverTestcase/ *{.xml,.xml.gz}", Glob::_BRACE,
48      *                std::back_inserter( plist ) );
49      * \endcode
50      * \see Manual page glob(3)
51      */
52     class Glob : private base::NonCopyable
53     {
54       public:
55         typedef size_t size_type;
56         typedef const char * value_type;
57
58         /** Iterate NULL terminated \c char* array. */
59         class const_iterator : public boost::iterator_adaptor<
60               const_iterator                // Derived
61             , char **                       // Base
62             , value_type                    // Value
63             , boost::forward_traversal_tag  // CategoryOrTraversal
64             , const value_type &            // Reference
65             >
66         {
67           public:
68             const_iterator()
69             : const_iterator::iterator_adaptor_( 0 )
70             {}
71
72             explicit const_iterator( char ** _idx )
73             : const_iterator::iterator_adaptor_( _idx && *_idx ? _idx : 0 )
74             {}
75
76           private:
77             friend class boost::iterator_core_access;
78             void increment()
79             {
80               if ( base_reference() && !*(++base_reference()) )
81                 base_reference() = 0;
82             }
83         };
84         ///////////////////////////////////////////////////////////////////
85
86       public:
87         /** Individual bits to combine in \ref Flags. */
88         enum Bits {
89           _ERR          = GLOB_ERR,             //!< Return on read errors.
90           _MARK         = GLOB_MARK,            //!< Append a slash to each name.
91           _NOSORT       = GLOB_NOSORT,          //!< Don't sort the names.
92           // unsupported _DOOFFS = GLOB_DOOFFS, //!< Insert PGLOB->gl_offs NULLs.
93           _NOCHECK      = GLOB_NOCHECK,         //!< If nothing matches, return the pattern.
94           // autoapplied _APPEND = GLOB_APPEND, //!< Append to results of a previous call.
95           _NOESCAPE     = GLOB_NOESCAPE,        //!< Backslashes don't quote metacharacters.
96           _PERIOD       = GLOB_PERIOD,          //!< Leading `.' can be matched by metachars.
97           // unsupported _MAGCHAR = GLOB_MAGCHAR,//!< Set in gl_flags if any metachars seen.
98           _ALTDIRFUNC   = GLOB_ALTDIRFUNC,      //!< Use gl_opendir et al functions.
99           _BRACE        = GLOB_BRACE,           //!< Expand "{a,b}" to "a" "b".
100           _NOMAGIC      = GLOB_NOMAGIC,         //!< If no magic chars, return the pattern.
101           _TILDE        = GLOB_TILDE,           //!< Expand ~user and ~ to home directories.
102           _ONLYDIR      = GLOB_ONLYDIR,         //!< Match only directories.
103           _TILDE_CHECK  = GLOB_TILDE_CHECK,     //!< Like GLOB_TILDE but return an error if the user name is not available.
104         };
105
106         /** type Flags: Type-safe OR-combination of \ref Bits. */
107         ZYPP_DECLARE_FLAGS( Flags, Bits );
108
109       public:
110         /** Default ctor optionally taking the default flags.
111          * The flags passed here are the default for \ref add.
112         */
113         Glob( Flags flags_r = Flags() )
114         : _defaultFlags( flags_r )
115         {}
116
117         /** Ctor adding pathnames matching \a pattern_r.
118          * The flags passed here are the default for \ref add.
119         */
120         explicit Glob( const std::string & pattern_r, Flags flags_r = Flags() )
121         : _defaultFlags( flags_r )
122         { add( pattern_r, flags_r ); }
123
124         /** Dtor */
125         ~Glob()
126         { if ( _result ) ::globfree( &(*_result) ); }
127
128         /** Add pathnames matching \a pattern_r to the current result.
129          *
130          * The flags passed here override the global default passed to
131          * the ctor. GLOB_APPEND is atomatically added to the flags if needed.
132          *
133          * This invalidates all iterators.
134          * \see \ref setDefaultFlags
135          * \return the value returned by ::glob().
136          */
137         int add( const std::string & pattern_r, Flags flags_r = Flags() );
138
139       public:
140         /** The default flags passed to \c ::glob(). */
141         Flags defaultFlags() const
142         { return _defaultFlags; }
143
144         /** Set the default flags passed to \c ::glob(). */
145         void setDefaultFlags( Flags flags_r = Flags() )
146         { _defaultFlags = flags_r; }
147
148         /** Returns the value returned by the last call to \c ::glob().
149          * \c Zero on successful completion. Otherwise \c GLOB_NOSPACE or \c GLOB_ABORTED
150          * or \c GLOB_NOMATCH.
151          */
152         int lastGlobReturn() const
153         { return _lastGlobReturn; }
154
155       public:
156         /** Whether matches were found. */
157         bool empty() const
158         { return ! ( _result && _result->gl_pathc ); }
159
160         /** The number of matches found so far. */
161         size_type size() const
162         { return( _result ? _result->gl_pathc : 0 ); }
163
164         /** Iterator pointing to the first result. */
165         const_iterator begin() const
166         { return( _result ? const_iterator( _result->gl_pathv ) : const_iterator() ); }
167
168         /** Iterator pointing behind the last result. */
169         const_iterator end() const
170         { return const_iterator(); }
171
172       public:
173
174         /** \name Collecting Glob results to some _OutputIterator
175          * \code
176          * std::list<Pathname> p;
177          * Glob::collect( "/bin/m*", std::back_inserter(p) );
178          * \endcode
179          */
180         //@{
181         /** Write glob result to some \c OutputIterator. */
182         template<class _OutputIterator>
183         static int collect( const std::string & pattern_r, Flags flags_r, _OutputIterator result_r )
184         {
185           Glob glob( pattern_r, flags_r );
186           if ( glob.lastGlobReturn() == 0 )
187             for_( it, glob.begin(), glob.end() )
188               (*result_r)++ = *it;
189           return glob.lastGlobReturn();
190         }
191         /** \overload */
192         template<class _OutputIterator>
193         static int collect( const std::string & pattern_r, _OutputIterator result_r )
194         { return collect( pattern_r, Flags(), result_r ); }
195         //@}
196
197       private:
198         Flags _defaultFlags;
199         scoped_ptr< ::glob_t> _result;
200         DefaultIntegral<int,0> _lastGlobReturn;
201     };
202     ///////////////////////////////////////////////////////////////////
203
204     /** \relates Glob Stream output */
205     std::ostream & operator<<( std::ostream & str, const Glob & obj );
206
207     ZYPP_DECLARE_OPERATORS_FOR_FLAGS( Glob::Flags );
208
209     ///////////////////////////////////////////////////////////////////
210
211     /////////////////////////////////////////////////////////////////
212   } // namespace filesystem
213   ///////////////////////////////////////////////////////////////////
214   /////////////////////////////////////////////////////////////////
215 } // namespace zypp
216 ///////////////////////////////////////////////////////////////////
217 #endif // ZYPP_GLOB_H