1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
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"
28 #include "zypp/Pathname.h"
30 ///////////////////////////////////////////////////////////////////
32 { /////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////
36 { /////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////
42 /** Find pathnames matching a pattern.
44 * Glob glob( Glob::_BRACE );
45 * glob.add( "/somewherre/solverTestcase/ *{.xml,.xml.gz}" );
48 * std::list<Pathname> plist;
49 * Glob::collect( "/somewherre/solverTestcase/ *{.xml,.xml.gz}", Glob::_BRACE,
50 * std::back_inserter( plist ) );
52 * \see Manual page glob(3)
54 class Glob : private base::NonCopyable
57 typedef size_t size_type;
58 typedef const char * value_type;
60 /** Iterate NULL terminated \c char* array. */
61 class const_iterator : public boost::iterator_adaptor<
62 const_iterator // Derived
65 , boost::forward_traversal_tag // CategoryOrTraversal
66 , const value_type // Reference
71 : const_iterator::iterator_adaptor_( 0 )
74 explicit const_iterator( char ** _idx )
75 : const_iterator::iterator_adaptor_( _idx && *_idx ? _idx : 0 )
79 friend class boost::iterator_core_access;
82 if ( base_reference() && !*(++base_reference()) )
85 reference dereference() const
86 { return( base() ? *base() : 0 ); }
88 ///////////////////////////////////////////////////////////////////
91 /** Individual bits to combine in \ref Flags. */
93 _ERR = GLOB_ERR, //!< Return on read errors.
94 _MARK = GLOB_MARK, //!< Append a slash to each name.
95 _NOSORT = GLOB_NOSORT, //!< Don't sort the names.
96 // unsupported _DOOFFS = GLOB_DOOFFS, //!< Insert PGLOB->gl_offs NULLs.
97 _NOCHECK = GLOB_NOCHECK, //!< If nothing matches, return the pattern.
98 // autoapplied _APPEND = GLOB_APPEND, //!< Append to results of a previous call.
99 _NOESCAPE = GLOB_NOESCAPE, //!< Backslashes don't quote metacharacters.
100 _PERIOD = GLOB_PERIOD, //!< Leading `.' can be matched by metachars.
101 // unsupported _MAGCHAR = GLOB_MAGCHAR,//!< Set in gl_flags if any metachars seen.
102 _ALTDIRFUNC = GLOB_ALTDIRFUNC, //!< Use gl_opendir et al functions.
103 _BRACE = GLOB_BRACE, //!< Expand "{a,b}" to "a" "b".
104 _NOMAGIC = GLOB_NOMAGIC, //!< If no magic chars, return the pattern.
105 _TILDE = GLOB_TILDE, //!< Expand ~user and ~ to home directories.
106 _ONLYDIR = GLOB_ONLYDIR, //!< Match only directories.
107 _TILDE_CHECK = GLOB_TILDE_CHECK, //!< Like GLOB_TILDE but return an error if the user name is not available.
110 /** type Flags: Type-safe OR-combination of \ref Bits. */
111 ZYPP_DECLARE_FLAGS( Flags, Bits );
114 /** Default ctor optionally taking the default flags.
115 * The flags passed here are the default for \ref add.
116 * \see \ref setDefaultFlags
118 Glob( Flags flags_r = Flags() )
119 : _defaultFlags( flags_r )
122 /** Ctor adding pathnames matching \a pattern_r.
123 * The flags passed here are the default for \ref add.
124 * \see \ref setDefaultFlags
126 explicit Glob( const Pathname & pattern_r, Flags flags_r = Flags() )
127 : _defaultFlags( flags_r )
128 { add( pattern_r, flags_r ); }
130 explicit Glob( const std::string & pattern_r, Flags flags_r = Flags() )
131 : _defaultFlags( flags_r )
132 { add( pattern_r, flags_r ); }
134 explicit Glob( const char * pattern_r, Flags flags_r = Flags() )
135 : _defaultFlags( flags_r )
136 { add( pattern_r, flags_r ); }
140 { if ( _result ) ::globfree( &(*_result) ); }
142 /** Add pathnames matching \a pattern_r to the current result.
144 * Any flags passed here override the global default passed to
145 * the ctor. GLOB_APPEND is atomatically added to the flags
148 * This invalidates all iterators.
149 * \see \ref setDefaultFlags
150 * \return the value returned by ::glob().
152 int add( const Pathname & pattern_r, Flags flags_r = Flags() )
153 { return add( pattern_r.c_str(), flags_r ); }
155 int add( const std::string & pattern_r, Flags flags_r = Flags() )
156 { return add( pattern_r.c_str(), flags_r ); }
158 int add( const char * pattern_r, Flags flags_r = Flags() );
160 /** Clear all results found so far. \ref defaultFlags remain active. */
163 /** Clear all results and reset \ref defaultFlags. */
164 void reset( Flags flags_r = Flags() )
165 { clear(); setDefaultFlags( flags_r ); }
169 /** The default flags passed to \c ::glob(). */
170 Flags defaultFlags() const
171 { return _defaultFlags; }
173 /** Set the default flags passed to \c ::glob(). */
174 void setDefaultFlags( Flags flags_r = Flags() )
175 { _defaultFlags = flags_r; }
177 /** Returns the value returned by the last call to \c ::glob().
178 * \c Zero on successful completion. Otherwise \c GLOB_NOSPACE or \c GLOB_ABORTED
179 * or \c GLOB_NOMATCH.
181 int lastGlobReturn() const
182 { return _lastGlobReturn; }
185 /** Whether matches were found. */
187 { return ! ( _result && _result->gl_pathc ); }
189 /** The number of matches found so far. */
190 size_type size() const
191 { return( _result ? _result->gl_pathc : 0 ); }
193 /** Iterator pointing to the first result. */
194 const_iterator begin() const
195 { return( _result ? const_iterator( _result->gl_pathv ) : const_iterator() ); }
197 /** Iterator pointing behind the last result. */
198 const_iterator end() const
199 { return const_iterator(); }
203 /** \name Collecting Glob results to some _OutputIterator
205 * std::list<Pathname> p;
206 * Glob::collect( "/bin/a*.dat}", std::back_inserter(p) );
207 * Glob::collect( "/bin/a*{.xml,.xml.gz}", Glob::_BRACE, std::back_inserter(p) );
211 /** Write glob result to some \c OutputIterator. */
212 template<class _OutputIterator>
213 static int collect( const Pathname & pattern_r, _OutputIterator result_r )
214 { return collect( pattern_r.c_str(), Flags(), result_r ); }
216 template<class _OutputIterator>
217 static int collect( const std::string & pattern_r, _OutputIterator result_r )
218 { return collect( pattern_r.c_str(), Flags(), result_r ); }
220 template<class _OutputIterator>
221 static int collect( const char * & pattern_r, _OutputIterator result_r )
222 { return collect( pattern_r, Flags(), result_r ); }
224 /** \overload With \ref Flags */
225 template<class _OutputIterator>
226 static int collect( const Pathname & pattern_r, Flags flags_r, _OutputIterator result_r )
227 { return collect( pattern_r.c_str(), flags_r, result_r ); }
229 template<class _OutputIterator>
230 static int collect( const std::string & pattern_r, Flags flags_r, _OutputIterator result_r )
231 { return collect( pattern_r.c_str(), flags_r, result_r ); }
233 template<class _OutputIterator>
234 static int collect( const char * pattern_r, Flags flags_r, _OutputIterator result_r )
236 Glob glob( pattern_r, flags_r );
237 if ( glob.lastGlobReturn() == 0 )
238 for_( it, glob.begin(), glob.end() )
240 return glob.lastGlobReturn();
246 scoped_ptr< ::glob_t> _result;
247 DefaultIntegral<int,0> _lastGlobReturn;
249 ///////////////////////////////////////////////////////////////////
251 /** \relates Glob Stream output */
252 std::ostream & operator<<( std::ostream & str, const Glob & obj );
254 /** \relates Glob::const_iterator Stream output */
255 inline std::ostream & operator<<( std::ostream & str, const Glob::const_iterator & obj )
256 { return str << *obj; }
258 ZYPP_DECLARE_OPERATORS_FOR_FLAGS( Glob::Flags );
260 ///////////////////////////////////////////////////////////////////
262 /////////////////////////////////////////////////////////////////
263 } // namespace filesystem
264 ///////////////////////////////////////////////////////////////////
265 /////////////////////////////////////////////////////////////////
267 ///////////////////////////////////////////////////////////////////
268 #endif // ZYPP_GLOB_H