1 /*==========================================================================
2 * Copyright (c) 2004 University of Massachusetts. All Rights Reserved.
4 * Use of the Lemur Toolkit for Language Modeling and Information Retrieval
5 * is subject to the terms of the software license set forth in the LICENSE
6 * file included with this software, and also available at
7 * http://www.lemurproject.org/license.html
9 *==========================================================================
19 #include "indri/DirectoryIterator.hpp"
20 #include "lemur/lemur-platform.h"
22 #include "indri/Path.hpp"
26 // static construction
27 indri::file::DirectoryIterator
indri::file::DirectoryIterator::_end
;
29 void* directoryiterator_init( const std::string
& path
);
30 void directoryiterator_destroy(void* opaque
);
31 std::string
directoryiterator_current();
32 bool directoryiterator_next(void* opaque
);
33 bool directoryiterator_done(void* opaque
);
36 #ifdef LEMUR_USING_FINDFIRST
39 // Windows platform-specific directory iterator code
42 struct win_iter_data
{
48 void* directoryiterator_init( const std::string
& path
) {
49 win_iter_data
* d
= new win_iter_data
;
50 std::string searchPath
= indri::file::Path::combine( path
, "*" );
52 d
->handle
= ::FindFirstFile( searchPath
.c_str(), &d
->data
);
53 d
->done
= (d
->handle
== INVALID_HANDLE_VALUE
);
58 void directoryiterator_destroy( void* opaque
) {
59 win_iter_data
* d
= (win_iter_data
*) opaque
;
60 ::FindClose( d
->handle
);
64 std::string
directoryiterator_current( void* opaque
) {
66 win_iter_data
* d
= (win_iter_data
*) opaque
;
67 return d
->data
.cFileName
;
70 bool directoryiterator_next( void* opaque
) {
72 win_iter_data
* d
= (win_iter_data
*) opaque
;
75 d
->done
= (::FindNextFile( d
->handle
, &d
->data
) != TRUE
);
80 bool directoryiterator_done( void* opaque
) {
82 return ( (win_iter_data
*) opaque
)->done
;
87 #include <sys/types.h>
92 // Linux/Unix platform specific directory iterator code
95 struct unix_iter_data
{
102 void directoryiterator_dirent_init( unix_iter_data
& d
) {
103 d
.entry
= (struct dirent
*) malloc( sizeof(struct dirent
) + PATH_MAX
);
106 void directoryiterator_dirent_destroy( unix_iter_data
& d
) {
110 bool directoryiterator_next( void* opaque
) {
111 unix_iter_data
* d
= (unix_iter_data
*) opaque
;
112 struct dirent
* result
= 0;
113 readdir_r( d
->directory
, d
->entry
, &result
);
114 d
->done
= ( result
? false : true );
118 void directoryiterator_dirent_init( unix_iter_data
& d
) {
122 void directoryiterator_dirent_destroy( unix_iter_data
& d
) {
125 bool directoryiterator_next( void* opaque
) {
126 unix_iter_data
* d
= (unix_iter_data
*) opaque
;
127 d
->entry
= readdir( d
->directory
);
128 d
->done
= ( d
->entry
? false : true );
131 #endif // HAS_READDIR_R
133 void* directoryiterator_init( const std::string
& path
) {
134 unix_iter_data
* d
= new unix_iter_data
;
135 d
->directory
= opendir( path
.c_str() );
136 d
->done
= (d
->directory
== 0);
137 d
->entry
= (struct dirent
*) malloc( sizeof(struct dirent
) + PATH_MAX
+ 1);
140 directoryiterator_next(d
);
145 void directoryiterator_destroy( void* opaque
) {
146 unix_iter_data
* d
= (unix_iter_data
*) opaque
;
147 closedir( d
->directory
);
152 std::string
directoryiterator_current( void* opaque
) {
153 unix_iter_data
* d
= (unix_iter_data
*) opaque
;
154 if (! d
->entry
) return "";
155 return d
->entry
->d_name
;
158 bool directoryiterator_done( void* opaque
) {
159 unix_iter_data
* d
= (unix_iter_data
*) opaque
;
163 #endif // LEMUR_USING_FINDFIRST
166 // Begin platform independent code
169 const indri::file::DirectoryIterator
& indri::file::DirectoryIterator::end() {
173 void indri::file::DirectoryIterator::_copyCurrent() {
175 _current
= indri::file::Path::combine( _path
, directoryiterator_current( _platform
) );
177 _current
= directoryiterator_current( _platform
);
180 _current
= indri::file::Path::trim( _current
);
183 void indri::file::DirectoryIterator::_next() {
184 directoryiterator_next( _platform
);
187 std::string current
= directoryiterator_current( _platform
);
189 if( !directoryiterator_done( _platform
) &&
190 (current
== "." || current
== "..") ) {
195 indri::file::DirectoryIterator::DirectoryIterator() :
201 indri::file::DirectoryIterator::DirectoryIterator( const std::string
& path
, bool relative
) :
204 _path
= indri::file::Path::trim( path
);
205 _platform
= directoryiterator_init( _path
);
207 std::string current
= directoryiterator_current( _platform
);
209 if( !directoryiterator_done( _platform
) &&
210 (current
== "." || current
== "..") ) {
217 indri::file::DirectoryIterator::~DirectoryIterator() {
221 const std::string
& indri::file::DirectoryIterator::base() const {
225 void indri::file::DirectoryIterator::close() {
227 directoryiterator_destroy( _platform
);
232 void indri::file::DirectoryIterator::operator ++ () {
233 if( !directoryiterator_done( _platform
))
237 void indri::file::DirectoryIterator::operator ++ (int) {
238 if( !directoryiterator_done( _platform
))
242 bool indri::file::DirectoryIterator::operator == ( const DirectoryIterator
& other
) {
243 // this is a hack, but I think it's decent: we assume
244 // the user is comparing against end() in an iteration sense
245 return directoryiterator_done( _platform
) && &other
== &_end
;
248 const std::string
& indri::file::DirectoryIterator::operator * () {