AutoHotkey Community

It is currently May 25th, 2012, 6:45 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 40 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
 Post subject:
PostPosted: May 25th, 2007, 9:58 pm 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
Since I couldn't speed up my function to be as quick as yours, I optimized yours and added comments:
Code:
Removed: see first post


Edit: It now even covers current directory "./" or ".\"

_________________
Ciao
toralf
Image


Last edited by toralf on May 25th, 2007, 11:30 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 25th, 2007, 10:40 pm 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5346
Location: UK
You actually unoptimized it - you think I combine expressions for no reason? :P

If time really is of the essence I'd make a few more changes, like using StringTrimLeft to avoid expressions. UseErrorLevel and Looping is a bad idea, I had troubles with them when writing XPath. Here's another version that uses dynamic variables for a shorter script:

Code:
RelToAbs(d1, d2, s = "\") {
   d0 := SubStr(d1, 1, len := InStr(d1, s, "", InStr(d1, s . s) + 2) - 1)
      , d1 := SubStr(d1, len + 1), off := 0
   Loop, 2
      If InStr(d%A_Index%, s, "", 0) = StrLen(d%A_Index%)
         StringTrimRight, d%A_Index%, d%A_Index%, 1
   Loop, Parse, d2, %s%
      If InStr(A_LoopField, "..") = 1
         d1 := SubStr(d1, 1, InStr(d1, s, "", 0) - 1)
      Else If InStr(A_LoopField, ".") = 1
         StringTrimLeft, d2, d2, 2
      Else If A_LoopField =
      {
         d1 =
         StringTrimLeft, d2, d2, 1
      }
   StringReplace, d2, d2, ..%s%, , All
   Return, d0 . d1 . s . d2
}

Test with: MsgBox, % RelToAbs("http://example.com/info/sec/", "./data/get.html", "/")

_________________
GitHubScriptsIronAHK Contact by email not private message.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 25th, 2007, 11:02 pm 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
I tested our codes and mine seems to be 30% faster. What are your findings?

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 25th, 2007, 11:02 pm 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
Based on your code idea I improved RelativePath in speed and add more exeptions. Will post soon.

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 25th, 2007, 11:25 pm 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5346
Location: UK
Your function doesn't recurse, which means it fails to expand complex paths such as RelToAbs("http://example.com/info/sec/", "./.././/data/get.html", "/"). This is my final version:

Code:
RelToAbs(root, dir, s = "\") {
   pr := SubStr(root, 1, len := InStr(root, s, "", InStr(root, s . s) + 2) - 1)
      , root := SubStr(root, len + 1)
   If InStr(root, s, "", 0) = StrLen(root)
      StringTrimRight, root, root, 1
   If InStr(dir, s, "", 0) = StrLen(dir)
      StringTrimRight, dir, dir, 1
   Loop, Parse, dir, %s%
      If InStr(A_LoopField, "..") = 1 {
         StringTrimRight, root, root, InStr(root, s, "", 0) - 2
         StringTrimLeft, dir, dir, 3
      }
      Else If InStr(A_LoopField, ".") = 1
         StringTrimLeft, dir, dir, 2
      Else If A_LoopField =
      {
         root =
         StringTrimLeft, dir, dir, 1
      }
   Return, pr . root . s . dir
}


I benchmarked both of our functions and got this result:

Code:
Test   Time   Deviation   Rank
1      189       0.02      45%
2      153      -0.02      56%

Iterations           3062
Standard deviation   0.03

This shows that surprisingly the loop can be faster. However since the standard deviation is so low it's susceptible to fluctuation.

_________________
GitHubScriptsIronAHK Contact by email not private message.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 25th, 2007, 11:40 pm 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
Titan wrote:
Your function doesn't recurse, which means it fails to expand complex paths such as RelToAbs("http://example.com/info/sec/", "./.././/data/get.html", "/").
That might be leagal, but does seem to be very rare. I'm unsure if this should be considered, since it is the same as "../data/get.html" I guess.
I'll add a link from the first post.

First post got updated.

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 25th, 2007, 11:41 pm 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5346
Location: UK
But the whole point of this function is to expand relative paths, don't you think anything else defeats the objective?

_________________
GitHubScriptsIronAHK Contact by email not private message.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 25th, 2007, 11:56 pm 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
You are right, it should be fail save,
unfortunately your code fails on
Code:
MsgBox, % RelToAbs("\\server.com\user\Files\Docs\Code\AHK\SmartGui\no_commit\icons_dev", "..\..\..\SciTERelativePathector\includes\")

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 26th, 2007, 12:03 am 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
Replacing these two lines solves the problem
Code:
         AbsolutPath := SubStr(AbsolutPath, 1, InStr(AbsolutPath, s, "", 0) - 1)
;          StringTrimRight, AbsolutPath, AbsolutPath, InStr(AbsolutPath, s, "", 0) - 2     ;<= doesn't work


Edit or with this line
Code:
StringLeft, AbsolutPath, AbsolutPath, InStr(AbsolutPath, s, "", 0) - 1

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 26th, 2007, 12:15 am 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
I improved the speed of your code by nearly a factor of two. :) it is now only slightly slower then mine code with the advantage of recursive.
Code:
AbsolutePath(AbsolutPath, RelativePath, s = "\") {
   pr := SubStr(AbsolutPath, 1, len := InStr(AbsolutPath, s, "", InStr(AbsolutPath, s . s) + 2) - 1)   ;get server or drive name
      , AbsolutPath := SubStr(AbsolutPath, len + 1)           ;remove server or drive from AbsolutPath
   If InStr(AbsolutPath, s, "", 0) = StrLen(AbsolutPath)      ;remove last \ from AbsolutPath if any
      StringTrimRight, AbsolutPath, AbsolutPath, 1
   If InStr(RelativePath, s, "", 0) = StrLen(RelativePath)    ;remove last \ from RelativePath if any
      StringTrimRight, RelativePath, RelativePath, 1

   Loop, Parse, RelativePath, %s%                         ;go through RelativePath
      If (A_LoopField = "..") {                           ;when higher directory
         StringLeft, AbsolutPath, AbsolutPath, InStr(AbsolutPath, s, "", 0) - 1     ;remove one folder of AbsolutPath
      }Else If (A_LoopField = ".")                        ;when there is a dot
         Continue
      Else If (A_LoopField = "")                          ;when there is a \ infront of RelativePath
         AbsolutPath =                                       ;set AbsolutPath to nothing
      Else
         RestPath .= s . A_LoopField
   Return, pr . AbsolutPath . RestPath               ;concatenate server + AbsolutPath + RelativePath
}
Any bugs???

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 26th, 2007, 12:57 am 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5346
Location: UK
toralf wrote:
I improved the speed of your code by nearly a factor of two.
When I checked it was less than a 2% improvement, are you sure your benchmark scripts are reliable? Interesting concept you had though, but I came up with something else:

Code:
RelToAbs(root, dir, s = "") {
   pr := SubStr(root, 1, len := InStr(root, s, "", InStr(root, s . s) + 2) - 1)
      , root := SubStr(root, len + 1)
   If InStr(root, s, "", 0) = StrLen(root)
      StringTrimRight, root, root, 1
   If InStr(dir, s, "", 0) = StrLen(dir)
      StringTrimRight, dir, dir, 1
   sk = 0
   Loop, Parse, dir, %s%
   {
      If A_LoopField = ..
      {
         StringLeft, root, root, InStr(root, s, "", 0) - 1
         sk += 3
      }
      Else If A_LoopField = .
         sk += 2
      Else If A_LoopField =
      {
         root =
         sk++
      }
   }
   StringTrimLeft, dir, dir, sk
   Return, pr . root . s . dir
}

For the few microseconds it's worth this is over 10% faster.

_________________
GitHubScriptsIronAHK Contact by email not private message.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 26th, 2007, 7:09 am 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
are these valid relative paths?
Code:
../data/../field
../data//field
Then they should represent
Code:
../field
/field
right? These are not covered, are they?

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 26th, 2007, 9:14 am 
Offline

Joined: June 15th, 2006, 6:29 am
Posts: 59
Location: Oriel College
If performance is important, you may wish to investigate: shlwapi.dll
See here, particularly PathCombine and PathCanonicalize.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 26th, 2007, 9:59 am 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5346
Location: UK
JGR does it work with URIs?
toralf try this, it's still faster:

Code:
RelToAbs(root, dir, s = "\") {
   pr := SubStr(root, 1, len := InStr(root, s, "", InStr(root, s . s) + 2) - 1)
      , root := SubStr(root, len + 1), sk := 0
   If InStr(root, s, "", 0) = StrLen(root)
      StringTrimRight, root, root, 1
   If InStr(dir, s, "", 0) = StrLen(dir)
      StringTrimRight, dir, dir, 1
   Loop, Parse, dir, %s%
   {
      If A_LoopField = ..
         StringLeft, root, root, InStr(root, s, "", 0) - 1
      Else If A_LoopField =
         root =
      Else If A_LoopField != .
         Continue
      StringReplace, dir, dir, %A_LoopField%%s%
   }
   Return, pr . root . s . dir
}

_________________
GitHubScriptsIronAHK Contact by email not private message.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 26th, 2007, 10:03 am 
Offline

Joined: June 15th, 2006, 6:29 am
Posts: 59
Location: Oriel College
Yes. There are also UrlCombine, UrlCanonicalize, and for making relative path names PathRelativePathTo.
There are 76 functions which do various things with path and URL strings...

JGR


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 40 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Exabot [Bot], tkmmkt and 17 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group