Boost logo

Boost :

From: Jason Stewart (res0054p_at_[hidden])
Date: 2002-01-29 11:16:13


> > I don't know, maybe they should, I guess for broad acceptance it might
> > should use locals (I've never used locals).
>
>I presume you meant "locales." That's how you would do the case
>conversions, but the issue of which case remains.

Yes, I meant locales. Would you actually convert the strings or can locales
compare without regards to case?

> > >ForwardSeparator::isSeparator()'s (is_separator()'s) implementation
>should
> > >just be...
> >
> > Possibly, in my software, I tend to convert all separators to forward
> > slashes since it works on all platforms that I deal with. However, users
> > still tend to enter backslashes on windows. Since I want to convert them I
> > like isSeparator to return true for both.
>
>If you're trying to create a pathname programmatically, and then you need to
>display it to the user, you'll want it to appear in the "correct" format.
>For Windows, that means using backslashes, even if the APIs will accept
>forward slashes.

It depends. Many times yes. Much of the software I have worked on recently
needed to create and store paths that worked on UNIX and Windows. Since
Windows handles forward slashes but UNIX doesn't handle backslashes we
converted everything to forward slashes.

Even without that need though, if I create a directory programmatically but
part of the name comes from the user then I could easily have mixed
separators. For instance, if the user entered "projects\myclass.cpp" and I
appended that to "/home/jason" then the result is
"/home/jason/projects\myclass.cpp". To convert this to backslashes, the
policy needs to recognize that both slash and backslash are valid
separators on Win32.

> > >Pathname::MakeAbsolute() should take the "current directory" as a
>parameter.
> > >Not only does that do what your version does, if the caller supplies the
> > >real current directory, but it also allows the caller to convert a
>relative
> > >path into an absolute path based upon any path of their choice. This is
> > >applicable for situations in which the program is given a relative path
> > >based upon the user's home directory or some data repository.
> > >
> > >Pathname::MakeRelative() says that the parameter defaults to the cwd, and
> > >yet the parameter has no default value. Nevertheless, I wouldn't change
>the
> > >signature; just its description. IOW, as with MakeAbsolute(), it should
>be
> > >up to the caller to provide the cwd, if that's what they want.
> >
> > In retrospect, are MakeAbsolute or MakeRelative similar to Exists in that
> > they should be handled outside the class?
>
>No. There is no filesystem interaction necessary. They are just
>manipulating the head of the pathname. Exists() has to interact with the
>filesystem to determine whether the file exists.

On Win32 there is a function to convert a relative name to an absolute name
but I can see that it is possible to do it solely with string manipulation.

> > >Pathname::Split() should not return a vector. Instead, make it a member
> > >template that takes an output iterator. I don't think the parameter is
> > >necessary. The caller can skip the first string if they don't want the
> > >volume. If you opt to keep that parameter, then create an enumerated
>type
> > >to control the behavior.
> >
> > The parameter decides whether the volume should be included in the first
> > parameter or not. Sometimes it is helpful to get the first part as
> > "c:/data" instead of "c:" and "/data". I agree with the iterator though.
> > I'll look into it.
>
>I understand the reason you included it. I was just pointing out that the
>caller can assemble the pieces as they see fit, or can ignore the first
>value altogether, if appropriate. What if the caller doesn't want the
>extension or the filename? You haven't provided options for those. If you
>want to offer this kind of flexibility, then I suggest taking pointers to
>strings for each possible component. If a pointer is non-null, write the
>corresponding component through the pointer.

I am open to your point of view, I just think that much code is easier to
write if you can know that the first piece you get back is the root of a
volume, not just the volume name itself. For instance:

///////////////////////////////////////////////////////////////////////////////
// Assuming a MakeDirectory_ function takes
// a pathname and makes a directory
// (hiding platform dependencies)
///////////////////////////////////////////////////////////////////////////////
void MakeDirectory(const pathname& dir, bool maketree)
{
         if (maketree)
         {
                 Pathname tmp;
                 for (pathname::iterator it = dir.begin(); it != dir.end();
++it)
                 {
                         tmp += *it;
                         if (!Exists(tmp)) MakeDirectory_(tmp);
                 }
         }
         if (!dir.Exists()) MakeDirectory_(dir);
}

///////////////////////////////////////////////////////////////////////////////
void MakeDirectory(const pathname& dir, bool maketree)
{
         if (maketree)
         {
                 if (dir.begin() == dir.end()) return;
                 pathname::iterator it = dir.begin();
                 Pathname tmp(*(it++));
                 for (; it != dir.end(); ++it)
                 {
                         tmp += *it;
                         if (!Exists(tmp)) MakeDirectory_(tmp);
                 }
         }
         if (!dir.Exists()) MakeDirectory_(dir);
}

In the second case you have to get the volume and add it to your temporary
path, increment your iterator, then go into your loop. In the first case
you don't have to handle the volume as a special case.

Jason


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