|
Boost : |
From: Beman Dawes (bdawes_at_[hidden])
Date: 2002-09-17 08:42:40
At 05:57 AM 9/17/2002, Vladimir Prus wrote:
>1. Say I have a path. I want to treat it as relative to some other
>directory, if it is relative. That is, I want function
>
> path root ( const path& p, const path& r )
>
>which will work like
>
> root ( "/home/ghost/a" , "/home/ghost" ) = "/home/ghost/a"
> root ( "a" , "/home/ghost" ) = "/home/ghost/a"
>
>How can I do that? I seems rather hard currently -- I see no way to join
>two paths
Operator <<= and operator << do that, if I understand your question.
To take your second example,
path p( "home/ghost" ); // the starting path
...
foo( p << "a" ); // p << "a" yields temporary path "home/ghost/a"
p <<= "a"; // afterwards, p.generic_path() ==
"home/ghost/a"
The above doesn't exactly duplicate your example 2. To do that, the first
line would be:
path p( "/home/ghost", system_specific ); // the starting path
The difference is because a leading "/" is not specified in the portable
grammar to mean "root"; it would only be valid as a system_specific path on
operating systems which support it. The reason for that can be best
answered in the context of your next comment:
> and I see no way to tell if a path is relative.
Let's take your example:
path p( "/home/ghost", system_specific );
and assume we add a path member function "bool relative() const" (and
possibly add a leading "/" to the portable grammar). Is this true or false:
p.relative() // true or false?
The answer depends on the operating system. For POSIX-like systems, the
answer is false. For many other operating systems the answer is true
(because they are multi-rooted.)
That scares me because programs using relative() easily code constructs
which won't be portable. It's the illusion-of-portability problem.
Early versions of path had a function is_absolute(), but it was removed
because of the portability worry. That raised your next question:
>2. I haven't found any treatment of relative paths in docs. It appears
>that they are accepted and treated relatively to the current dir, but
>isn't relying on current dir considered bad? How can I avoid it, if I
>can't implement the function 'root' above?
Here is the approach that seemed to work well in various initial uses of
the library:
First, nail down a base directory, either from user input:
path base( argv[1], system_specific );
or from the initial directory:
path base( initial_directory() );
From this point on, all path references are relative to "base". (A more
complex program might have several base directory paths, named
appropriately, and perhaps store them in an object.)
For example, if you want to see if base contains a file called "foo",
write:
if ( exists( base << "foo" ) ) ...
For files or directories referenced more than once, create a path variable
and then use it:
path bar_path( base << "bar" );
create_directory( bar_path );
if ( bar_path << "foo" ) ...
Notice that we don't care whether:
* base is absolute or relative.
* the operating system even has a concept of relative paths.
* the operating system has a concept of current directory.
* the operating system allows the current directory to be changed.
* and, finally, we don't need a concept of "root" (since that is
dealt with by either initial_directory() or user input.
I consider this to be much better design than the traditional approach,
because it avoids global variables like current directory, and because it
avoids a lot of portability pitfalls. It also seems to me to use familiar
C++ idioms. So far, it has been very easy to use in practice, and
functions like relative() haven't been missed.
Note that the library doesn't currently enforce the above approach. You can
code create_directory( "bar" ) and it will work fine, although it is
anybody's bet what directory "bar" will end up in; the implementor is only
expected to do what is natural for the operating system (which may have no
concept of current directory).
Comments?
--Beman
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk