Boost logo

Boost :

From: Beman Dawes (bdawes_at_[hidden])
Date: 2002-07-19 20:53:54


At 01:15 PM 7/19/2002, Giovanni Bajo wrote:

>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).

That's correct, and that is a deliberate design decision arrived at after
months of considering other schemes.

The basic problem is that the specification of root directories is
inherently non-portable. Even something as simple as "/" has
somewhat different meanings between POSIX, where it is an absolute path to
the filesystem root, and Windows, where it is a relative path to the
current drive's root.

The fs::path::system_specific constructor allows for the construction of
paths with roots which are drives, devices, volumes, or any other kind of
system-specific root. Typical sources of such base paths are user input or
the initial_directory() function. The program itself is usually better off
(and much more portable) to deal only in paths relative to that base
path.

>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).

The idea is that paths constructed with the regular (no 2nd argument)
constructor are portable (except for the name issue; there are separate
functions to help in dealing with that).

Paths constructed with the additional constructor argument
"system_specific", aren't limited. The syntax is deliberately a bit
longer; we only want people to use this form if they have really thought it
out and need it.

I'm quite happy with the approach. It encourages portability without
requiring it.

>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).

The approach is hardly unheard of. See the standard's stream iterators
(section 24.5 of the standard).

By the way, Dietmar Kühl did the original design and implemention of
directory_iterators.

>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...

A directory isn't a container, anymore than an I/O stream is a container.
They are operating system resources, and the only thing that a library can
do with them is whatever is provided the OS API.

That's why access via an input iterator makes sense. It is a thin wrapper
that papers over differences between operating systems, yet in a form
familiar to C++ programmers.

...

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

Sure, and trivial for the user to code given the basic toolkit provided by
the Filesystem Library components, and all the tools available for working
with iterators.

In the lengthy discussions on the Boost list last Winter we talked about
higher levels of functionality, but always bogged down in details. The
proposed library provides a toolkit; higher level functions can be built on
top of it if you can get people to agree just what they are.

>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.

The current fs::directory_iterator is "on-the-fly" in the sense that is how
it calls the operating system functions which do the actual work. But how
the operating system performs the actual directory access is completely out
of the control of the directory_iterator implementor, or any similar
library for that matter. The Filesystem Library doesn't ask implementors to
rewrite the operating system or make other heroic efforts.

Thanks for the comments. I'll try to review the FAQ a bit to make sure
they are covered there.

--Beman


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