FindMemory() FindMemoryString()
Posted: Sat Mar 30, 2024 11:19 pm
I thought here is a better place to publish it.
It is not assembler optimized, but it is flexible and cross platform.
FindMemoryString() is only for unicode strings, but it is twice faster, since the memory step is 2 and not 1.
It is not assembler optimized, but it is flexible and cross platform.
FindMemoryString() is only for unicode strings, but it is twice faster, since the memory step is 2 and not 1.

Code: Select all
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
DisableDebugger
CompilerEndIf
Procedure.i FindMemory(*Memory, *ToFind.Ascii, FindFromEnd.i=#False, MemoryLength.i=0, ToFindLength.i=0, ReturnOffset.i=#False, *StartPtr.Ascii=#Null)
Protected.i ByteLength, Result
Protected *MemoryEnd, *Ptr.Ascii, *FoundPtr, *Ptr2.Ascii, *ToFindTmp.Ascii, *ToFindEnd
If ToFindLength = 0
ByteLength = MemorySize(*ToFind)
Else
ByteLength = ToFindLength
EndIf
*ToFindTmp = *ToFind
*ToFindEnd = *ToFind + ByteLength
If FindFromEnd
If *StartPtr
*Ptr = *StartPtr - ByteLength
Else
*Ptr = *Memory + MemorySize(*Memory) - ByteLength
EndIf
Repeat
If *Ptr\a = *ToFindTmp\a
*Ptr2 = *Ptr + 1
*ToFindTmp + 1
While *Ptr2\a = *ToFindTmp\a
*Ptr2 + 1
*ToFindTmp + 1
If *ToFindTmp = *ToFindEnd
*FoundPtr = *Ptr
Break 2
EndIf
Wend
*ToFindTmp = *ToFind
EndIf
*Ptr - 1
Until *Ptr <= *Memory
Else
*MemoryEnd = *Memory + MemorySize(*Memory) - ByteLength
If *StartPtr
If *StartPtr\a = *ToFind\a
*Ptr = *StartPtr + 1
Else
*Ptr = *StartPtr
EndIf
Else
*Ptr = *Memory
EndIf
Repeat
If *Ptr\a = *ToFindTmp\a
*Ptr2 = *Ptr + 1
*ToFindTmp + 1
While *Ptr2\a = *ToFindTmp\a
*Ptr2 + 1
*ToFindTmp + 1
If *ToFindTmp = *ToFindEnd
*FoundPtr = *Ptr
Break 2
EndIf
Wend
*ToFindTmp = *ToFind
EndIf
*Ptr + 1
Until *Ptr >= *MemoryEnd
EndIf
If ReturnOffset
Result = *FoundPtr - *Memory
Else
Result = *FoundPtr
EndIf
ProcedureReturn Result
EndProcedure
Procedure.i FindMemoryString(*Memory, String$, FindFromEnd.i=#False, ReturnOffset.i=#False, *StartPtr.Character=#Null)
Protected.i StringByteLength, Result
Protected *MemoryEnd, *Ptr.Character, *FoundPtr, *Ptr2.Character, *String.Character
StringByteLength = StringByteLength(String$)
*String = @String$
If FindFromEnd
If *StartPtr
*Ptr = *StartPtr - StringByteLength
Else
*Ptr = *Memory + MemorySize(*Memory) - StringByteLength
EndIf
Repeat
If *Ptr\c = *String\c
*Ptr2 = *Ptr + 2
*String + 2
While *Ptr2\c = *String\c
*Ptr2 + 2
*String + 2
Wend
If *String\c = #Null
*FoundPtr = *Ptr
Break
EndIf
*String = @String$
EndIf
*Ptr - 2
Until *Ptr <= *Memory
Else
*MemoryEnd = *Memory + MemorySize(*Memory) - StringByteLength
If *StartPtr
If *StartPtr\c = *String\c
*Ptr = *StartPtr + 2
Else
*Ptr = *StartPtr
EndIf
Else
*Ptr = *Memory
EndIf
Repeat
If *Ptr\c = *String\c
*Ptr2 = *Ptr + 2
*String + 2
While *Ptr2\c = *String\c
*Ptr2 + 2
*String + 2
Wend
If *String\c = #Null
*FoundPtr = *Ptr
Break
EndIf
*String = @String$
EndIf
*Ptr + 2
Until *Ptr >= *MemoryEnd
EndIf
If ReturnOffset
Result = *FoundPtr - *Memory
Else
Result = *FoundPtr
EndIf
ProcedureReturn Result
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
Define.q StartTime, EndTime, Summ
Define HW$, Result$
Define *Memory, *Here, *HW
HW$ = "Hello World of "
*Memory = AllocateMemory(50 * 1024 * 1024) ; 50MB
If *Memory
PokeS(*Memory + 18205400, HW$ + "Europe !")
PokeS(*Memory + 26055450, HW$ + "America!")
PokeS(*Memory + 36750820, HW$ + "Asia !")
PokeS(*Memory + 39046460, HW$ + "Africa !")
PokeS(*Memory + 46750820, HW$ + "Oceania!")
Result$ = "Forward string search:" + #LF$
Repeat
StartTime = ElapsedMilliseconds()
*Here = FindMemoryString(*Memory, HW$, #False, #False, *Here)
EndTime = ElapsedMilliseconds()
If *Here
Result$ + PeekS(*Here + StringByteLength(HW$), 7) + " in " + Str(EndTime - StartTime) + "ms" + #LF$
Summ + (EndTime - StartTime)
EndIf
Until Not *Here
Result$ + "Summ: " + Str(Summ) + "ms" + #LF$
Result$ + #LF$ + "Reverse string search:" + #LF$
*Here = #Null
Summ = 0
Repeat
StartTime = ElapsedMilliseconds()
*Here = FindMemoryString(*Memory, HW$, #True, #False, *Here)
EndTime = ElapsedMilliseconds()
If *Here
Result$ + PeekS(*Here + StringByteLength(HW$), 7) + " in " + Str(EndTime - StartTime) + "ms" + #LF$
Summ + (EndTime - StartTime)
EndIf
Until Not *Here
Result$ + "Summ: " + Str(Summ) + "ms" + #LF$
FreeMemory(*Memory)
EndIf
*HW = UTF8(HW$)
If *HW
*Memory = AllocateMemory(50 * 1024 * 1024) ; 50MB
If *Memory
PokeS(*Memory + 18205400, HW$ + "Europe !", -1, #PB_UTF8|#PB_String_NoZero)
PokeS(*Memory + 26055450, HW$ + "America!", -1, #PB_UTF8|#PB_String_NoZero)
PokeS(*Memory + 36750820, HW$ + "Asia !", -1, #PB_UTF8|#PB_String_NoZero)
PokeS(*Memory + 39046460, HW$ + "Africa !", -1, #PB_UTF8|#PB_String_NoZero)
PokeS(*Memory + 46750820, HW$ + "Oceania!", -1, #PB_UTF8|#PB_String_NoZero)
Result$ + #LF$ + "Forward byte search:" + #LF$
Repeat
StartTime = ElapsedMilliseconds()
*Here = FindMemory(*Memory, *HW, #False, 0, MemorySize(*HW) - 1, #False, *Here)
EndTime = ElapsedMilliseconds()
If *Here
Result$ + PeekS(*Here + MemorySize(*HW) - 1, 7, #PB_UTF8) + " in " + Str(EndTime - StartTime) + "ms" + #LF$
Summ + (EndTime - StartTime)
EndIf
Until Not *Here
Result$ + "Summ: " + Str(Summ) + "ms" + #LF$
Result$ + #LF$ + "Reverse byte search:" + #LF$
*Here = #Null
Summ = 0
Repeat
StartTime = ElapsedMilliseconds()
*Here = FindMemory(*Memory, *HW, #True, 0, MemorySize(*HW) - 1, #False, *Here)
EndTime = ElapsedMilliseconds()
If *Here
Result$ + PeekS(*Here + MemorySize(*HW) - 1, 7, #PB_UTF8) + " in " + Str(EndTime - StartTime) + "ms" + #LF$
Summ + (EndTime - StartTime)
EndIf
Until Not *Here
Result$ + "Summ: " + Str(Summ) + "ms" + #LF$
FreeMemory(*Memory)
EndIf
FreeMemory(*HW)
EndIf
EnableDebugger
Debug Result$
CompilerEndIf