实现一个高效的二进制数据搜索工具(InBin函数)。它可以在指定的内存区域中快速搜索子数据(Needle)在目标数据(Haystack)中的位置,同时支持多种搜索方式,例如:
- 正常搜索:从左到右查找子数据。
- 反向搜索:从右到左查找子数据。
- 指定第n次出现:支持从左或从右指定第n次匹配。
- 大小写敏感/不敏感搜索。
; 更多深入用法示例:https://www.autohotkey.com/boards/viewtopic.php?f=6&t=90318
#NoEnv
#Warn
#SingleInstance, Force
Hay := "The Quick Brown Fox Jumps Over the Lazy Dog"
HayLen := VarSetCapacity(Hay)
Ndl := "o"
NdlLen := 1
FoundPtr := InBin(&Hay, HayLen, &Ndl, NdlLen) ; 正常搜索
MsgBox % StrGet( FoundPtr )
FoundPtr := InBin(&Hay, HayLen, &Ndl, NdlLen,, 0) ; 从右侧搜索
MsgBox % StrGet( FoundPtr )
FoundPtr := InBin(&Hay, HayLen, &Ndl, NdlLen,, 0, 2) ; 从右侧搜索第2次出现
MsgBox % StrGet( FoundPtr )
FoundPtr := InBin(&Hay, HayLen, &Ndl, NdlLen, 0, 0, 2) ; 从右侧搜索第2次出现,不区分大小写
MsgBox % StrGet( FoundPtr )
InBin( pHaystack, HaystackBytes, pNeedle, NeedleBytes:=0, CaseSensitive:=1, StartingPos:=1, Occurence:=1 ) {
Local ; InBin v0.60 by SKAN on D456/D459 @ tiny.cc/inbin
Static InBinMcode := InBin(0,0,0,0)
Static MemCpyLower := InBinMcode + (A_PtrSize=8 ? 204 : 184)
If !VarSetCapacity(InBinMcode) {
M1 := DllCall("Kernel32.dll\GlobalAlloc", "Int",0, "Ptr",Msz := A_PtrSize=8 ? 268 : 248, "UPtr")
M2 := DllCall("Kernel32.dll\VirtualProtect", "Ptr",M1, "Ptr",Msz, "Int",0x40, "IntP",0)
M3 := DllCall("Crypt32.dll\CryptStringToBinary", "Str",A_PtrSize=8
? "U1ZXQVSLRCRIRItcJFCJ00Qpy4XAvgEAAABBuv////9BD07yhcB+B2dEjVD/6wgBwkGJ0kUpykGD6QFFhdJyQzHSQTnadzxEidBB"
. "ijhAODwBdShEichBigQAZ0ONPAqJ/zgEOXUVQYP5AnMbg8IB6wVEOc909kQ52nRDQQHyRYXSc78xwOs9vwEAAABBg/kBdt8PH0QA"
. "AGYPH4QAAAAAAIn4QYoEAGdFjSQ6RYnkQjgEIXW9g8cBRDnPcuTrs0SJ0EgByEFcX15bwwAARYXAdjoxwEGJwUaKFAlBgPpAdhJB"
. "icNCgDwZW3MIQbsgAAAA6wNFMdtFD7bSRQHaRYjSRogUCoPAAUQ5wHLIww" : "VYnlg+wQU1ZXi1UIi00Qi3UUi0UMKfC"
. "JRfQxwIN9GAAPntD32IPg/kCJRfyDfRgAfgmLRRhIiUX46wuLRQwDRRgp8IlF+ItF+InHToX/cjvHRfAAAAAAO330dy+KBDo6AXU"
. "hjQQ3igQCOgQxdRaD/gJzHP9F8OsEOfN094tF8DtFHHQnA338hf9zzDHA6x+7AQAAAIP+AXbfjQQfigQCOgQZddRDOfNy8OvNjQQ"
. "6X15biexdwwAAAFNWV4tEJBCLVCQUi0wkGIXJdiYx9oocMID7QHYNgDwwW3MHvyAAAADrAjH/D7bbAfuIHDJGOc5y3F9eW8MAAAA"
, "Int",A_PtrSize=8 ? 358 : 331, "Int",0x1, "Ptr",M1, "IntP",Msz, "Int",0, "Int",0)
Return M1
}
If NeedleBytes is number
{
NeedleBytes := Max(-8, Format("{:d}", NeedleBytes))
If ( NeedleBytes<0 && NeedleBytes>-9 ) {
VarSetCapacity(Bin,8)
pNeedle := NumPut(pNeedle, Bin, "UInt64") - 8
NeedleBytes := Abs(NeedleBytes)
} Else If ( NeedleBytes=0 ) {
Src := StrReplace(pNeedle,A_Space)
Len := StrLen(Src)
NeedleBytes := Ceil(Len/2)
VarSetCapacity(Bin, NeedleBytes, 0)
If !DllCall("Crypt32.dll\CryptStringToBinary", "Str",Src, "Int",Len, "Int",12
, "Ptr",pNeedle := &Bin, "UIntP",NeedleBytes, "Int",0, "Int",0)
Return (0, ErrorLevel := "Hex to Bin conversion failed.")
}
} Else If ( InStr(".double.float.uint64.int64.uint.int.ushort.short.uptr.ptr.uchar.char."
, "." . RTrim(NeedleBytes, "*p") . ".") ) {
VarSetCapacity(Bin, 8, 0)
NeedleBytes := NumPut(pNeedle, &Bin, NeedleBytes) - &Bin
pNeedle := &Bin
} Else {
m := ( NeedleBytes="utf-16" || NeedleBytes="cp1200" ? 2 : 1 )
If ! ( nBytes := StrPut(pNeedle, NeedleBytes) - 1 )
Return (0, ErrorLevel := "String encode failed: '" . NeedleBytes . "'")
VarSetCapacity(sStr, nBytes * m)
nBytes := StrPut(pNeedle, &sStr, nBytes, NeedleBytes)
pNeedle := &sStr, NeedleBytes := nBytes * m
}
NeedleBytes := Min(256, NeedleBytes)
Occurence := Max(1, Format("{:d}", Occurence))
, CaseSensitive := !!CaseSensitive
If ( CaseSensitive=0 && HaystackBytes>0x1000000 )
Return (0, ErrorLevel := "Haystack too large for case-insensitve search. (Limit: 16 MiB)")
If ( HaystackBytes - NeedleBytes - (StartingPos>0 ? StartingPos-1 : Abs(StartingPos)) < 0 )
Return (0, ErrorLevel := "Haystack is too small to accomodate StartPosition and Needle")
If (CaseSensitive = False) {
VarSetCapacity(Hay, HaystackBytes), pHaystack2 := &Hay
DllCall(MemCpyLower, "Ptr",pHaystack, "Ptr",pHaystack2, "Int", HaystackBytes, "CDecl")
VarSetCapacity(Ndl, NeedleBytes), pNeedle2 := &Ndl
DllCall(MemCpyLower, "Ptr",pNeedle, "Ptr",pNeedle2, "Int", NeedleBytes, "CDecl")
}
FoundPtr := DllCall(InBinMcode, "Ptr",CaseSensitive ? pHaystack : pHaystack2, "Int", HaystackBytes
, "Ptr",CaseSensitive ? pNeedle : pNeedle2, "Short", NeedleBytes
, "Int",StartingPos, "Int",Occurence, "CDecl Ptr")
ErrorLevel := ( FoundPtr="" ? "Memory access violation" : FoundPtr=0 ? "Needle not found." : "" )
Return ( FoundPtr ? ( CaseSensitive ? FoundPtr : pHaystack + FoundPtr - pHaystack2 ) : FoundPtr )
}
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。

评论(0)