Path as an object in std.path

Lars T. Kyllingstad public at kyllingen.net
Thu Jun 6 10:40:37 PDT 2013


On Thursday, 6 June 2013 at 17:28:56 UTC, Steven Schveighoffer 
wrote:
> On Thu, 06 Jun 2013 13:25:56 -0400, Lars T. Kyllingstad 
> <public at kyllingen.net> wrote:
>
>> On Thursday, 6 June 2013 at 17:13:10 UTC, Steven Schveighoffer 
>> wrote:
>>> On Thu, 06 Jun 2013 12:14:30 -0400, Dylan Knutson 
>>> <tcdknutson at gmail.com> wrote:
>>>
>>>> It doesn't do any allocations that the user won't have to do 
>>>> anyways. Paths have to be normalized before comparison; not 
>>>> doing so isn't correct behavior. Eg, the strings `foo../bar` 
>>>> != `bar`, yet they're equivalent paths. Path encapsulates 
>>>> the behavior. So it's the difference between
>>>>
>>>> buildNormalizedPath(s1) == buildNormalizedPath(s2);
>>>>
>>>> and
>>>>
>>>> p1 == p2;
>>>
>>> This can be done without allocations.
>>
>> I know.  There are a few additions that I've been planning to 
>> make for std.path for the longest time, I just haven't found 
>> the time to do so yet.  Specifically, I want to add a couple 
>> of functions that deal with ranges of path segments rather 
>> than full path strings.
>>
>> The first one is a lazy "path normaliser":
>>
>>   assert (equal(pathNormalizer(["foo", "bar", "..", "baz"]),
>>                 ["foo", "bar", "baz"]));
>>
>> With this, non-allocating path comparison is easy.  The 
>> verbose version of p1 == p2, which could be wrapped for 
>> convenience, is then:
>>
>>   equal(pathNormalizer(pathSplitter(p1)),
>>         pathNormalizer(pathSplitter(p2)))
>>
>> You can also use filenameCmp() as a predicate to equal() to 
>> make the comparison case-insensitive on OSes where this is 
>> expected.  Very general and composable, and easily wrappable.
>
> Great!  I'd highly suggest pathEqual which takes two ranges of 
> dchar and does the composition and OS-specific comparison for 
> you.

They don't have to be dchar if all the building blocks are 
templates (as the existing ones are):

bool pathEqual(CaseSensitive cs = CaseSensitive.osDefault, C1, C2)
               (const(C1)[] p1, const(C2)[] p2)
     if (isSomeChar!C1 && isSomeChar!C2)
{
     return equal!((a, b) => filenameCharCmp!cs(a, b) == 0)
                  (pathNormalizer(pathSplitter(p1)),
                   pathNormalizer(pathSplitter(p2)));
}


More information about the Digitalmars-d mailing list