Boost logo

Boost :

From: Vladimir Prus (ghost_at_[hidden])
Date: 2004-09-06 02:01:58


Martin wrote:

> Vladimir Prus <ghost <at> cs.msu.su> writes:
>
>> > Let the path be a container for all kind of paths that follow the
>> > generic syntax explained in the boost::filesystem documentation.
>>
>> That's already the case, no?
> No, the current implementation only allows you to have a single path
> "type" for everything since the handling of root etc is built into the
> path class (via #ifdefs for windows and posix).

I would say that most of #ifdefs inside path.cpp exist to handle root path
on Windows. The path is stored as a string and there are many instances of
code which looks at first characters to determine if there <letter> ':' '/'
pattern. I think if path explicitly store

  - a bool telling if path has a root
  - the length of the root

all this logic would be much simplified.

> If you want to add another path type (e.g. url) you would need to keep
> track of the type inside the class and then do "if (type==url) ... else
> ..." in all operations.

Not sure. Why appending "foo" path element to a URL is different from adding
the same "foo" to a regular filesystem path? with ad

>> > 2. Operations can be implemented selectivly for different types (No
>> > need for the current messy #ifdefs)
>> > bool exists( const path_base<posixfs<std::string> >& aPath);
>> > bool exists( const path_base<win32fs<std::wstring> >& aPath);
>>
>> Aren't those two mutually exclusive? You have the first on POSIX systems
>> and the second on the win32 systems.
>
> Yes posixfs and win32fs are mutually exclusive but that doesn't mean that
> all path types are. There might still be a need to have more than one path
> type in a single application.

If we take the approach that path is "root" + relative path, where "root" is
an arbitrary string, then almost all kinds of path can be stored in
boost::path.

> With the current implementation it would look like this:
>
> bool exists(const path& aPath) {
> if (aPath.type == path::filesystem)
> #ifdef BOOST_POSIX
> ...
> #elif BOOST_WINDOWS
> ...
> else if (aPath.type == path::registry)
> ...
> #endif
> else if (aPath.type == ...
> }
>
> It is possible to do it like that but the problem I see is that when you
> add a new path type you will need to add another "if (aPath.type ==" to
> all operations instead of just adding another overload.

Ok, let me ask another way: why

   exists(registry_path(p))

is better than

   exists_in_registry(p);

Where 'p' is of type boost::fs::path and registry_path is
path_base<win32reg<boost::fixed_string<100> > > that you've proposed.

>> If so, I don't understand how I can write
>> portable code -- I will have to call different function on different
>> pratforms, something like:
>>
>> #ifdef BOOST_WINDOWS
>> if (exists(win32path(p))
>> #else
>> if (exists(posix_path(p))
>> #endif
>
> It is easy to do a conditional typedef in the path.hpp so that you can
> use "path" portable on both systems.
>
> #ifdef BOOST_WINDOWS
> #include "win32fs.hpp"
> typedef path_base<win32fs> path;
> #elif BOOST_POSIX
> #include "posixfs.hpp"
> typedef path_base<posixfs> path;
> #endif
>
> ...
>
> if (exists(path(p))

Yes, it's possible. You essentially lift the #ifdefs: they are inside 'path'
methods now and now they are around definition of 'path'. That will work,
but I still don't understand why it's good given that win32 and posix are
mutually exclusive. Do you think it would be good to compile both win32fs
adn posixfs on all systems?

>> > bool exists( const path_base<win32reg<boost::fixed_string<100> > >&
>> > aPath);
>>
>> This can be handled by
>>
>> class registry {
>> bool exists(const fs::path&);
>> };
>>
> Don't understand what you mean.

I mean that the object you want to operate at (filesystem, registry), can be
encoded not only in argument type of 'exists', but also in the name of the
function you call (e.g. exists_in_registry, or registry::exists).

> The current path implementation doesn't
> allow you to handle more than one type (i.e. winfs or posixfs). You can't
> store a registrypath in a fs::path since it can't handle a hkey.. root.

Why? Can't I put literal "HKEY_CURRENT_USER" in boost::path?

>> Actually, I think it is very desired to have boost::path usable in more
>> contexts than the filesystem. For example
>>
>> fs::path base("http://my_site.org");
>> ..... get_file(base / "foo" / "bar") .....
>>
>> would be great. But I'm just don't sure this requires all that drastic
>> changes.
>
> Why do you think it is a drastic change?
> Changing operations will not take much time since it is only to move the
> things inside "#ifdef BOOST_POSIX" and "#ifdef BOOST_WINDOWS" into
> separate overloads.

And #ifdef the overloads ;-) I don't think Win32 API calls can be compiled
on Linux.

I really think that win32/posix distinction should say as it is. For other
types of path, I'm not sure. I *think* that boost::fs::path can accomodate
all of them. Of course, if you stick URL into boost::fs::path, the name
'native_file_path' becomes questionable ;-)

- Volodya


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