Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2003-08-18 16:28:58


Beman Dawes <bdawes_at_[hidden]> writes:

> At 10:59 AM 8/18/2003, David Abrahams wrote:
>
> >Beman Dawes <bdawes_at_[hidden]> writes:
> >
> >> Yes. Plus there are some other issues.
> >>
> >> The actual interface would include boost::filesystem::path
> >> constructors which take an additional argument to explicitly specify a
> >> name checker function. In working out use cases, it seems that
> >> temporary overrides of the default function are best handled via these
> >> constructors. That leaves only the case of wishing to permanently
> >> replace the default function, and the simpler approach you are talking
> >> about would be better for that.
> >>
> >> For safety, such a set_legal_name_policy() would use the
> >> write-once-before-read idiom to avoid a dangerous global
> >> variable. (I'm actually thinking of "name_check" for the type, and
> >> "set_name_check" for the function name.)
> >>
> >> I'm about to post a message asking for opinions on the details of the
> >> policy function pointer or object.
> >
> >This starts to align with what I've been thinking. Every path object
> >could maintain a chain of checkers, and combinations of path objects
> >(e.g. via operator/) would use the union of the checkers of their
> >components, so that checking would never become less-restrictive
> >silently.
>
> That is more machinery than is needed. It would be a nice design for a
> system that had to revisit elements, but for that isn't required here.
>
> When I was first working with designs for error checking, I tried a
> lot of similar schemes. Eventually I realized that treating name
> validity as an invariant established at construction was much simpler
> and performed quite well. It doesn't require keeping a chain of
> checkers. It performs the checking at the point in the calling program
> where knowledge of what is valid is present.

Sure. The question is:

       path x('foo/bar', portable_check);
       path y('baz', native_check);

       path z = x/y; // Which checks are made?

       path q = z/y; // which checks are made?

> > Of course, though I think this goes against the grain of
> >the library, I believe the default checker should always be the for
> >the native platform.
>
> Because the native platform may support several different file systems
> within the same directory tree, it isn't possible to perform a full
> and correct lexical (inspection of the name only) check for the native
> platform. You in effect have to try the path and see if the operating
> system accepts it. What the lexical level name check done by class
> path is trying to do is early detection of gross naming errors.

Sure; I just don't want to have to be explicit about anything just to
say "I'm doing native path manipulation", since I believe that's the
90% case. I don't want to be stopped by irrelevant portable path
considerations nor uglify my code to avoid it.

> A specific example might help. Say you are working on a Linux
> platform. It supports a really wide range of characters in
> names. But you know the code sometimes will run on Windows, so you
> would like to check automatically that some directory tree you
> create doesn't violate Windows naming conventions. You do this by
> specifying a Windows name checker (which disallows a bunch of
> special characters). This will prevent your program from
> inadvertently using the special characters that Windows always
> disallows.
>
> Now when the program actually runs on a Windows box, a native path
> may be given (say by operator input) as the root, and then the
> relative portions your program adds get tacked on. If the operator
> supplied root happens to be a CD ISO-9660 file system, your
> carefully chosen relative names may fail, because the ISO-9660 names
> are way more restricted that general Windows names.
>
> In that case, the attempt at early detection was a failure; the name
> checker did no good. But a lot of real-world errors will be detected
> early, so I don't see the name checking as a failure. It just is a
> partial check, not an iron-clad guarantee. A useful axillary
> mechanism, but not the main show.

No argument.

> But because it can't be an iron-clad guarantee, I'd prefer not to
> build an even mildly complex mechanism to support it. Particularly
> since some programmers will disable it anyhow.

You need to define sensible semantics for path combinators then.

Oh, and disabling is easy:

   path z = path(x, no_check)/path(y, no_check);

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

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