Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Sun Jul 24, 2005 6:42 pm Post subject: Binary Buffer Copy and Compare |
|
|
Since AHK does not yet directly support binary buffers (assignment truncates the variable at the first NULL; a=b -type comparisons ignore bytes after the first NULL), we need DLL calls for the basic operations. Following Chris' advice, I wrote the necessary functions. Unfortunately, the C runtime library msvcrt.dll is needed (most systems have it anyway).
StrLen does not work for binary buffers, either (only tell where the first NULL is), so these functions need an extra parameter, the actual length of the buffers (which can be smaller than the allocated memory). Setting the length to 0 makes the functions use all the allocated space for the buffers.
Hex2Bin and Bin2Hex convert data between binary form and double-digit hex strings.
BufferCopy copies (part of) a binary buffer into another variable.
BufferCompare compares two binary variables. The result is 0 at equality, otherwise the first different bytes determine the sign of the returned value: negative if the first parameter is smaller, positive if it is larger than the second parameter.
First some calling examples are given, with listing all the variables. The actual functions follow.
| Code: | hModule := DllCall("LoadLibrary","str","msvcrt.dll") ; Preloads C library
Hex2Bin(b0,"000102030405060708090a0b0c0d0e0f00")
Hex2Bin(b1,"000102030405060708090a0b0c0d0e0f01")
BufferCopy(a,b0,0,17)
BufferCopy(c,b0,2,15)
Bin2Hex(g,a,17)
Bin2Hex(h,c,15)
x := BufferCompare(a, b0,17)
y := BufferCompare(b1,b0,17)
MsgBox %g%`n%h%`n%x%`n%y%
GoSub $ ; ListVars for debug
DllCall("FreeLibrary", "UInt", hModule)
ExitApp
BufferCompare(ByRef a, Byref b, n=0) ; compare buffers
{ ; a <,=,> b: Return <,=,> 0
u := VarSetCapacity(a)
v := VarSetCapacity(b)
IfLess n, 1, SetEnv n,0xffffffff ; n = 0: compare all allocated
IfLess u,%n%, SetEnv n,%u% ; use at most the capacity of a
IfLess v,%n%, SetEnv n,%v% ; use at most the capacity of b
Return DllCall("msvcrt\memcmp", "UInt", &a, "UInt", &b, "UInt", n, "CDecl Int")
}
BufferCopy(ByRef a, Byref b, b0=0,n=0) ; copy buffer a <- b[b0 + 0..n-1]
{
m := VarSetCapacity(b)-b0
IfLess m,1, { ; nothing is left
a =
Return
}
IfLess n, 1, SetEnv n,0xffffffff ; n = 0: copy all allocated memory
IfLess m,%n%, SetEnv n,%m% ; copy at most the capacity
Granted := VarSetCapacity(a, n, 33) ; make sure a is large enough
IfLess Granted,%n%, {
ErrorLevel = Mem=%Granted% ; Error if not enough memory
Return
}
StringLeft a, a, n ; trim to the right length
DllCall("RtlMoveMemory", "UInt", &a, "UInt", &b + b0, "UInt", n)
}
Bin2Hex(ByRef h, ByRef b, n=0) ; n bytes binary data -> stream of 2-digit hex
{ ; n = 0: all (SetCapacity can be larger than used!)
format = %A_FormatInteger% ; save original integer format
SetFormat Integer, Hex ; for converting bytes to hex
m := VarSetCapacity(b)
If (n < 1 or n > m)
n := m
Address := &b
h =
Loop %n%
{
x := *Address ; get byte in hex
StringTrimLeft x, x, 2 ; remove 0x
x = 0%x% ; pad left
StringRight x, x, 2 ; 2 hex digits
h = %h%%x%
Address++
}
SetFormat Integer, %format% ; restore original format
}
Hex2Bin(ByRef b, h, n=0) ; n hex digit-pairs -> binary data
{ ; n = 0: all. (Only ByRef can handle binaries)
m := Ceil(StrLen(h)/2)
If (n < 1 or n > m)
n := m
Granted := VarSetCapacity(b, n, 33)
IfLess Granted,%n%, {
ErrorLevel = Mem=%Granted%
Return
}
StringLeft b, b, n
Address := &b
Loop %n%
{
StringLeft x, h, 2
StringTrimLeft h, h, 2
x = 0x%x%
DllCall("RtlFillMemory", "UInt", Address, "UInt", 1, "UChar", x)
Address++
}
}
$:
ShowVars: ; list vars, wait until closed (ESC, [x])
ListVars ; Subroutine shows function locals, too
WinGet ID, ID, A ; note ListVars window ID
Loop
{
Sleep 30
IfWinNotExist ahk_id %ID%
break
}
Return |
|
|