News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

FileName from Path

Started by jckl, March 15, 2006, 03:03:16 AM

Previous topic - Next topic

jckl

How would i get a file name from a path?? I didnt see an API call for it and the only thing i thought of is a loop from end to start and when i find the first \ shift all charactors but i couldnt get that working.

Timbo

That's pretty much the way to do it without using API (like you, I don't know of one either).  Walk the string backwards stuffing each character into a buffer until you hit '\' at which point you know you are finished.

If you post some code, we can help you better.

Tim

zooba

PathRemoveFileSpec from shlwapi.dll will do it.

Cheers,

Zooba :U

jckl

hmmm just as i figured it out.. Thx tho.. Also here is what i came up with. Would you recommend one over the other?


GetFileNameFromPath PROC SRC:DWORD, DST:DWORD
   LOCAL ln:DWORD
   LOCAL lnst:DWORD

   push edi
   INVOKE StrLen,SRC
   mov lnst, eax
   mov ln, 0
   mov edx, SRC
   mov esi, lnst

  @@:
   sub esi, 1
   add ln, 1
   mov al, [edx+esi]
   cmp al,"\"
   jnz @B
   sub ln, 1
   mov eax, lnst
   sub eax, ln
   add edx, eax
   mov edi, DST
   xor ecx, ecx
  @@:
   mov al, [edx+ecx]
   mov [edi+ecx], al
   add ecx, 1
   test al, al
   jne @B
   pop edi
   mov eax, DST

   ret
GetFileNameFromPath endp

jckl

also PathFindFileName looks more like what i would want since i want the file name.

zooba

Hehe, good point. Guess I didn't read the original question properly... :red

Probably a better solution is to simply point to the start of the filename. Find the last '\' like you have been and then pass the address of the next byte to whatever function you're using. This will save shifting it all along.

Keep in mind that you can't pass this value to a free memory function :U

jckl

so more like this or did i misunderstand what you said??


GetFileNameFromPath PROC SRC:DWORD, DST:DWORD
   push edi
   mov ecx, SRC
  @@:
   mov al, [ecx]
   add ecx, 1
   test al, al
   je @F
   cmp al, "\"
   jne @B
   mov edx, ecx
   jmp @B
  @@:
   mov edi, DST
   xor ecx, ecx
  @@:
   mov al, [edx+ecx]
   mov [edi+ecx], al
   add ecx, 1
   test al, al
   jne @B
   pop edi
   mov eax, DST
   ret
GetFileNameFromPath endp

Timbo

jckl,

This is what I cooked up.  It takes the address of the path string and returns the address of the first byte after the last '\':

Path2FileName proc lpSrc:dword
push edx
mov edx, lpSrc          ;edx = starting address of the string to process
invoke lstrlen, lpSrc
add edx, eax            ;edx = address of the last byte of the string

findbackslash:
mov al, [edx]           
cmp al, '\'             ;is it a backslash?
je backslashfound         
dec edx                 ;keep walking backwards
jmp findbackslash

backslashfound:
inc edx                 ;move forward a character as we were last pointing to a '\'
mov eax, edx            ;return the address of the byte we want.
pop edx
ret
Path2FileName endp


See if it meets your requirements.  It doesn't produce a new string, but makes your existing string usable for your purpose.

Regards,

Tim

jckl

well i need to keep the old one with the full path aswell so that wouldnt work. I need it to be put in a new string so i have both. Thanks tho  :bg

Timbo

jckl,

It doesn't alter the original string.  It only yields the portion of the full path that represents the file name without the path.  This way does yield both.

Regards,

Tim

evlncrn8

Quote from: jckl
findbackslash:
mov al, [edx

cmp al, '\'             ;is it a backslash?
je backslashfound         
dec edx                 ;keep walking backwards
jmp findbackslash

technically u got a bug there, if the string doesnt have a backslash in it (and i have seen some return with / instead of \) your code will most likely screw up
best check that edx >= start of string :)

skywalker

Quote from: jckl on March 15, 2006, 03:03:16 AM
How would i get a file name from a path?? I didnt see an API call for it and the only thing i thought of is a loop from end to start and when i find the first \ shift all charactors but i couldnt get that working.

Here some code that should be of value.



[attachment deleted by admin]

PBrennick

From masm32 in the m32lib folder - namefpth.asm

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    .486
    .model flat, stdcall  ; 32 bit memory model
    option casemap :none  ; case sensitive

    .code

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

align 4

NameFromPath proc src:DWORD,dst:DWORD

    push esi
    push edi

    mov esi, src
    mov ecx, esi
    mov edx, -1
    xor eax, eax

  @@:
    add edx, 1
    cmp BYTE PTR [esi+edx], 0       ; test for terminator
    je @F
    cmp BYTE PTR [esi+edx], "\"     ; test for "\"
    jne @B
    mov ecx, edx
    jmp @B
  @@:
    cmp ecx, esi                    ; test if ECX has been modified
    je error                        ; exit on error if it is the same
    lea ecx, [ecx+esi+1]            ; add ESI to ECX and increment to following character
    mov edi, dst                    ; load destination address
    mov edx, -1
  @@:
    add edx, 1
    mov al, [ecx+edx]               ; copy file name to destination
    mov [edi+edx], al
    test al, al                     ; test for written terminator
    jnz @B

    sub eax, eax                    ; return value zero on success
    jmp nfpout

  error:
    mov eax, -1                     ; invalid path no "\"

  nfpout:

    pop edi
    pop esi

    ret

NameFromPath endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end


Paul
The GeneSys Project is available from:
The Repository or My crappy website

MichaelW

There is also the CRT _splitpath function.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc

    ; These from stdlib.h:

    _MAX_PATH   equ 260   ; max. length of full pathname
    _MAX_DRIVE  equ 3     ; max. length of drive component
    _MAX_DIR    equ 256   ; max. length of path component
    _MAX_FNAME  equ 256   ; max. length of file name component
    _MAX_EXT    equ 256   ; max. length of extension component

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      modpath    db _MAX_PATH   dup(0)
      moddrive   db _MAX_DRIVE  dup(0)
      moddir     db _MAX_DIR    dup(0)
      modfname   db _MAX_FNAME  dup(0)
      modext     db _MAX_EXT    dup(0)
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    invoke GetModuleFileName, 0, ADDR modpath, _MAX_PATH
    print ADDR modpath,13,10

    invoke crt__splitpath,ADDR modpath,
                          ADDR moddrive,
                          ADDR moddir,
                          ADDR modfname,
                          ADDR modext

    print ADDR moddrive, 13,10
    print ADDR moddir, 13,10
    print ADDR modfname, 13,10
    print ADDR modext, 13,10
   
    inkey "Press any key to exit..."
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start



eschew obfuscation

lingo

Why not a bit faster.. :lol
OPTION PROLOGUE:NONE ; turn it off
OPTION EPILOGUE:NONE
FileNameFromPath proc       lpPath:DWORD
mov eax, [esp+4] ; eax->lpPath
mov [esp+4], ebx ; saving ebx register
mov ebx, [eax] ;
mov ecx, eax ; eax->lpPath
@LV1:
lea edx, [ebx-1010101h]
xor ebx, 5C5C5C5Ch ; 5Ch -> ASCII code of "\"
add ecx, 4 
sub ebx, 1010101h ;
or edx, ebx ; testing "\" and 0 simultaneously
mov ebx, [ecx] ; ebx-> next dword
and edx, 80808080h ;
je @LV1
cmp byte ptr [ecx-4], 5Ch ; 5Ch -> ASCII code of "\"
mov edx, -4
jne @LV4
@LV2:
lea eax, [ecx+edx+1] ; eax->address of next char after "\"
@LV3:
add edx, 1
je @LV1
cmp byte ptr [ecx+edx], 5Ch ; 5Ch -> ASCII code of "\"
je @LV2
@LV4:
cmp byte ptr [ecx+edx], 0 ; is it end of string?
jne @LV3
mov ebx, [esp+4] ; restore ebx register
ret 4
FileNameFromPath endp
OPTION PROLOGUE:PROLOGUEDEF ; turn back on the defaults
OPTION EPILOGUE:EPILOGUEDEF


Regards,
Lingo