a96d72c143cb9ca4977fab7df92c6687e6392b33
[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 #include "zypp/Pathname.h"
29
30 ///////////////////////////////////////////////////////////////////
31 namespace zypp
32 { /////////////////////////////////////////////////////////////////
33
34   ///////////////////////////////////////////////////////////////////
35   namespace filesystem
36   { /////////////////////////////////////////////////////////////////
37
38     ///////////////////////////////////////////////////////////////////
39     //
40     //  CLASS NAME : Glob
41     //
42     /** Find pathnames matching a pattern.
43      * \code
44      * Glob glob( Glob::kBrace );
45      * glob.add( "/somewhere/solverTestcase/ *{.xml,.xml.gz}" );
46      * glob.add( "/somewhere/else/a*" );
47      * for_( it, glob.begin(), glob.end() )
48      *   ...
49      * \endcode
50      * \code
51      * std::list<Pathname> plist;
52      * Glob::collect( "/somewherre/solverTestcase/ *{.xml,.xml.gz}", Glob::kBrace,
53      *                std::back_inserter( plist ) );
54      * \endcode
55      * \see Manual page glob(3)
56      */
57     class Glob : private base::NonCopyable
58     {
59       public:
60         typedef size_t size_type;
61         typedef const char * value_type;
62
63         /** Iterate NULL terminated \c char* array. */
64         class const_iterator : public boost::iterator_adaptor<
65               const_iterator                // Derived
66             , char **                       // Base
67             , value_type                    // Value
68             , boost::forward_traversal_tag  // CategoryOrTraversal
69             , const value_type              // Reference
70             >
71         {
72           public:
73             const_iterator()
74             : const_iterator::iterator_adaptor_( 0 )
75             {}
76
77             explicit const_iterator( char ** _idx )
78             : const_iterator::iterator_adaptor_( _idx && *_idx ? _idx : 0 )
79             {}
80
81           private:
82             friend class boost::iterator_core_access;
83             void increment()
84             {
85               if ( base_reference() && !*(++base_reference()) )
86                 base_reference() = 0;
87             }
88             reference dereference() const
89             { return( base() ? *base() : 0 ); }
90         };
91         ///////////////////////////////////////////////////////////////////
92
93       public:
94         /** Individual bits to combine in \ref Flags. */
95         enum Bits {
96           kErr          = GLOB_ERR,             //!< Return on read errors.
97           kMark         = GLOB_MARK,            //!< Append a slash to each name.
98           kNoSort       = GLOB_NOSORT,          //!< Don't sort the names.
99           // unsupported kDoOffs = GLOB_DOOFFS, //!< Insert PGLOB->gl_offs NULLs.
100           kNoCheck      = GLOB_NOCHECK,         //!< If nothing matches, return the pattern.
101           // autoapplied kAppend = GLOB_APPEND, //!< Append to results of a previous call.
102           kNoEscape     = GLOB_NOESCAPE,        //!< Backslashes don't quote metacharacters.
103           kPeriod       = GLOB_PERIOD,          //!< Leading `.' can be matched by metachars.
104           // unsupported kMagChar = GLOB_MAGCHAR,//!< Set in gl_flags if any metachars seen.
105           kAltDirFunc   = GLOB_ALTDIRFUNC,      //!< Use gl_opendir et al functions.
106           kBrace        = GLOB_BRACE,           //!< Expand "{a,b}" to "a" "b".
107           kNoMagic      = GLOB_NOMAGIC,         //!< If no magic chars, return the pattern.
108           kTilde        = GLOB_TILDE,           //!< Expand ~user and ~ to home directories.
109           kOnlyDir      = GLOB_ONLYDIR,         //!< Match only directories.
110           kTildeCheck   = GLOB_TILDE_CHECK,     //!< Like GLOB_TILDE but return an error if the user name is not available.
111         };
112
113         /** type Flags: Type-safe OR-combination of \ref Bits. */
114         ZYPP_DECLARE_FLAGS( Flags, Bits );
115
116       public:
117         /** Default ctor optionally taking the default flags.
118          * The flags passed here are the default for \ref add.
119          * \see \ref setDefaultFlags
120         */
121         Glob( Flags flags_r = Flags() )
122         : _defaultFlags( flags_r )
123         {}
124
125         /** Ctor adding pathnames matching \a pattern_r.
126          * The flags passed here are the default for \ref add.
127          * \see \ref setDefaultFlags
128         */
129         explicit Glob( const Pathname & pattern_r, Flags flags_r = Flags() )
130         : _defaultFlags( flags_r )
131         { add( pattern_r, flags_r ); }
132         /** \overload */
133         explicit Glob( const std::string & pattern_r, Flags flags_r = Flags() )
134         : _defaultFlags( flags_r )
135         { add( pattern_r, flags_r ); }
136         /** \overload */
137         explicit Glob( const char * pattern_r, Flags flags_r = Flags() )
138         : _defaultFlags( flags_r )
139         { add( pattern_r, flags_r ); }
140
141         /** Dtor */
142         ~Glob()
143         { if ( _result ) ::globfree( &(*_result) ); }
144
145         /** Add pathnames matching \a pattern_r to the current result.
146          *
147          * Any flags passed here override the global default passed to
148          * the ctor. GLOB_APPEND is atomatically added to the flags
149          * f needed.
150          *
151          * This invalidates all iterators.
152          * \see \ref setDefaultFlags
153          * \return the value returned by ::glob().
154          */
155         int add( const Pathname & pattern_r, Flags flags_r = Flags() )
156         { return add( pattern_r.c_str(), flags_r ); }
157         /** \overload */
158         int add( const std::string & pattern_r, Flags flags_r = Flags() )
159         { return add( pattern_r.c_str(), flags_r ); }
160         /** \overload */
161         int add( const char * pattern_r, Flags flags_r = Flags() );
162
163         /** Clear all results found so far. \ref defaultFlags remain active. */
164         void clear();
165
166         /** Clear all results and reset \ref defaultFlags. */
167         void reset( Flags flags_r = Flags() )
168         { clear(); setDefaultFlags( flags_r ); }
169
170
171       public:
172         /** The default flags passed to \c ::glob(). */
173         Flags defaultFlags() const
174         { return _defaultFlags; }
175
176         /** Set the default flags passed to \c ::glob(). */
177         void setDefaultFlags( Flags flags_r = Flags() )
178         { _defaultFlags = flags_r; }
179
180         /** Returns the value returned by the last call to \c ::glob().
181          * \c Zero on successful completion. Otherwise \c GLOB_NOSPACE or \c GLOB_ABORTED
182          * or \c GLOB_NOMATCH.
183          */
184         int lastGlobReturn() const
185         { return _lastGlobReturn; }
186
187       public:
188         /** Whether matches were found. */
189         bool empty() const
190         { return ! ( _result && _result->gl_pathc ); }
191
192         /** The number of matches found so far. */
193         size_type size() const
194         { return( _result ? _result->gl_pathc : 0 ); }
195
196         /** Iterator pointing to the first result. */
197         const_iterator begin() const
198         { return( _result ? const_iterator( _result->gl_pathv ) : const_iterator() ); }
199
200         /** Iterator pointing behind the last result. */
201         const_iterator end() const
202         { return const_iterator(); }
203
204       public:
205
206         /** \name Collecting Glob results to some TOutputIterator
207          * \code
208          * std::list<Pathname> p;
209          * Glob::collect( "/bin/a*.dat}", std::back_inserter(p) );
210          * Glob::collect( "/bin/a*{.xml,.xml.gz}", Glob::kBrace, std::back_inserter(p) );
211          * \endcode
212          */
213         //@{
214         /** Write glob result to some \c OutputIterator. */
215         template<class TOutputIterator>
216         static int collect( const Pathname & pattern_r, TOutputIterator result_r )
217         { return collect( pattern_r.c_str(), Flags(), result_r ); }
218         /** \overload */
219         template<class TOutputIterator>
220         static int collect( const std::string & pattern_r, TOutputIterator result_r )
221         { return collect( pattern_r.c_str(), Flags(), result_r ); }
222         /** \overload */
223         template<class TOutputIterator>
224         static int collect( const char * pattern_r, TOutputIterator result_r )
225         { return collect( pattern_r, Flags(), result_r ); }
226
227         /** \overload With \ref Flags */
228         template<class TOutputIterator>
229         static int collect( const Pathname & pattern_r, Flags flags_r, TOutputIterator result_r )
230         { return collect( pattern_r.c_str(), flags_r, result_r ); }
231         /** \overload */
232         template<class TOutputIterator>
233         static int collect( const std::string & pattern_r, Flags flags_r, TOutputIterator result_r )
234         { return collect( pattern_r.c_str(), flags_r, result_r ); }
235         /** \overload */
236         template<class TOutputIterator>
237         static int collect( const char * pattern_r, Flags flags_r, TOutputIterator result_r )
238         {
239           Glob glob( pattern_r, flags_r );
240           if ( glob.lastGlobReturn() == 0 )
241             for_( it, glob.begin(), glob.end() )
242               (*result_r)++ = typename TOutputIterator::container_type::value_type(*it);
243           return glob.lastGlobReturn();
244         }
245         //@}
246
247       private:
248         Flags _defaultFlags;
249         scoped_ptr< ::glob_t> _result;
250         DefaultIntegral<int,0> _lastGlobReturn;
251     };
252     ///////////////////////////////////////////////////////////////////
253
254     /** \relates Glob Stream output */
255     std::ostream & operator<<( std::ostream & str, const Glob & obj );
256
257     /** \relates Glob::const_iterator Stream output */
258     inline std::ostream & operator<<( std::ostream & str, const Glob::const_iterator & obj )
259     { return str << *obj; }
260
261     ZYPP_DECLARE_OPERATORS_FOR_FLAGS( Glob::Flags );
262
263     ///////////////////////////////////////////////////////////////////
264
265     /////////////////////////////////////////////////////////////////
266   } // namespace filesystem
267   ///////////////////////////////////////////////////////////////////
268   /////////////////////////////////////////////////////////////////
269 } // namespace zypp
270 ///////////////////////////////////////////////////////////////////
271 #endif // ZYPP_GLOB_H