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