std.path review: update

Steven Schveighoffer schveiguy at yahoo.com
Wed Jul 20 11:16:04 PDT 2011


On Wed, 20 Jul 2011 13:36:51 -0400, Lars T. Kyllingstad  
<public at kyllingen.nospamnet> wrote:

> On Mon, 18 Jul 2011 14:51:06 -0400, Steven Schveighoffer wrote:
>
>> On Mon, 18 Jul 2011 14:25:57 -0400, Lars T. Kyllingstad
>> <public at kyllingen.nospamnet> wrote:
>>
>>> On Mon, 18 Jul 2011 13:16:29 -0400, Steven Schveighoffer wrote:
>>
>>>> In driveName:
>>>>
>>>> Should std.path handle uunc paths?  i.e. \\servername\share\path  (I
>>>> think if it does, it should specify \\servername\share as the drive)
>>>
>>> Yes, std.path is supposed to support UNC paths.  For instance, the
>>> following works now:
>>>
>>>   assert (equal(pathSplitter(`\\foo\bar\baz`), [`\\foo`, "bar",
>>>   "baz"]));
>>>
>>> I guess you would rather have that
>>>
>>>   assert (equal(pathSplitter(`\\foo\bar\baz`), [`\\foo\bar`, "baz"]));
>>>
>>> then?  I am not very familiar with Windows network shares; is \\foo
>>> never a valid path on its own?
>>
>> It is and it isn't.
>
> Well, that certainly cleared things up. ;)

It is in that if you open explorer and type in \\servername, it will give  
you a list of shares you can try.  But I don't think it's a valid *path*,  
except in explorer.  So my intuition is to declare it never a valid path.

I'm not sure how \\server interacts with the low level functions of  
Windows (such as CreateFile).  Some research/experimentation is probably  
warranted.

>> It's *not* a normal directory, because only shares
>> can be in that directory.  In other words, the point at which a UNC path
>> turns into normal directory structure is after the share name.
>>
>> An easy way to compare is, you can only map drive letters to shares, not
>> to servers.
>
> Then driveName() should probably return the full share path.  But, of the
> following asserts, which should pass?
>
>     assert (pathSplitter(`\\foo\bar\baz`).front == `\\foo\bar`);
>     assert (pathSplitter(`\\foo\bar\baz`).front == `\\foo`);
>
>     assert (baseName(`\\foo\bar`) == `\\foo\bar`);
>     assert (baseName(`\\foo\bar`) == "bar");
>
>     assert (dirName(`\\foo\bar`) == `\\foo\bar`);
>     assert (dirName(`\\foo\bar`) == `\\foo`);
>
> Note that if you replace `\\foo\bar` with `c:\` in the above, the first
> assert in each pair will pass.  Same with "/" on POSIX.  Basically, that
> choice corresponds to treating `\\foo\bar` as a filesystem root.

Yes, I think this sounds right (pending research/experimentation cited  
above).

>>> As I understand it, some POSIX systems also mount network drives using
>>> similar paths.  Does anyone know whether "//foo" is a valid path on
>>> these systems, or does it have to bee "//foo/bar"?
>>
>> Typically, linux uses URL's, i.e. smb://server/share   URL parsing is
>> probably not in std.path's charter.
>>
>> However, I have used a command like:
>>
>> mount -t cifs //server/share /mnt/serverfiles
>>
>> But this is only in very special contexts.  In general I don't think
>> //foo should be considered a server path on Posix systems.
>
> I actually got a request on the Phobos list that std.path should support
> such paths.  Furthermore, the POSIX stardard explicitly mentions "//"
> paths (though it basically says it is implementation-defined whether to
> bother dealing with them).

ls //root lists the contents of /root.  I'd guess that opening //root with  
open() would simply open /root.  Given that context, they should not be  
considered to be a server path IMO.

>>>> joinPath:
>>>>
>>>> Does this normalize the paths?  For example:
>>>>
>>>> joinPath("/home/steves", "../lars") => /home/steves/../lars or
>>>> /home/lars ?
>>>>
>>>> If so, the docs should reflect that.  If not, maybe it should :)  If
>>>> it doesn't, at least the docs should state that it doesn't.
>>>
>>> No, it doesn't, and I don't think it should.  It is better to let the
>>> user choose whether they want the overhead of normalization by calling
>>> normalize() explicitly.  I will specify this in the docs.
>>
>> In fact, if you do not normalize during the join, it's *more* overhead
>> to normalize afterwards.  If normalization is done while joining, then
>> you only build one string.  There's no need to build a non-normalized
>> string, then build a normalized string based on that.
>>
>> Plus the data is only iterated once.
>>
>> I think it's at least worth an option, but I'm not going to hold back my
>> vote based on this :)
>
> If it doesn't turn out to be a huge undertaking, I think I'll replace
> joinPath() with a function buildPath() that takes an input range of path
> segments and joins them together, with optional normalization.  Then,
> normalize(path) can be implemented as:
>
>     buildPath(pathSplitter(path));
>
> Does that sound sensible?

That sounds good.

-Steve


More information about the Digitalmars-d mailing list