[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-devel
Subject:    Re: Relative Path Fuction
From:       Oswald Buddenhagen <ossi () kde ! org>
Date:       2003-06-03 22:38:24
[Download RAW message or body]

On Tue, Jun 03, 2003 at 04:19:34PM -0400, Benjamin Meyer wrote:
>   while(list1[level] == list2[++level]);
> 
i'm not sure whether the behaviour of this construct is defined in the c
standard ... in any case better use
 while(list1[level] == list2[level])
  level++;
instead.

one thing i don't like too much about this function is the
specialization on directories. it should work for any referer and
target. if one/both paths need to be directories, explicitly append
slashes - the empty file name is a file name, too, so things keep
working.

one more note: //host/path is also a relative url, so urls with
different hosts can be handled, too (not that i've ever seen something
like this in the wild ...). and an absolute url can be interpreted as a
special case of an absolute path, too, so the case of two totally
different urls can be handled, too.

appended is my version. as a relative path is something different than a
relative url, i created two functions. the relative url variant _can_
return the empty string - try it, you can use <a href="">. the relative
file variant has a flag to prefix "./" for the cases where a file with
no path is expected to be interpreted as "search the file in some PATH".
of course this code needs to be implanted into kurl.{h,cpp} before being
testable/commitable. :)

btw, the special case "path2 should be in path1; return the relative
path if true, otherwise error" julian mentioned, is simple to handle:
 if (path2.startsWith(path1))  // path1 must end with a slash!
   relpath = path2.mid(path1.length());
 else
   error;

greetings

-- 
Hi! I'm a .signature virus! Copy me into your ~/.signature, please!
--
Chaos, panic, and disorder - my work here is done.

["relpath.cpp" (text/x-c++src)]

/**
 * Finds the relative URL from @p link to @p target.<br>
 * URLs representing directories must have a trailing slash.
 * @param link This is the source (if you like, the referer).
 * @param target This is the location @p link points to.
 * @return the relative URL needed to get from @p link to @p target.
 */
QString KURL::relativeURL( const KURL &link, const KURL &target )
{
  KURL p1 = link;
  KURL p2 = target;
  p1.cleanPath(true);
  p2.cleanPath(true);

  if(p1.protocol() != p2.protocol() ||
     p1.user() != p2.user() ||
     p1.pass() != p2.pass() ||
     p1.host() != p2.host() ||
     p1.port() != p2.port())
    return p2.url();
 
  QStringList list1 = QStringList::split('/', p1.path(), true);
  QStringList list2 = QStringList::split('/', p2.path(), true);
 
  QString relURL;

  list1.remove(--list1.end());
  QStringList::ConstIterator it1 = list1.begin();
  QStringList::ConstIterator it2 = list2.begin();

  // Find where they meet
  while (it1 != list1.end() && it2 != list2.end() && *it1 == *it2)
    ++it1, ++it2;

  // Need to go down out of the first path to the common branch.
  for ( ; it1 != list1.end(); ++it1)
    relURL += "../";
 
  // Now up from the common branch to the second path.
  for ( ; it2 != list2.last(); ++it2) {
    relURL += *it2;
    relURL += '/';
  }
  relURL += *it2;

  relURL = encode( relURL, false, 0 );
  relURL += p2.query();

  return relURL;
}

/**
 * Finds the relative path from @p link to @p target.<br>
 * Paths representing directories must have a trailing slash.
 * @param link This is the source (if you like, the referer).
 * @param target This is the location @p link points to.
 * @param needpath If the result would not contain any slashes, prepend "./".
 * @return the relative URL needed to get from @p link to @p target.
 */
QString KURL::relativePath( const QString &link, const QString &target, bool needpath = false )
{
  QStringList list1 = QStringList::split('/', cleanpath(link, true), true);
  QStringList list2 = QStringList::split('/', cleanpath(target, true), true);
 
  QString relPath;

  list1.remove(--list1.end());
  QStringList::ConstIterator it1 = list1.begin();
  QStringList::ConstIterator it2 = list2.begin();

  // Find where they meet
  while (it1 != list1.end() && it2 != list2.end() && *it1 == *it2)
    ++it1, ++it2;

  // Need to go down out of the first path to the common branch.
  for ( ; it1 != list1.end(); ++it1)
    relPath += "../";
 
  // Now up from the common branch to the second path.
  for ( ; it2 != list2.last(); ++it2) {
    relPath += *it2;
    relPath += '/';
  }
  if (relPath.isEmpty() && needpath)
    relPath = "./";
  relPath += *it2;

  return relPath;
}



>> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic