Jump to content
Sign in to follow this  
funkey

Faster _PathSplit function

Recommended Posts

funkey

Hello, i just found the dll function _splitpath(), testet it and made a faster _PathSplit() function with the same results as the original.

#include <File.au3>

;~ Global $sFile = "C:\Program Files/Another Dir\AutoIt3\AutoIt3.chm"
;~ Global $sFile = @ScriptFullPath
;~ Global $sFile = "\\127.0.0.1/SharedDocs/foo.txt"
Global $sFile = "\\127.0.0.1/SharedDocs\ggg/foo.txt"

Global $szDrive, $szDir, $szFName, $szExt
Global $iStart, $iLoop = 10000

ConsoleWrite("_PathSplit" & @LF)
$iStart = TimerInit()
For $i = 1 To $iLoop
    _PathSplit($sFile, $szDrive, $szDir, $szFName, $szExt)
Next
ConsoleWrite(TimerDiff($iStart) & @LF)

ConsoleWrite($szDrive & @LF)
ConsoleWrite($szDir & @LF)
ConsoleWrite($szFName & @LF)
ConsoleWrite($szExt & @LF)
;~ MsgBox(48, $sFile, $szDrive & @LF & $szDir & @LF & $szFName & @LF & $szExt)

ConsoleWrite(@LF)
$szDrive = ""
$szDir = ""
$szFName = ""
$szExt = ""

ConsoleWrite("_PathSplit2" & @LF)
$iStart = TimerInit()
For $i = 1 To $iLoop
    _PathSplit2($sFile, $szDrive, $szDir, $szFName, $szExt)
Next
ConsoleWrite(TimerDiff($iStart) & @LF)

ConsoleWrite($szDrive & @LF)
ConsoleWrite($szDir & @LF)
ConsoleWrite($szFName & @LF)
ConsoleWrite($szExt & @LF)
;~ MsgBox(48, $sFile, $szDrive & @LF & $szDir & @LF & $szFName & @LF & $szExt)


Func _PathSplit2($szPath, ByRef $szDrive, ByRef $szDir, ByRef $szFName, ByRef $szExt)
    Local $sTemp, $pos, $pos2
    Local $aRet = DllCall("MSVCRT.DLL", "none:cdecl", "_wsplitpath", "wstr", $szPath, "wstr", "", "wstr", "", "wstr", "", "wstr", "")
    If $aRet[2] = "" Then   ; UNC path
        $sTemp = StringTrimLeft($aRet[3], 2)
        $pos = StringInStr($sTemp, "\")
        $pos2 = StringInStr($sTemp, "/")
        If $pos = 0 And $pos2 = 0 Then
            $szDrive = ""
            $szDir = $aRet[3]
        Else
            If $pos <> 0 And $pos < $pos2 Then
                $szDrive = StringLeft($aRet[3], $pos + 1)
                $szDir = StringTrimLeft($aRet[3], $pos + 1)
            Else
                $szDrive = StringLeft($aRet[3], $pos2 + 1)
                $szDir = StringTrimLeft($aRet[3], $pos2 + 1)
            EndIf
        EndIf
    Else
        $szDrive = $aRet[2]
        $szDir = $aRet[3]
    EndIf

    $szFName = $aRet[4]
    $szExt = $aRet[5]
EndFunc
Edited by funkey

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
PhoenixXL

I got this output

 

_PathSplit

480.500241946127

127.0.0.1
/SharedDocs/
foo
.txt
 
 
_PathSplit2
604.845887649017
127.0.0.1
/SharedDocs/
foo
.txt

My code:

PredictText: Predict Text of an Edit Control Like Scite. Remote Gmail: Execute your Scripts through Gmail. StringRegExp:Share and learn RegExp.

Run As System: A command line wrapper around PSEXEC.exe to execute your apps scripts as System (LSA). Database: An easier approach for _SQ_LITE beginners.

MathsEx: A UDF for Fractions and LCM, GCF/HCF. FloatingText: An UDF for make your text floating. Clipboard Extendor: A clipboard monitoring tool. 

Custom ScrollBar: Scroll Bar made with GDI+, user can use bitmaps instead. RestrictEdit_SRE: Restrict text in an Edit Control through a Regular Expression.

Share this post


Link to post
Share on other sites
funkey

For me it's always like this, so it's different on every machine. I didn't think of this, sorry.

UNC path

406.457246744497
\\127.0.0.1
/SharedDocs/
foo
.txt

315.326709386166
\\127.0.0.1
/SharedDocs/

Standard path

323.811346394686
C:
\Program Files/Another Dir\AutoIt3\
AutoIt3
.chm

221.623222230238
C:
\Program Files/Another Dir\AutoIt3\
AutoIt3
.chm

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
DXRW4E

No, is not fast, trytest "127.0.0.1/SharedDocsggg/foo.txt" ehhhhh

#include <File.au3>

;~ Global $sFile = "C:\Program Files/Another Dir\AutoIt3\AutoIt3.chm"
;~ Global $sFile = @ScriptFullPath
Global $sFile = "\\127.0.0.1/SharedDocs\ggg/foo.txt"

Global $szDrive, $szDir, $szFName, $szExt
Global $iStart, $iLoop = 10000

$iStart = TimerInit()
For $i = 1 To $iLoop
    _PathSplit2($sFile, $szDrive, $szDir, $szFName, $szExt)
Next
ConsoleWrite(TimerDiff($iStart) & @LF)

ConsoleWrite($szDrive & @LF)
ConsoleWrite($szDir & @LF)
ConsoleWrite($szFName & @LF)
ConsoleWrite($szExt & @LF)

ConsoleWrite(@LF)
$szDrive = ""
$szDir = ""
$szFName = ""
$szExt = ""

$iStart = TimerInit()
For $i = 1 To $iLoop
    _PathSplit($sFile, $szDrive, $szDir, $szFName, $szExt)
Next
ConsoleWrite(TimerDiff($iStart) & @LF)

ConsoleWrite($szDrive & @LF)
ConsoleWrite($szDir & @LF)
ConsoleWrite($szFName & @LF)
ConsoleWrite($szExt & @LF)


Func _PathSplit2($szPath, ByRef $szDrive, ByRef $szDir, ByRef $szFName, ByRef $szExt)
    Local $sTemp, $pos
    Local $aRet = DllCall("MSVCRT.DLL", "none:cdecl", "_splitpath", "str", $szPath, "str", "", "str", "", "str", "", "str", "")
    If $aRet[2] = "" Then   ; UNC path
        $sTemp = StringTrimLeft($aRet[3], 2)
        $pos = StringInStr($sTemp, "\")
        If $pos = 0 Then $pos = StringInStr($sTemp, "/")
        If $pos <> 0 Then
            $szDrive = StringLeft($aRet[3], $pos + 1)
            $szDir = StringTrimLeft($aRet[3], $pos + 1)
        Else
            $szDir = $aRet[3]
        EndIf
    Else
        $szDrive = $aRet[2]
        $szDir = $aRet[3]
    EndIf

    $szFName = $aRet[4]
    $szExt = $aRet[5]
EndFunc
;~ >Running AU3Check (3.3.11.3)  from:C:\Program Files (x86)\AutoIt3\Beta  input:C:\Users\DXRW4E\Desktop\New AutoIt v3 Script.au3
;~ +>16:33:33 AU3Check ended.rc:0
;~ >Running:(3.3.11.3):C:\Program Files (x86)\AutoIt3\Beta\autoit3.exe "C:\Users\DXRW4E\Desktop\New AutoIt v3 Script.au3"    
;~ --> Press Ctrl+Alt+F5 to Restart or Ctrl+Break to Stop
;~ 706.954906964859
;~ \\127.0.0.1/SharedDocs
;~ \ggg/
;~ foo
;~ .txt
;~ 
;~ 
;~ 564.625793920667
;~ \\127.0.0.1
;~ /SharedDocs/ggg/
;~ foo
;~ .txt
;~ +>16:33:34 AutoIt3.exe ended.rc:0
;~ +>16:33:34 AutoIt3Wrapper Finished..
;~ >Exit code: 0    Time: 1.828

Ciao.

Edited by DXRW4E

apps-odrive.pngdrive_app_badge.png box-logo.png new_logo.png MEGA_Logo.png

Share this post


Link to post
Share on other sites
supersonic

I've tested DRXW4E's code example and got the following results:

--> Press Ctrl+Alt+F5 to Restart or Ctrl+Break to Stop
367.492122034166
\\127.0.0.1/SharedDocs
\ggg/
foo
.txt
462.093395973904
\\127.0.0.1/SharedDocs
\ggg/
foo
.txt
+>07:43:36 AutoIt3.exe ended.rc:0
>Exit code: 0    Time: 1.249

So - for me - funkeys' solution is faster... At least it's a good example to make path splitting more easier...

Edited by supersonic

Share this post


Link to post
Share on other sites
DXRW4E

so I invented this return??

;~ >Running AU3Check (3.3.11.3)  from:C:\Program Files (x86)\AutoIt3\Beta  input:C:\Users\DXRW4E\Desktop\New AutoIt v3 Script.au3
;~ +>16:33:33 AU3Check ended.rc:0
;~ >Running:(3.3.11.3):C:\Program Files (x86)\AutoIt3\Beta\autoit3.exe "C:\Users\DXRW4E\Desktop\New AutoIt v3 Script.au3"    
;~ --> Press Ctrl+Alt+F5 to Restart or Ctrl+Break to Stop
;~ 706.954906964859
;~ \\127.0.0.1/SharedDocs
;~ \ggg/
;~ foo
;~ .txt
;~ 
;~ 
;~ 564.625793920667
;~ \\127.0.0.1
;~ /SharedDocs/ggg/
;~ foo
;~ .txt
;~ +>16:33:34 AutoIt3.exe ended.rc:0
;~ +>16:33:34 AutoIt3Wrapper Finished..
;~ >Exit code: 0    Time: 1.828

which version of autoit you are using ???, AutoIt _PathSplit func not return

127.0.0.1/SharedDocs
ggg/

AutoIt _PathSplit func return

\\127.0.0.1
/SharedDocs/ggg/

 
Ciao.

Edited by DXRW4E

apps-odrive.pngdrive_app_badge.png box-logo.png new_logo.png MEGA_Logo.png

Share this post


Link to post
Share on other sites
funkey

I'm on 3.3.8.1 and I didn't notice that _PathSplit() has been rewritten using regexp. So regexp version will be faster than DLL version.


Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
DXRW4E

Hi funkey, is all Ok, I really like the (_splitpath) dll mod, I do not understand why you used the

Local $aRet = DllCall("MSVCRT.DLL", "none:cdecl", "_splitpath", "str", $szPath, "str", "", "str", "", "str", "", "str", "")

and not

Local $aRet = DllCall("MSVCRT.DLL", "none:cdecl", "_wsplitpath", "wstr", $szPath, "wstr", "", "wstr", "", "wstr", "", "wstr", "")

Ciao.

  
  

Edited by DXRW4E

apps-odrive.pngdrive_app_badge.png box-logo.png new_logo.png MEGA_Logo.png

Share this post


Link to post
Share on other sites
funkey

Hi funkey, is all Ok, I really like the (_splitpath) dll mod, I do not understand why you used the

Local $aRet = DllCall("MSVCRT.DLL", "none:cdecl", "_splitpath", "str", $szPath, "str", "", "str", "", "str", "", "str", "")
and not

Local $aRet = DllCall("MSVCRT.DLL", "none:cdecl", "_wsplitpath", "wstr", $szPath, "wstr", "", "wstr", "", "wstr", "", "wstr", "")
Ciao.

You are right, wstring version of the function would be better, because it works with unicode paths, at least I hope it does.


Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Similar Content

    • Gibbo
      By Gibbo
      Recently I had the need to split paths like _PathSplit outside of AutoIt.
      Regular expressions seemed to be the way to go and it was fun to learn a bit more about their power.
      I backported it to AutoIt and now use it instead of _PathSplit.

      This should match any combination of:

      servershare[$] | Drive path filename .extention Some caveats:
      It only returns an array (returning strings via byref aswell seemed a tad overkill / messy)
      The Drive letter retains its trailing "" NOT the path (this seemed more sane as the path should be relative not anchored to the root of the drive) - Found that this was not so good for things like "C:" as the path shoud be set to "" not nothing


      ; #FUNCTION# ==================================================================================================================== ; Name...........: _PathSplitRegEx ; Description ...: Splits a path into the drive, directory, file name and file extension parts. An empty string is set if a part is missing. ; Syntax.........: _PathSplitRegEx($sPath) ; Parameters ....: $sPath - The path to be split (Can contain a UNC server or drive letter) ; Return values .: Success - Returns an array with 5 elements where 0 = original path, 1 = drive, 2 = directory, 3 = filename, 4 = extension ; Author ........: Gibbo ; Modified.......: ; Remarks .......: This function does not take a command line string. It works on paths, not paths with arguments. ; This differs from _PathSplit in that the drive letter or servershare retains the "" not the path ; RegEx Built using examples from "Regular Expressions Cookbook (O’Reilly Media, 2009)" ; Related .......: _PathSplit, _PathFull, _PathMake ; Link ..........: ; Example .......: Yes ; =============================================================================================================================== Func _PathSplitRegEx($sPath) if $sPath="" then Return SetError(1,0,"") Local Const $rPathSplit = '^(?i)([a-z]:|[a-z0-9_.$]+[a-z0-9_.]+$?)?((?:[^/:*?"<>|rn]+)*)?([^/:*?"<>|rn.]*)((?:.[^./:*?"<>|rn]+)?)$' Local $aResult = StringRegExp($sPath, $rPathSplit, 2) Switch @error Case 0 Return $aResult Case 1 Return SetError(2, 0, "") Case 2 ;This should never happen! EndSwitch EndFunc ;==>_PathSplitRegEx Anyhow, I hope someone else finds this useful

      Edit: @ScriptFullPath replaced with the parameter $sPath - Thanks czardas. Should have reread before posting.
      Edit2: Changed regex to move the trailing "" from the "root" to the begining of the path.
      Edit3: Edit destroyed the regex (why??) added below as well in plain code tags just in case it happens again:

      Local Const $rPathSplit = '^(?i)([a-z]:|[a-z0-9_.$]+[a-z0-9_.]+$?)?((?:[^/:*?"<>|rn]+)*)?([^/:*?"<>|rn.]*)((?:.[^./:*?"<>|rn]+)?)$'
×