Boost logo

Boost :

From: Walter Landry (wlandry_at_[hidden])
Date: 2003-11-11 13:31:44


Greetings,

I have been using boost::filesystem for a little while, and I am
finding that it would be nice to be able to just work on the paths in
the directory as a std::list or std::vector. Boost::filesystem
currently just provides an iterator, not the complete list.

I did a little survey of other filesystem libraries. Qt, gnome-vfsmm,
Emacs-lisp, python, and java provide a way of getting the entire list
of paths in a directory in addition to an iterator. Perl, Ruby,
wxWindows, and POSIX do not.

This subject is touched upon lightly in the FAQ (directory handles),
but I can't find a good rationale for not providing such a function.
The first downside I can think of is that it can make code a little
longer, though not always. I would argue that it makes it easier
to understand. In the current system, we have something like

  void foo(path &ph)
  {
    for(directory_iterator i(ph);i!=directory_iterator();++i)
      // do something
    find(directory_iterator(ph),directory_iterator(),bar,baz);
  }

while with a list it becomes

  void foo(path &ph)
  {
    directory dir_list(ph);
    for(directory::iterator i=dir_list.begin(); i!=dir_list.end(); ++i)
      // do something
    find(dir_list.begin(),dir_list.end(),bar,baz);
  }

Using a list seems more idiomatic. In particular, using an empty
constructor in the first example is potentially confusing.

The second downside is that it can be very inefficient to actually
create a list if not all of the elements are used, especially if there
are a lot of files. The POSIX api's, for example, don't seem to
create anything until it is needed. I could imagine this to be
important if we are just looking for the first file of a particular
type.

So I decided to just write a directory class on top of
directory_iterator. I have attached a patch. The names are going to
have to be fixed, since there is now directory_iterator and
directory::iterator. There should also be more std:: container
functions. Not all of the functions should be present, since you
shouldn't be able to add or delete elements. There could also be
separate functions to iterate over only files or only directories.

Regards,
Walter Landry
wlandry_at_[hidden]

    class directory
    {
    private:
      directory();
      std::list<path> dirs;
      path ph;

    public:
      directory(const path &PH): ph(PH)
      {
        if(is_directory(ph))
          {
            for(directory_iterator i(ph);i!=directory_iterator();++i)
              {
                dirs.push_back(*i);
              }
          }
        else
          {
            boost::throw_exception( filesystem_error(
              "boost::filesystem::is_directory",
              ph, detail::system_error_code() ) );
          }
      }

      typedef std::list<path>::iterator iterator;

      iterator begin()
      {
        return dirs.begin();
      }
      iterator end()
      {
        return dirs.end();
      }
      bool empty()
      {
        return dirs.empty();
      }
      const path dir_path()
      {
        return ph;
      }
    };


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