Page 1 of 1

StripExtension

Posted: Fri Jan 25, 2008 12:40 am
by Mistrel
This one is pretty self-explanatory.

Code: Select all

Procedure.s StripExtension(Filename.s)
	For i=Len(Filename.s) To 1 Step -1
		If mid(Filename.s,i,1)="."
			ProcedureReturn Left(Filename.s,i-1)
		EndIf
	Next i
	ProcedureReturn Filename.s
EndProcedure

Debug StripExtension("This.ext")
End

Posted: Fri Jan 25, 2008 1:00 am
by Hroudtwolf
Hi. Nice idea.
But it is possible that your code is a little bit slowly.
Maybe my try could be faster.
But I didn't made speedtests.

Code: Select all

; PureBasic-Lounge.com
; Author: Hroudtwolf
; OS: Windows, Linux, OSX
; Demo: Yes

Structure tCHAR
   StructureUnion
      c.c
      s.s {1}
   EndStructureUnion
EndStructure

Procedure.s StripExtension (sFilename.s)
   Protected *Source.tCHAR     = @sFilename + (Len (sFilename) * SizeOf (tCHAR))
   Protected *EOS              = @sFilename
   Protected lFlag             = #False
   Protected sTemp  .s
   
   If Not *EOS : ProcedureReturn "" : EndIf
   
   While *EOS <= *Source
      If *Source\c = 46 And Not lFlag 
         lFlag = #True
         *Source - SizeOf (tCHAR)
      EndIf
      If lFlag
         sTemp = *Source\s + sTemp 
      EndIf
      *Source - SizeOf (tCHAR)
   Wend
   
   ProcedureReturn sTemp
EndProcedure

; Safety. Only the extensions will be cutted.
Debug StripExtension("This.ext.ext")
Debug StripExtension(".This.ext.ext")
Debug StripExtension("This.ext")
Best regards

Wolf

Posted: Fri Jan 25, 2008 1:13 am
by SFSxOI
Hey, I was just looking for something like this, how timely. Thank You :)

Posted: Fri Jan 25, 2008 1:32 am
by Hroudtwolf
Faster one.

Code: Select all

; PureBasic-Lounge.com
; Author: Hroudtwolf
; OS: Windows, Linux, OSX
; Demo: Yes

Structure tCHAR
   StructureUnion
      c.c
      s.s {1}
   EndStructureUnion
EndStructure

Procedure.s StripExtension (sFilename.s)
   Protected *Source.tCHAR     = @sFilename + (Len (sFilename) * SizeOf (tCHAR))
   Protected *EOS              = @sFilename
   
   If Not *EOS : ProcedureReturn "" : EndIf
   
   While *EOS <= *Source
      If *Source\c = 46
         ProcedureReturn PeekS (*EOS , *Source - *EOS)
      EndIf
      *Source - SizeOf (tCHAR)
   Wend
   
   ProcedureReturn ""
EndProcedure
Test

Code: Select all

Structure tCHAR
   StructureUnion
      c.c
      s.s {1}
   EndStructureUnion
EndStructure

Procedure.s StripExtension1 (sFilename.s)
   Protected *Source.tCHAR     = @sFilename + (Len (sFilename) * SizeOf (tCHAR))
   Protected *EOS              = @sFilename
   
   If Not *EOS : ProcedureReturn "" : EndIf
   
   While *EOS <= *Source
      If *Source\c = 46
         ProcedureReturn PeekS (*EOS , *Source - *EOS)
      EndIf
      *Source - SizeOf (tCHAR)
   Wend
   
   ProcedureReturn ""
EndProcedure

Procedure.s StripExtension2 (sFilename.s)
   For i=Len(sFilename.s) To 1 Step -1
      If Mid(sFilename.s,i,1)="."
         ProcedureReturn Left(sFilename.s,i-1)
      EndIf
   Next i
   ProcedureReturn sFilename.s
EndProcedure 

Define.s sTest
Define.l lTime1
Define.l lTime2

lTime1 = timeGetTime_()
For lI = 1 To 800000
   sTest = StripExtension1 ("Filename.extension")
Next lI
lTime1 = timeGetTime_() - lTime1

lTime2 = timeGetTime_()
For lI = 1 To 800000
   sTest = StripExtension2 ("Filename.extension")
Next lI
lTime2 = timeGetTime_() - lTime2

MessageBox_(0 , "StripExtension1 (MS):" + Str (lTime1) + #LF$ + "StripExtension2 (MS):" + Str (lTime2), "Test" , #MB_OK)

Posted: Fri Jan 25, 2008 1:32 am
by Mistrel
Why would my code run slowly, Hroudtwolf?

Posted: Fri Jan 25, 2008 1:33 am
by Hroudtwolf
Test it by yourself ;-)
But it isn't important for such function.
It's just fun to optimize it.

Posted: Fri Jan 25, 2008 10:37 am
by PB
My version (don't know how fast it is compared to the others, because
I'm far too lazy to cut-and-paste the other examples to test):

Code: Select all

Procedure.s StripExt(file$)
  e$=GetExtensionPart(file$) : If e$ : e=1 : EndIf
  ProcedureReturn Left(file$,Len(file$)-Len(e$)-e)
EndProcedure

Debug StripExt("iexplore.exe")
Debug StripExt("noextension")

Posted: Fri Jan 25, 2008 10:52 am
by PB
Okay, I added mine to the test and it comes second, which I think is a
good compromise between code size and speed. :)

BTW, a file called "file.name.ext" only has one extension, called "ext".
It's only the part from the final dot that is the actual extension.

Code: Select all

DisableDebugger

Structure tCHAR
   StructureUnion
      c.c
      s.s {1}
   EndStructureUnion
EndStructure

Procedure.s StripExtension1 (sFilename.s)
   Protected *Source.tCHAR     = @sFilename + (Len (sFilename) * SizeOf (tCHAR))
   Protected *EOS              = @sFilename

   If Not *EOS : ProcedureReturn "" : EndIf

   While *EOS <= *Source
      If *Source\c = 46
         ProcedureReturn PeekS (*EOS , *Source - *EOS)
      EndIf
      *Source - SizeOf (tCHAR)
   Wend

   ProcedureReturn ""
EndProcedure

Procedure.s StripExtension2 (sFilename.s)
   For i=Len(sFilename.s) To 1 Step -1
      If Mid(sFilename.s,i,1)="."
         ProcedureReturn Left(sFilename.s,i-1)
      EndIf
   Next i
   ProcedureReturn sFilename.s
EndProcedure

Procedure.s StripExt(file$)
  e$=GetExtensionPart(file$) : If e$ : e=1 : EndIf
  ProcedureReturn Left(file$,Len(file$)-Len(e$)-e)
EndProcedure

Define.s sTest
Define.l lTime1
Define.l lTime2

lTime1 = timeGetTime_()
For lI = 1 To 800000
   sTest = StripExtension1 ("Filename.extension")
Next lI
lTime1 = timeGetTime_() - lTime1

lTime2 = timeGetTime_()
For lI = 1 To 800000
   sTest = StripExtension2 ("Filename.extension")
Next lI
lTime2 = timeGetTime_() - lTime2

lTime3 = timeGetTime_()
For lI = 1 To 800000
   sTest = StripExt ("Filename.extension")
Next lI
lTime3 = timeGetTime_() - lTime3

MessageBox_(0 , "StripExtension1 (MS):" + Str (lTime1) + #LF$ + "StripExtension2 (MS):" + Str (lTime2) + #LF$ + "StripExtension3 (MS):" + Str (lTime3), "Test" , #MB_OK)

Posted: Fri Jan 25, 2008 1:45 pm
by AND51
@ StripExtension1
Len (sFilename) * SizeOf (tCHAR) = StringByteLength() :wink:

@ StripExtension, StripExtension1 and StripExtension2
:arrow: Your codes fail when you feed your procedures with "C:\Folder with .dot\no extension"


In a loop with 800000 loops, my procedure is ca. 29 ms slower than StripExtension1 (which is still the fastest), but it can handle full paths. remember that Linux ("/") and Windows ("\") are using different path-separators, so my procedure is cross-platform compatible.

Code: Select all

Procedure.s myStripExtension(filename$)
	Protected *dot.Character=@filename$+StringByteLength(filename$)-SizeOf(Character)
	While *dot\c
		If *dot\c = '\' Or *dot\c = '/'
			ProcedureReturn filename$
		ElseIf *dot\c = '.'
			ProcedureReturn PeekS(@filename$, *dot-@filename$)
		EndIf
		*dot-SizeOf(Character)
	Wend
	ProcedureReturn filename$
EndProcedure
800 000 loops:
StripExtension1: 439 ms
myStripExtenstion: 468 ms

Posted: Fri Jan 25, 2008 11:10 pm
by Psychophanta
My 1.5 cents:

Code: Select all

Macro ReplaceFilenameExtension(filename,newfilenameextension="")
  ReplaceString(filename#,"."+GetExtensionPart(filename#),newfilenameextension#,1,Len(filename#)-Len("."+GetExtensionPart(filename#)))
EndMacro

Debug ReplaceFilenameExtension("iexplore.exe")
Debug ReplaceFilenameExtension("noextension")
Debug ReplaceFilenameExtension("iexplore.exeeee.exeee.exe")
Debug ReplaceFilenameExtension("iexplore.exe.exeeee")
:)

Posted: Sat Jan 26, 2008 12:13 am
by Thalius
Mistrel wrote:Why would my code run slowly, Hroudtwolf?
i could imagine because of Len and Mid which iterate thru the stringbuffer til the end then you step back backwards and reiterate. So working once len is known with a pointer than reMidding the string in a loop is alot faster.

Thalius

Posted: Sat Jan 26, 2008 4:24 am
by Mistrel
Thalius wrote:
Mistrel wrote:Why would my code run slowly, Hroudtwolf?
i could imagine because of Len and Mid which iterate thru the stringbuffer til the end then you step back backwards and reiterate. So working once len is known with a pointer than reMidding the string in a loop is alot faster.

Thalius
Thank you. :)