std.path review: update
Lars T. Kyllingstad
public at kyllingen.NOSPAMnet
Wed Jul 20 10:36:51 PDT 2011
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'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.
>> 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).
>>> 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?
>>> pathSplitter:
>>>
>>> I think this should be a bi-directional range (no technical limitation
>>> I can think of).
>>
>> It is more of a complexity vs. benefit thing, but as you are the second
>> person to ask for this, I will look into it. A convincing use case
>> would be nice, though. :)
>
> Well a path is more like a stack than a queue. You are usually
> operating more on the back side of it. To provide back and popBack
> makes a lot of sense to me. For example, to implement the command cd
> ../foo, you need to popBack the topmost directory.
Ok, I'll see what I can do about it. :)
>>> fcmp:
>>> "On Windows, fcmp is an alias for std.string.icmp, which yields a case
>>> insensitive comparison. On POSIX, it is an alias for
>>> std.algorithm.cmp, i.e. a case sensitive comparison."
>>>
>>> What about comparing c:/foo with c:\foo? This isn't going to be equal
>>> with icmp.
>>
>> I am a bit unsure what to do about the comparison functions (fcmp,
>> pathCharMatch and globMatch). Aside from the issue with directory
>> separators it is, as was pointed out by someone else, entirely possible
>> to mount case-sensitive file systems on Windows and case-insensitive
>> file systems on POSIX. (The latter is not uncommon on OSX, I believe.)
>> I am open to suggestions.
>
> It's definitely something to think about. At the very least, I think
> the default file system case sensitivity should be mapped to a certain
> function. It doesn't hurt to expose the opposite sensitivity as an
> alternate (you need to implement both anyway). A template with all
> options defaulted for the current OS makes good sense I think.
> Actually, expanding/renaming pathCharMatch provides a perfect way to
> default these:
>
> e.g.:
> version(Windows)
> {
> enum defaultOSSensitivity = false;
> enum defaultOSDirSeps = `\/`;
> }
> else version(Posix)
> {
> enum defaultOSSensitivity = true;
> enum defaultOSDirSeps = "/";
> }
>
> // replaces pathCharMatch
> int pathCharCmp(bool caseSensitive = defaultOSSensitivity, string
> dirseps = defaultOSDirSeps)(dchar a, dchar b);
>
> int fcmp(alias pred = "pathCharCmp(a, b)", S1, S2)(S1 filename1, S2
> filename2);
>
> Anyone who wants to do alternate comparisons is free to do so using
> other options from pathCharCmp.
Good idea. I'll probably implement something like that.
>>> expandTilde:
>>>
>>> I've commented on expandTilde from the other posts, but if it is kept
>>> a posix-only function, the documentation should reflect that.
>>
>> It does; look at the "Returns" section. Perhaps it should be moved to
>> a more prominent location?
>
> Yes. It should say (Posix-only). I believe technically that it should
> fail to compile on Windows if it does not map to a "home" directory
> there. Note that as named, it's possible to confuse with expanding the
> DOS 8.3 name of a file, i.e. Progra~1
I agree. I'll put it inside a version(Posix) block.
-Lars
More information about the Digitalmars-d
mailing list