Boost logo

Boost :

From: John Maddock (john_at_[hidden])
Date: 2004-08-21 05:36:31

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

> * The programmer will have to specifically tell the libary when a
> path is 'native' and when not. A native path is accepted according to
> rules and never gives any problem (exceptions) further on.
> A non-native path is checked according to the existing rules, which
> means that the programmer can set a default check routine that will in
> determine how portable the application will be.

That is also true now, isn't it?

> I propose two design changes:
> 1) 'native' is now not only a representation, but an *internal state* of
> (this has no effect on the representation as returned by
> 2) All 'complete' paths are automatically marked as 'native'.

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.

Actually, there is another case where error checking needs to be turned off:
when the path is obtained from a directory_iterator, but is none the less
relative (and *please* don't tell me that all such paths should be complete,
that would break a lot of code; actually it would make a lot of coding
idioms impossible).

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

> fs::path p4(complete(p3)); // p4 is now "native", because now it is
> std::cout << p4.native_directory_string(); // ok
> And the following will fail (assertion?):
> std::cout << p4.string() // Not allowed because p4 is native (complete).

One could add an assertion that the path is not complete, if you want that

Actually this change would break the bcp utility - there is a (slightly
hairy) use for this.

> Since there would be a default way defined of how a relative path is
> completed, all operation functions will accept both, relative
> and complete paths. For example:
> fs::path p1("C:\\cygwin\\usr/bin/ls", native); // Legal path on Cygwin.
> if (fs::exists(p1)) // Ok, access complete path.
> // For clarification
> fs::path p2("C:\\cygwin\\usr"); // Just an example
> fs::default_working_directory(p2); // fictuous function.
> fs::path p3("bin/ls"); // Portable representation (refers in fact to
> if (fs::exists(p3)) // Ok : exists() will make the path complete before
> And this throws:
> fs::path p4("/bin/ls"); // Not allowed: this path has a root but is not
marked 'native'.
> Setting the default_working_directory shall allways
> need to be done for each supported OS seperately.
> Of course you can set it to "/" on single root machines, and
> set it to "E:/" after extracting the 'E:' from the current
> path at application start up, in effect simulating a 'single root':

You should never need to set that explicitly unless you want to: each
aplication inherits a default working directory anyway from the host

BTW the behaviour you're asking for was required by bcp - all the paths are
relative to some root (the boost installation path) - that path may be
relative or absolute; and whenever you need a path relative to some root,
one can just use:

my_root / my_relative_path

so again, you can do what you want right now.

> The average application will work with relative
> paths, relative to some (native) base directory
> and next to that have some arbitrary, complete and thus native
> directories (ie, read from environment variables).
> But in case more than one 'working' directory seems needed
> then we can add support for that too by allowing to
> construct paths with a reference to the (complete/native)
> working directory. Ie,
> fs::path homedir(g_getenv("HOME"), native);
> fs::path rcdir(homedir / "edragon/rc", native);
> fs::path tmpdir(current_path().root_path() / "tmp");
> // ...
> fs::path runtime_rcfile(rcdir); // Set 'runtime_rcfile' to be relative
to 'rcdir'.
> // ...
> runtime_rcfile = "config/runtimerc";
> which is then relative to `rcdir' instead of
> a single, global 'working directory' (as now returned
> by fs::current_path()).

I'm sorry, but that looks way more complicated to me than the current
design: if you want a path to be relative to a specific base, then use
"my_base/my_path", it's easy to use, works, and it's clear what you mean as


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