Initial import into git.
[galago.git] / cpp / galago / contrib / indri / src / DirectoryIterator.cpp
blob1ccfe652715d2aeecd9901186e305c545e2f65ee
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 *==========================================================================
14 // DirectoryIterator
16 // 26 May 2004 -- tds
19 #include "indri/DirectoryIterator.hpp"
20 #include "lemur/lemur-platform.h"
21 #include <assert.h>
22 #include "indri/Path.hpp"
23 #include <vector>
24 #include <iostream>
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 {
43 HANDLE handle;
44 WIN32_FIND_DATA data;
45 bool done;
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);
55 return d;
58 void directoryiterator_destroy( void* opaque ) {
59 win_iter_data* d = (win_iter_data*) opaque;
60 ::FindClose( d->handle );
61 delete d;
64 std::string directoryiterator_current( void* opaque ) {
65 assert( opaque );
66 win_iter_data* d = (win_iter_data*) opaque;
67 return d->data.cFileName;
70 bool directoryiterator_next( void* opaque ) {
71 assert( opaque );
72 win_iter_data* d = (win_iter_data*) opaque;
74 if( !d->done )
75 d->done = (::FindNextFile( d->handle, &d->data ) != TRUE);
77 return d->done;
80 bool directoryiterator_done( void* opaque ) {
81 assert( opaque );
82 return ( (win_iter_data*) opaque )->done;
85 #else
87 #include <sys/types.h>
88 #include <dirent.h>
89 #include <limits.h>
92 // Linux/Unix platform specific directory iterator code
95 struct unix_iter_data {
96 DIR* directory;
97 bool done;
98 struct dirent* entry;
101 #ifdef HAS_READDIR_R
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 ) {
107 free( d.entry );
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 );
115 return d->done;
117 #else
118 void directoryiterator_dirent_init( unix_iter_data& d ) {
119 d.entry = 0;
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 );
129 return d->done;
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);
139 if( !d->done )
140 directoryiterator_next(d);
142 return d;
145 void directoryiterator_destroy( void* opaque ) {
146 unix_iter_data* d = (unix_iter_data*) opaque;
147 closedir( d->directory );
148 free( d->entry );
149 delete d;
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;
160 return d->done;
163 #endif // LEMUR_USING_FINDFIRST
166 // Begin platform independent code
169 const indri::file::DirectoryIterator& indri::file::DirectoryIterator::end() {
170 return _end;
173 void indri::file::DirectoryIterator::_copyCurrent() {
174 if( _relative ) {
175 _current = indri::file::Path::combine( _path, directoryiterator_current( _platform ) );
176 } else {
177 _current = directoryiterator_current( _platform );
180 _current = indri::file::Path::trim( _current );
183 void indri::file::DirectoryIterator::_next() {
184 directoryiterator_next( _platform );
185 _copyCurrent();
187 std::string current = directoryiterator_current( _platform );
189 if( !directoryiterator_done( _platform ) &&
190 (current == "." || current == "..") ) {
191 _next();
195 indri::file::DirectoryIterator::DirectoryIterator() :
196 _relative(false),
197 _platform(0)
201 indri::file::DirectoryIterator::DirectoryIterator( const std::string& path, bool relative ) :
202 _relative(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 == "..") ) {
211 _next();
214 _copyCurrent();
217 indri::file::DirectoryIterator::~DirectoryIterator() {
218 close();
221 const std::string& indri::file::DirectoryIterator::base() const {
222 return _path;
225 void indri::file::DirectoryIterator::close() {
226 if( _platform ) {
227 directoryiterator_destroy( _platform );
228 _platform = 0;
232 void indri::file::DirectoryIterator::operator ++ () {
233 if( !directoryiterator_done( _platform ))
234 _next();
237 void indri::file::DirectoryIterator::operator ++ (int) {
238 if( !directoryiterator_done( _platform ))
239 _next();
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 * () {
249 return _current;