Thread overview
Re: function for inverse relative path?
Dec 07, 2017
Timothee Cour
Dec 07, 2017
Jonathan M Davis
Dec 07, 2017
Timothee Cour
December 06, 2017
how about:
```
string inverseRelativePath(string root, string rel){
while(true){
if(rel.empty || rel==".") {
return root;
}
auto a1=root.baseName;
auto a2=rel.baseName;
enforce(a1==a2, text(root, " ", rel));
root=root.dirName;
rel=rel.dirName;
}
}

unittest{
import std.exception;
auto a="/a/b/c.d";
auto b="b/c.d";
assert(inverseRelativePath(a, b) == "/a");
assertThrown(inverseRelativePath(a, "c2.d"));
}
```


On Wed, Dec 6, 2017 at 5:36 PM, Timothee Cour <thelastmammoth@gmail.com> wrote:
> what would be a robust way to do this `inverseRelativePath`, and should that be in std.path?
>
> ```
> auto a="/a/b/c.d";
> auto b="b/c.d";
> assert(inverseRelativePath(a, b) == "/a");
> assertThrown(inverseRelativePath(a, "c2.d"));
> ```
December 06, 2017
On Wednesday, December 06, 2017 17:36:04 Timothee Cour via Digitalmars-d wrote:
> what would be a robust way to do this `inverseRelativePath`, and should that be in std.path?
>
> ```
> auto a="/a/b/c.d";
> auto b="b/c.d";
> assert(inverseRelativePath(a, b) == "/a");
> assertThrown(inverseRelativePath(a, "c2.d"));
> ```

I've never heard of inverse relative paths, but it looks like all you're doing is looking for a substring match at the end and returning the parts at the front that don't match. If you're doing that, you could simply do something like

enforce(lhs.length >= rhs.length, "some error message");
if(lhs[rhs.length .. $] == rhs)
    return lhs[0 .. rhs.length];
throw new Exception("some error message");

though if you want /a instead of /a/ in your example, some extra code would have to be added for properly handling trailing slashes, and depending, you might want to normalize paths first (though typically, that sort of thing is left up to the caller). It might also need to be enforced that the left-hand argument is an absolute path.

- Jonathan M Davis

December 07, 2017
relativePath works with un-normalized paths, and I'd want the same for
inverseRelativePath, eg: should work with:
`/a//b/./c/bar.d` and `c//bar.d` => `/a//b`

unfortunately buildNormalizedPath(rel) will prepend getcwd to `rel` so it's a tad more complex than just calling buildNormalizedPath on both arguments; which is way would be nice to have in std.path


On Wed, Dec 6, 2017 at 8:55 PM, Jonathan M Davis via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On Wednesday, December 06, 2017 17:36:04 Timothee Cour via Digitalmars-d wrote:
>> what would be a robust way to do this `inverseRelativePath`, and should that be in std.path?
>>
>> ```
>> auto a="/a/b/c.d";
>> auto b="b/c.d";
>> assert(inverseRelativePath(a, b) == "/a");
>> assertThrown(inverseRelativePath(a, "c2.d"));
>> ```
>
> I've never heard of inverse relative paths, but it looks like all you're doing is looking for a substring match at the end and returning the parts at the front that don't match. If you're doing that, you could simply do something like
>
> enforce(lhs.length >= rhs.length, "some error message");
> if(lhs[rhs.length .. $] == rhs)
>     return lhs[0 .. rhs.length];
> throw new Exception("some error message");
>
> though if you want /a instead of /a/ in your example, some extra code would have to be added for properly handling trailing slashes, and depending, you might want to normalize paths first (though typically, that sort of thing is left up to the caller). It might also need to be enforced that the left-hand argument is an absolute path.
>
> - Jonathan M Davis
>