implement a recursive dir iterator

Hi,
I want to write a recursive dir iterator, so I can write code like:
 
for_each(recursive_dir_iter("c:/", "*.txt"), recursive_dir_iter(), display_func);


I've been googling for a while, there are articles about non-recursive dir iterator, like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#pragma once

#include <windows.h>
#include <string>

#include <algorithm>
#include <memory>
using namespace std;

struct file_info {
	bool is_dir;
	string name;

	file_info() {}
	file_info(const WIN32_FIND_DATA& x)
		: is_dir((FILE_ATTRIBUTE_DIRECTORY & x.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY)
		, name(x.cFileName)
	{}
};


template <typename value_t>
struct file_iter : public iterator<input_iterator_tag, value_t> {
	typedef file_iter<value_t> self_t;

	bool end_;
	string path_;
	string pattern_;
	value_t value_;
	WIN32_FIND_DATA ffd_;
	shared_ptr<void> hfind_; // HANDLE is defined as void* in SDK

	file_iter() : end_(true) {
	}
	file_iter(const string& path, const string& pattern)
		: end_(false)
		, path_(path)
		, pattern_(pattern)
	{
		hfind_ = shared_ptr<void>(FindFirstFile((path_ + pattern_).c_str(), &ffd_), ::FindClose);
		if(hfind_.get() == INVALID_HANDLE_VALUE) {
			end_ = true;
		} else {
			value_ = value_t(ffd_);
		}
	}

	void next() {
		if(FindNextFile(hfind_.get(), &ffd_)) {
			value_ = value_t(ffd_);
		} else {
			end_ = true;
		}
	}
	const value_t& operator*() {
		return value_; 
	}
	const value_t* operator->() {
		return &(operator*());
	}

	file_iter& operator++() {
		next();
		return *this;
	}
	bool equal(const file_iter<value_t>& x) const {
		if(end_ && x.end_) {
			return true;
		}
		return (strcmp(ffd_.cFileName, x.ffd_.cFileName) == 0
			&& hfind_ == x.hfind_
			&& path_ == x.path_
			&& pattern_ == x.pattern_);
	}
};

template <typename value_t>
inline bool operator ==(const file_iter<value_t>& x, const file_iter<value_t>& y)
{
	return x.equal(y);
}

template <typename value_t>
inline bool operator !=(const file_iter<value_t>& x, const file_iter<value_t>& y)
{
	return !x.equal(y);
}


anyone has been working on this before? How to make it recursive.

Thanks in advance.
Last edited on
Think about what you'd do if you where using the native OS call to do recursive traversal.

1. You use FindFirstFile/FindNextFile to get each entry.
2. You'd check the type of the entry.
3. If it's a normal file, you pass it to the caller.
4. If it's a directory:
a. you stash your current context (in the call stack)
b. make up the new name
c. do the whole FindFirstFile/FindNextFile thing all over again.
d. pop the stack and continue

Your iterator should do the same. So, for example, you ought to have a stack of WIN32_FIND_DATA in your iterator.
Thanks,
At first I use the first parameter of FindFirstFile, it handles the pattern, eg: *atl*.dll,

but now the pattern must be "*", so it could search for directories, now I need to do the filtering
Clearly you need to remember the filter so you can make up the correct wildcard in step 4b above.
Topic archived. No new replies allowed.