Boost logo

Boost :

From: Giovanni Bajo (giovannibajo_at_[hidden])
Date: 2002-07-19 12:15:39


Hello,

after having played a bit with the file system library, I have several
feedbacks to share.

What's the canonical form for "c:\windows"? The only way I found to setup a
path like this is fs::path("c:\\windows", fs::path::system_specific). Now, I
understand there are platforms where drives are mapped to directories. But
it sounds strange that there is simply no way to specify a drive when using
the library under Windows. Actually, if you print a path constructed as
above, it displays "c:/windows", but you can't construct the path with this
syntax. So, my point basically is that I want a way to select a driver under
Windows in canonical form. Suggestions are to accept either "c:/windows" or
"/c/windows" (changing the library so that the first directory in an
absolute path is always the drive name - under Windows).

I pretty much don't like "directory_iterator" in its current form. When I
read the word iterator, I expect to have a container associated to it with
its begin() and end() members. directory_iterator behaves as a STL iterator
for some things (full InputIterator semantic), but does not for others (it
incapsulate its own 'container' to the user).
My proposal is creating a new class called 'directory_list' which would act
as a container (I think it should match what it's now called
directory_iterator_impl), and then defining directory_list::iterator used to
simply navigate through it as normal.

Basically, 'directory_list' would be very very similar to a list<fs::path>
(it might be its underlying implementation), with the list holding the names
of the files within the directory (and with lazy evaluation to be sure it
gets filled only when the informations are requested by the user). It would
have a constructor getting a fs::path (throwing an exception if the path
does not represent an existing directory). It would also implement most
(all?) the member functions found in a list<fs::path> (like begin(), end(),
size(), erase(), etc). Giving it a full container semantic allows to write
code like:

bool MatchCPP(fs::path fileName)
{
    return fileName.leaf().find(".cpp") != string::npos;
}

fs::directory_list dir = fs::path("/usr/whatever");
fs::directory_list dir_only_cpp;

std::copy_if(dir.begin(), dir.end(), back_inserter(dir_only_cpp), MatchCPP);

A further step would be to automatically implements filters like this and
more features with overloaded constructors:

fs::directory_list dir(fs::path("/usr/whatever"), "*.cpp"); // construct a
directory_list only with .cpp files
fs::directory_list dir("/usr/whatever", "*.cpp"); // as above, just handier
fs::directory_list dir("/usr/whatever", "*.cpp", true); // automatically
recurse subdirs
fs::directory_list dir("/usr/whatever", regex(".+\\.(cpp|C)$"), true); //
matching with boost::regex instead of wildcards

Filtering and recursing subdirectories are very important because, in my
opinion, they are the two most common operations done while browsing a
directory.

One may ask why you need a directory_list, when you could simply have a
make_directory_list() (with the overloads shown above for the constructor)
and returning a list<fs::path>. The answer is that I really like lazy
evaluation for directory browsing (especially when dealing with subdir
recursion). A simple make_directory_list() would have to browse all the
files to create a complete list<fs::path>, while a directory_list can be
"constructed" on the fly, when the elements are requested by the user.

I'm awaiting your comments.

Giovanni Bajo


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk