News:

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

Search Replace String in a file

Started by ragdog, April 03, 2011, 06:59:12 AM

Previous topic - Next topic

ragdog

Hi

I use szRep from Masm32 Package for Search a string and Replace it
but if my Replace String to long have i a bug in my Replaced text.

Expl:

Search for Test123 and Replace with Replace123 or Replace12345

Greets

jj2007

How does it deviate from the docu?
the memory strategy for the destination buffer needs to be properly thought out to get reliable operation.
If the replacement is the same length as the text to replace or shorter, the destination buffer can safely be made
the same length as the source buffer but if the replacement text is longer, a method to calculate the extra size
of the destination buffer must be used


hutch--

Basically if the text you want to replace is shorter than the text you want to replace it with, you need to allocate a bigger buffer for the result. To calculate this difference you can use an algo like "szWcnt proc src:DWORD,txt:DWORD" in the masm32 library.

You need to do a bit of simple arithmetic but just calculate the maximum buffer length by knowing how much longer each pattern is multiplied by the number of ihstances of the text.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

ragdog

#3
@jj2007

Ohh i have not see :bg

So must i get from replace string the lenght  add to the Filesize and Allocate a new memory for the dest buffer?

to Hutch

example:

Lenght of Replace word * result of szWcnt + Filesize

The result if my size for Allocate the Dest buffer

invoke GlobalAlloc,GMEM_FIXED,Result <<<<<<<



invoke GlobalAlloc,GMEM_FIXED,hFileSize      ; allocate at least that much memory
                   mov hMem, eax
                invoke ReadFile,hFile,hMem,hFileSize,addr ByteWritten,NULL

;-----------------------------------------------------------------------
             invoke lstrlen,addr szWord1
                  mov ecx ,eax
               invoke szWcnt, hMem,addr szWord1
                  mov edx,ecx
                  mul edx
               invoke GlobalAlloc,GMEM_FIXED,edx      ; allocate at least that much memory
                  mov hMem2, eax
           invoke szRep,hMem,hMem2,addr szWord1,addr szWord2 ;perform replacement on its contents



Now Crash it with szRep if close my app
Remove i szRep Crash it not

hutch--

Somewhere along the line you are not using the return value from szWcnt and then you overwrite EAX with another function call. Look up how to use szWcnt in the help file.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

ragdog

I have read your source about szRep in masm32lib.hlp

what if "lsrc"?

add lsrc, 16384

Ok i have it running

you your source say you

QuoteWhile the text replacement technique is unproblematic, the memory strategy for the destination buffer needs to be properly thought out to get reliable operation. If the replacement is the same length as the text to replace or shorter, the destination buffer can safely be made the same length as the source buffer but if the replacement text is longer, a method to calculate the extra size of the destination buffer must be used

.if lwrd1 >= eax
; --------------
; simple replace
.else
; ---------------
; complex replace


But if my Replace text smaller or longer as the search text does it work
why?

jj2007

Quote from: ragdog on April 03, 2011, 10:44:00 AM
But if my Replace text smaller or longer as the search text does it work
why?

.data? segments are at least 4096 bytes long. So if you use
dest db 20 dup(?)
and no other data come after that, your code will not choke if the destination needs, say, 100 bytes instead of 20. But it would be dangerous to rely on that, of course.

ragdog

My source buffer pMem and pMem2 is Local
Or what mean you directly?

hutch--

Think of what is involved, if you want to replace "text" with "MY_LONG_TEXT" then you need to have a bigger output buffer to hold the longer result. You calculate this by counting the number of occurrences of "text" in your source. Subtract the length of "text" from the length of "MY_LONG_TEXT" and you have the difference. Multiply that difference by the number of occurrences and you have the extra size required.

Then you take the original buffer length and add the extra to it and the result will then fit into your output buffer.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

ragdog

Yes is logic but try it this works same with my complete text file

szSearch  db "text",0
szReplace db "MY_LONG_TEXT",0

I have make aTest

szSearch  db "MY_LONG_TEXT",0
szReplace db "text",0

I have by both the same result without a error in the text



LOCAL pMem:DWORD

invoke  VirtualAlloc,0,hFileSize,MEM_COMMIT,PAGE_READWRITE       
mov  pMem, eax
invoke  ReadFile,hFile,pMem,hFileSize,addr ByteWritten,NULL
invoke SearchAndReplace,pMem,addr szSearch ,addrszReplace
invoke  SetDlgItemText,hWnd,1002,pMem

invoke SearchAndReplace,pMem,addr szReplace,addr szSearch
invoke  SetDlgItemText,hWnd,1003,pMem



SearchAndReplace proc uses ecx pBuffer:DWORD ,lpszSearchFor:DWORD,lpszReplaceWith:DWORD
LOCAL pNumberOfWords:DWORD
LOCAL pMem:DWORD
   invoke  szWcnt,pBuffer,lpszSearchFor
      mov  pNumberOfWords,eax
      xor  ecx,ecx
   .while  ecx < pNumberOfWords
           invoke  VirtualAlloc,0,hFileSize,MEM_COMMIT,PAGE_READWRITE       
              mov  pMem, eax
           invoke  szRep,pBuffer,pMem,lpszSearchFor,lpszReplaceWith
           invoke  lstrcpy,pBuffer,pMem
           invoke  VirtualFree,pMem,0,MEM_RELEASE
              inc  ecx
   .endw
ret
SearchAndReplace endp

donkey

invoke  VirtualAlloc,0,hFileSize,MEM_COMMIT,PAGE_READWRITE

Should be

invoke  VirtualAlloc,0,hFileSize,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE

Quote from: MSDNYou can commit reserved pages in subsequent calls to the VirtualAlloc function. To reserve and commit pages in one step, call VirtualAlloc with MEM_COMMIT | MEM_RESERVE.

Can't say as I have ever run into a problem with MEM_COMMIT alone but Microsoft says it can result in a page fault and after all its their OS and they can change the memory allocation engine any time they want, better to stick to what the API says you are required to do.


As to the problem with the buffer why not just make a self expanding buffer ?
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

ragdog

self expanding buffer?

What mean you with it?

donkey

Quote from: ragdog on April 03, 2011, 07:55:46 PM
self expanding buffer?

What mean you with it?

Allocate memory using MEM_RESERVE and PAGE_NOACCESS, then write an SEH handler to trap the access violation (EXCEPTION_ACCESS_VIOLATION) when you attempt to write to it. Each time the error is trapped you simply commit another page of the reserved memory (MEM_COMMIT and PAGE_READWRITE), expanding the array, and continue at the instruction that caused the fault. You should also be able to use vectored exception handling which would make the code a little tighter and easier to manage however it would only be compatible with XP+.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

oex

Quote from: donkey on April 03, 2011, 08:06:29 PM
then write an SEH handler to trap the access violation (EXCEPTION_ACCESS_VIOLATION) when you attempt to write to it. Each time the error is trapped....

We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

Magnum

Quote from: ragdog on April 03, 2011, 07:55:46 PM
self expanding buffer?

What mean you with it?

I know for sure that you are from Germany.

The American language is an amalgam of different languages.

"What do you mean ?"  is what the Americans would say.

Outta here,
                 Andy

P.S.
     I read where Canada is the most "Americanized country" next to Saudia Arabia.

Have a great day,
                         Andy