public Uri relTo(Uri baseUri)
{
if (!OpUtil.compareEQ(this.m_scheme, baseUri.m_scheme) ||
!OpUtil.compareEQ(this.m_userInfo, baseUri.m_userInfo) ||
!OpUtil.compareEQ(this.m_host, baseUri.m_host) ||
!OpUtil.compareEQ(this.m_port, baseUri.m_port))
return this;
// at this point we know we have the same scheme and auth, and
// we're going to create a new URI which is a subset of this one
Sections t = new Sections();
t.query = this.m_query;
t.queryStr = this.m_queryStr;
t.frag = this.m_frag;
// find divergence
int d=0;
int len = Math.Min(this.m_path.sz(), baseUri.m_path.sz());
for (; d<len; ++d)
if (!this.m_path.get(d).Equals(baseUri.m_path.get(d)))
break;
// if diverenge is at root, then no commonality
if (d == 0)
{
// `/a/b/c`.relTo(`/`) should be `a/b/c`
if (baseUri.m_path.isEmpty() && this.m_pathStr.StartsWith("/"))
{
t.path = this.m_path;
t.pathStr = this.m_pathStr.Substring(1);
}
else
{
t.path = this.m_path;
t.pathStr = this.m_pathStr;
}
}
// if paths are exactly the same
else if (d == this.m_path.sz() && d == baseUri.m_path.sz())
{
t.path = emptyPath();
t.pathStr = string.Empty;
}
// create sub-path at divergence point
else
{
// slice my path
t.path = this.m_path.getRange(Range.makeInclusive(d, -1));
// insert .. backup if needed
int backup = baseUri.m_path.sz() - d;
if (!baseUri.isDir()) backup--;
while (backup-- > 0) t.path.insert(0, dotDot);
// format the new path string
t.pathStr = toPathStr(false, t.path, this.isDir());
}
return new Uri(t);
}