Boost logo

Boost :

From: Reece Dunn (msclrhd_at_[hidden])
Date: 2004-08-22 03:14:34

Carlo Wood wrote:
>On Sat, Aug 21, 2004 at 11:36:31AM +0100, John Maddock wrote:
> > > I propose the following design. The aim of boost::filesystem should
>be to
> > > support the following coding idiom:
> > >
> > > * The programmer should take care to only handle two types of paths
> > > in his application:
> > >
> > > 1) Complete paths
> > > 2) Relative paths
> >
> > That is true now.
>No, the current implementation/design doesn't restrict anything at all
>in this regard. You can just use fs::path to store paths - and that is
>it. A path is not aware of a distinct difference between complete
>paths and relative paths (except that they are complete or relative
>of course) - definitely not in the same way as a design would that
>uses two different classes for the two.

A complete path is one that is fully qualified, thus:

   fs::path absolute = fs::path( "d:/devel/libraries/boost/1.31.0/libs" );

whereas a relative path is one that is "relative" to another. With a
relative path, you must have an absolute path as the basis, e.g.:

   fs::path relative = fs::path( "../boost/mpl" );

and can turn the relative path into an absolute one by doing:

   fs::path qualified = absolute / relative;

so where is the problem?

>The most problematic difference is that it is possible to even store
>a third possibility (one that is neither complete nor relative).

??? Do you mean one that isn't relative because it is not based from an
absoute path, or that the path does not exist? If so, you can do that in any
file system, e.g.:

   fs::path foobar = fs::path( "../booster/" );
   fs::exists( absolute / foobar );

A path will either (in absolute form) refer to a file, a directory or be

> > > * The programmer will have to specifically tell the libary when a
> > constructed
> > > path is 'native' and when not. A native path is accepted according
> > native
> > > rules and never gives any problem (exceptions) further on.
> > > A non-native path is checked according to the existing rules, which
> > basically
> > > means that the programmer can set a default check routine that will
> > effect
> > > determine how portable the application will be.
> >
> > That is also true now, isn't it?
>No, because the 'native' that you can specify with the current design
>is only a check on the characters used in the directory components, and
>only related to the representation of a path - not *marking* the path
>as different. The 'native' I am talking about is enforced for complete
>paths and reflexs also the root part of a directory ("C:\", "c:/cywgin/",
>"/" etc). The essential difference is that a path that is once marked
>as 'native' must stay native. It can never be converted to a portable
>path anymore. Only relative paths that are portable from the start
>can stay portable after certain operations (like appending a directory, or
>cutting off a directory at the end).

The native you are referring to is an "absolute" path, correct?
Boost.Filesystem stores the paths in a generic form. Thus, if your
filesystem uses ':' as a directory separator, the library will map this
correctly from it's internal state. If you enforce that all "native" Windows
paths must have a directory, you are restricting the use of the library,
e.g. "\\mycomp\devel\libraries" is not possible! Likewise, it would not be
possible to store URLs.

NOTE: I am not sure if Boost.Filesystem currently supports URLs, but it
should be possible to extend it to add that support. Also, URLs are not
attached to a particular filesystem and are thus portable. It should be
possible to handle both URLs and native paths, but limiting "native" paths
will only make this harder.

> > > I propose two design changes:
> > >
> > > 1) 'native' is now not only a representation, but an *internal state*
> > fs::path.
> > > (this has no effect on the representation as returned by
> > fs::path::string()).

This would make things too restrictive. I think you are confusing "native"
with "absolute" paths, but how do you validate an absolute path? Is there a
Windows and a POSIX function to validate an absolute path (e.g.
IsPathAbsoute)? It would then be possible to have a fs::is_absolute( ... )

> > > 2) All 'complete' paths are automatically marked as 'native'.

Likewise, how do you validate a complete path? What about a URL? If you have
the URL "" and are using a system whereby the
native directory separator is ':', the URL will be mapped to
"", corrupting the URL.

> > If I understand you correctly, you are suggesting that error checking is
> > turned off for native paths, I would support that, but other than that I
> > don't see how it differs.
>Heh - the current design does NOT have an internal state that marks
>a path as native or not. Hence, it cannot do sensible error checks
>that need that knowledge. Isn't that difference enough?

Native - as Boost.FileSystem uses it - is used to mark a path as using the
native OS syntax for specifying paths. This is so you can do:

   fs::system_complete( fs::path( argv[1], fs::native ) );

and use the library on Windows, *nix, OpenVMS, MacOS, etc. without having to
worry about the differences between how they specify their paths and thus
what regular expressions need to be used on the string. The example from the
documentation (using OpenVMS) is:


> > > Examples, the following code is legal:
> > >
> > > fs::path p1("C:\\foo\\a.exe", native); // As one might do on windows.
> > > fs::path p2("/usr/src/a.out, native); // As one might do on linux.
> > > std::cout << p1.native_file_string(); // ok, p1 is native.
> > >
> > > fs::path p3("foo/bar"); // Relative path, always succeeds.
> > > std::cout << p.string(); // ok
> > > std::cout << p.native_directory_string(); // Useless, but ok.
> >
> > Not useless at all. And works now.
> ^^^^^^^^^^^^^^^^
> \__ this.
>That is not backupped.

Did you mean p to be the relative path p3? If so, then
p3.native_directory_string() is perfectly valid and *not* useless. If the OS
uses ':' as it's directory separator, then this will return "foo:bar". It is
useful for all sorts of purposes, like debuging.

> > > fs::path p4(complete(p3)); // p4 is now "native", because now it is
> > complete.

Why does native ==> complete? You can have a native relative and/or complete

> > > std::cout << p4.string() // Not allowed because p4 is native

Huh? IIUC path.string() returns the internal format of the path (e.g.
"foo/bar") whereas path.native_directory_string() returns the path as
represented by the native OS (e.g. "foo:bar").

>Right now you can call all the operations that actually pass a path to some
>system call - and UNLESS that path is complete - it will not be

Not true. "foo/bar" is relative *and* non-portable for OS's that use ':' as
a directory separator.

>THAT means that boost::filesystem has a structural design error. You are
>now saying that I can complete all paths just prior to calling any
>that passes paths to system calls. Would you mind even listing those for
>Why not change boost::filesystem so that it takes care of completion
>automatically when needed? That way you cannot make errors.

If you have an absolute path boost_dir and a relative path boost_build2, you
can do:

   ::SetWorkingDirectory(( boost_dir / boost_build2

>As an example - I developed my application first on GNU/Linux with as only
>demand that it had to be portable to cygwin. Therefore, I used UNIX paths.
>Testing if /usr/src/edragon/edragon/build/src/gui/ existed on linux
>worked fine. It did NOT work on cygwin. Because I was stupid? No, I
>that was because boost::filesystem is not activily supporting portable

Did you check that you have the file where you said on the cygwin system.
Have you checked that "/usr/bin/ls.exe" exists? Also, have you checked that
BOOST_POSIX is defined as per the note on using the cygwin platform in the


Express yourself with cool new emoticons

Boost list run by bdawes at, gregod at, cpdaniel at, john at