Code : Tout sélectionner
#include-once
#include <AutoItConstants.au3>
#include <Math.au3>
Global Const $_TAB = ' '
; user-callable function, so that noone messes with __VarDump indentation
; $vVar is the variable to be dumped
; $iLimit is the max number of entries of an array, map or DllStruct array element to be displayed in full
Func _VarDump(ByRef $vVar, $iLimit = 20)
If $iLimit < 3 Then $iLimit = 0
Return(__VarDump($vVar, $iLimit))
EndFunc ; =>_VarDump
Func __VarDump(ByRef $vVar, $iLimit, $sIndent = '')
Local $ret, $len, $ptr
Select
Case IsString($vVar)
$len = StringLen($vVar)
Return 'String (' & $len & ") " & __DumpStr($vVar)
Case VarGetType($vVar) = "Double"
Return 'Double ' & $vVar & (IsInt($vVar) ? '.0' : '')
Case IsInt($vVar)
Return VarGetType($vVar) & ' ' & $vVar
Case IsArray($vVar)
Local $iDimensions = UBound($vVar, 0)
Local $iCells = 1
$ret = 'Array'
$iDimensions -= 1
For $i = 0 To $iDimensions
$ret &= '[' & UBound($vVar, $i + 1) & ']'
$iCells *= UBound($vVar, $i + 1)
Next
If $iCells = 0 Then
Return $ret & $_TAB & ' (array is empty)'
Else
Return $ret & @CRLF & __VarDumpArray($vVar, $iLimit, $sIndent)
EndIf
Case IsBinary($vVar)
$len = BinaryLen($vVar)
$ret = 'Binary (' & BinaryLen($vVar) & ') '
Return($ret & (($len <= 32) ? $vVar : BinaryMid($vVar, 1, 16) & ' ... ' & StringTrimLeft(BinaryMid($vVar, $len - 15, 16), 2)))
Case IsBool($vVar)
Return 'Boolean ' & $vVar
Case IsKeyword($vVar)
Return('Keyword ' & ($vVar = Null ? 'Null' : ($vVar = Default ? 'Default' : 'Other keyword')))
Case IsHWnd($vVar)
Return 'HWnd ' & $vVar
Case IsPtr($vVar)
Return 'Pointer ' & $vVar
Case IsObj($vVar)
Return 'Object ' & ObjName($vVar)
Case IsFunc($vVar)
Return StringFormat('%-13s', VarGetType($vVar)) & FuncName($vVar)
Case IsDllStruct($vVar)
$len = DllStructGetSize($vVar)
$ptr = DllStructGetPtr($vVar)
$ret = 'Struct (' & $len & ') @:' & Hex($ptr) & ' (structure alignment is unknown)' & @CRLF
Local $nbElem = 1, $idx, $incr, $data, $type, $indent = $sIndent & $_TAB, $oldvalue, $readvalue, $field, $elem
While 1
$data = DllStructGetData($vVar, $nbElem)
If @error = 2 Then ExitLoop
$type = VarGetType($data)
$idx = 1
$incr = 0
; determine max index of element
While 1
DllStructGetData($vVar, $nbElem, 2 * $idx)
If @error = 3 Then ExitLoop
$incr = $idx
$idx *= 2
WEnd
; index is in [$idx, (2 * $idx) - 1]
$idx += $incr
Do
DllStructGetData($vVar, $nbElem, $idx)
If @error = 3 Then
; approach is asymetric (upper bound is too big)
$idx -= ($incr = 1) ? 1 : $incr / 2
Else
$idx += Int($incr / 2)
EndIf
$incr = Int($incr / 2)
Until $incr = 0
Switch $type
Case "Int32", "Int64"
$ret &= $indent
$data = DllStructGetData($vVar, $nbElem, 1)
DllStructSetData($vVar, $nbElem, 0x7777666655554433, 1)
$readvalue = DllStructGetData($vVar, $nbElem, 1)
Switch $readvalue
Case 0x7777666655554433
$elem = "int64"
; alias: uint64
; alias: int_ptr(x64), long_ptr(x64), lresult(x64), lparam(x64)
; alias: uint_ptr(x64), ulong_ptr(x64), dword_ptr(x64), wparam(x64)
Case 0x55554433
DllStructSetData($vVar, $nbElem, 0x88887777, 1)
$readvalue = DllStructGetData($vVar, $nbElem, 1)
$elem = ($readvalue > 0 ? "uint" : "int")
; int aliases: long, bool, int_ptr(x86), long_ptr(x86), lresult(x86), lparam(x86);
; uint aliases: ulong, dword, uint_ptr(x86), ulong_ptr(x86), dword_ptr(x86), wparam(x86)
Case 0x4433
DllStructSetData($vVar, $nbElem, 0x8888, 1)
$readvalue = DllStructGetData($vVar, $nbElem, 1)
$elem = ($readvalue > 0 ? "ushort" : "short")
; ushort alias: word
Case 0x33
$elem = "byte"
; alias: ubyte
EndSwitch
DllStructSetData($vVar, $nbElem, $data, 1)
If $idx = 1 Then
$ret &= StringFormat('%-' & 9 + StringLen($len) & 's ', $elem) & $data & @CRLF
Else
$ret &= $elem & "[" & $idx & "]" & @CRLF
For $i = 1 To $idx
If $iLimit And $idx > $iLimit And $i > $iLimit Then
$ret &= $indent & StringFormat('%-' & 9 + StringLen($len) & 's ', '') & '... there are ' & $idx - $iLimit & ' more ' & $elem & ' in this array' & @CRLF
ExitLoop
Else
$ret &= $indent & StringFormat('%-' & 9 + StringLen($len) & 's ', '') & DllStructGetData($vVar, $nbElem, $i) & @CRLF
EndIf
Next
EndIf
Case "String"
$oldvalue = DllStructGetData($vVar, $nbElem, 1)
DllStructSetData($vVar, $nbElem, ChrW(0x2573), 1)
$readvalue = DllStructGetData($vVar, $nbElem, 1)
DllStructSetData($vVar, $nbElem, $oldvalue, 1)
$elem = ($readvalue = ChrW(0x2573) ? "wchar" : "char")
If $idx > 1 Then $elem &= "[" & $idx & "]"
$ret &= $indent & StringFormat('%-' & 9 + StringLen($len) & 's ', $elem) & __DumpStr($data) & @CRLF
Case "Binary"
Local $blen = BinaryLen($data)
$elem = "byte"
If $idx > 1 Then $elem &= "[" & $idx & "]"
$ret &= $indent & StringFormat('%-' & 9 + StringLen($len) & 's ', $elem) & (($blen <= 32) ? $data : BinaryMid($data, 1, 16) & ' ... ' & StringTrimLeft(BinaryMid($data, $blen - 15, 16), 2)) & @CRLF
Case "Ptr"
$ret &= $indent
$elem = "ptr"
; alias: hwnd, handle
If $idx = 1 Then
$ret &= StringFormat('%-' & 9 + StringLen($len) & 's ', $elem) & $data & @CRLF
Else
$ret &= $elem & "[" & $idx & "]" & @CRLF
For $i = 1 To $idx
$ret &= $indent & StringFormat('%-' & 9 + StringLen($len) & 's ', '') & DllStructGetData($vVar, $nbElem, $i) & @CRLF
Next
EndIf
Case "Double"
$ret &= $indent
$oldvalue = DllStructGetData($vVar, $nbElem, 1)
DllStructSetData($vVar, $nbElem, 10^-15, 1)
$readvalue = DllStructGetData($vVar, $nbElem, 1)
DllStructSetData($vVar, $nbElem, $oldvalue, 1)
$elem = ($readvalue = 10^-15 ? "double" : "float")
If $idx = 1 Then
$ret &= StringFormat('%-' & 9 + StringLen($len) & 's ', $elem) & $data & (IsInt($data) ? '.0' : '') & @CRLF
Else
$ret &= $elem & "[" & $idx & "]" & @CRLF
For $i = 1 To $idx
If $iLimit And $idx > $iLimit And $i > $iLimit Then
$ret &= $indent & StringFormat('%-' & 9 + StringLen($len) & 's ', '') & '... there are ' & $idx - $iLimit & ' more ' & $elem & ' in this array' & @CRLF
ExitLoop
Else
$ret &= $indent & StringFormat('%-' & 9 + StringLen($len) & 's %s', '', DllStructGetData($vVar, $nbElem, $i)) & (IsInt(DllStructGetData($vVar, $nbElem, $i)) ? '.0' : '') & @CRLF
EndIf
Next
EndIf
EndSwitch
$nbElem += 1
WEnd
Return StringTrimRight($ret, 2)
Case IsMap($vVar)
Local $iCells = UBound($vVar)
$ret = 'Map[' & $iCells & ']'
If $iCells = 0 Then
Return $ret & $_TAB & ' (map is empty)'
Else
Return $ret & @CRLF & __VarDumpMap($vVar, $iLimit, $sIndent)
EndIf
Case Else
Return StringFormat('%-13s', VarGetType($vVar)) & $vVar
EndSelect
EndFunc ;==>__VarDump
Func __VarDumpArray(ByRef $aArray, $iLimit, $sIndent = $_TAB)
Local $sDump, $sArrayFetch, $sArrayRead, $iDone = 0, $iElements = 1
Local $iDimensions = UBound($aArray, 0)
Local $aUBounds[$iDimensions]
Local $aIndices[$iDimensions]
$iDimensions -= 1
For $i = 0 To $iDimensions
$aUBounds[$i] = UBound($aArray, $i + 1) - 1
$iElements *= $aUBounds[$i] + 1
$aIndices[$i] = 0
Next
$sIndent &= $_TAB
While $iDone < ($iLimit ? _Min($iLimit, $iElements) : $iElements)
$sArrayFetch = ''
For $i = 0 To $iDimensions
$sArrayFetch &= '[' & $aIndices[$i] & ']'
Next
$sArrayRead = Execute('$aArray' & $sArrayFetch)
$sDump &= $sIndent & $sArrayFetch & ' => ' & __VarDump($sArrayRead, $iLimit, $sIndent) & @CRLF
$iDone += 1
If $iLimit And $iDone = $iLimit Then
$sDump &= $sIndent & '... there are ' & $iElements - $iDone & ' more elements in this array' & @CRLF
ExitLoop
EndIf
For $i = $iDimensions To 0 Step -1
$aIndices[$i] += 1
If $aIndices[$i] > $aUBounds[$i] Then
$aIndices[$i] = 0
Else
ExitLoop
EndIf
Next
WEnd
Return(StringTrimRight($sDump, 2))
EndFunc ;==>__VarDumpArray
Func __VarDumpMap(ByRef $mMap, $iLimit, $sIndent = $_TAB)
Local $i = 0, $sDump
$sIndent &= $_TAB
For $key In Mapkeys($mMap)
$sDump &= $sIndent & StringFormat('%-16s => ', _
"[" & (IsString($key) ? __DumpStr($key) : $key) & "]")
$sDump &= __VarDump($mMap[$key], $iLimit, $sIndent) & @CRLF
If $iLimit And $i = $iLimit - 1 Then
$sDump &= $sIndent & '... there are ' & UBound($mMap) - $i - 1 & ' more elements in this map' & @CRLF
ExitLoop
EndIf
$i += 1
Next
Return(StringTrimRight($sDump, 2))
EndFunc ;==>__VarDumpMap
Func __DumpStr($vVar)
Local $len = StringLen($vVar)
$vVar = Execute("'" & StringRegExpReplace(StringReplace($vVar, "'", "''"), "([\p{Cc}])", "<0x' & Hex(AscW('$1'), 2) & '>") & "'")
Return "'" & (($len <= 64) ? $vVar : StringMid($vVar, 1, 32) & ' ... ' & StringTrimLeft(StringMid($vVar, $len - 31, 32), 2)) & "'"
EndFunc ;==>__DumpStr
Func _VarEqual(ByRef $vVar1, ByRef $vVar2, $iMethod = 1)
If $iMethod = Default Then $iMethod = 1
Local $dim = UBound($vVar1, $UBOUND_DIMENSIONS)
If $dim <> UBound($vVar2, $UBOUND_DIMENSIONS) Then Return SetError(1, 0, '')
Local $err = 0
If $dim = 0 Then
If BitAND($iMethod, 1) And $vVar1 <> $vVar2 Then $err = 4
If BitAND($iMethod, 2) And Not ($vVar1 == $vVar2) Then $err += 8
If BitAND($iMethod, 4) And VarGetType($vVar1) <> VarGetType($vVar2) Then $err += 16
If BitAND($iMethod, 8) And _VarDump($vVar1) <> _VarDump($vVar2) Then $err += 32
If $err Then Return SetError($err, 0, '')
EndIf
Local $iElems = 1
For $i = 1 To $dim
If UBound($vVar1, $i) <> UBound($vVar2, $i) Then Return SetError(2, 0, $i)
$iElems *= UBound($vVar1, $i)
Next
Local $idx, $n, $v1, $v2
For $i = 0 To $iElems - 1
$idx = ''
$n = $i
For $j = 1 To $dim
$n = Mod($n, UBound($vVar1, $j))
$idx = '[' & $n & ']' & $idx
$n = Int($i / UBound($vVar1, $j))
Next
$v1 = Execute('$vVar1' & $idx)
$v2 = Execute('$vVar2' & $idx)
If BitAND($iMethod, 1) And $v1 <> $v2 Then $err = 4
If BitAND($iMethod, 2) And Not ($v1 == $v2) Then $err += 8
If BitAND($iMethod, 4) And VarGetType($v1) <> VarGetType($v2) Then $err += 16
If BitAND($iMethod, 8) And _VarDump($v1) <> _VarDump($v2) Then $err += 32
If $err Then Return SetError($err, 0, $idx)
Next
Return SetError(0, 0, '')
EndFunc
;~ Local $tTest = DllStructCreate("byte;byte[3];char;char[3];wchar;wchar[3];short;short[3];ushort;ushort[3];int;int[3];uint;uint[3];int64;int64[3];uint64;uint64[3];float;float[3];double;double[3];handle;handle[3];boolean;bool;hwnd;handle;int_ptr;long_ptr;lresult;lparam;uint_ptr;ulong_ptr;dword_ptr;wparam")
;~ DllStructSetData($tTest, 2, '€')
;~ DllStructSetData($tTest, 6, '€')
;~ _ConsoleWrite('Test structure types' & @LF & _VarDump($tTest) & @LF & @LF)
;~ Local $struct = DllStructCreate("char[3];handle[3];uint[35];byte[128];wchar[190000]; double[3];int64[3];char[3];float;double;byte;byte;short;ushort;int;uint;char")
;~ DllStructSetData($struct, 1, 'sos')
;~ DllStructSetData($struct, 2, Ptr(123456789))
;~ DllStructSetData($struct, 3, 8, 1)
;~ DllStructSetData($struct, 3, 0x87654321, 2)
;~ DllStructSetData($struct, 3, 256, 5)
;~ DllStructSetData($struct, 4, Binary('sos'))
;~ DllStructSetData($struct, 5, 'gno' & @CRLF & 'j''i' & @TAB & 'o')
;~ DllStructSetData($struct, 6, 3.1415926, 2)
;~ DllStructSetData($struct, 7, 17, 1)
;~ DllStructSetData($struct, 7, -1, 2)
;~ DllStructSetData($struct, 8, 'end')
;~ DllStructSetData($struct, 9, 2.7182818284590452353602874713527)
;~ DllStructSetData($struct, 10, 2.7182818284590452353602874713527)
;~ DllStructSetData($struct, 11, 107)
;~ DllStructSetData($struct, 12, -108)
;~ DllStructSetData($struct, 13, 109)
;~ DllStructSetData($struct, 14, 110)
;~ DllStructSetData($struct, 15, 111)
;~ DllStructSetData($struct, 16, 112)
;~ Local $f = _VarDump
;~ Local $c[2][0]
;~ Local $e = [[Null, Default], [__DumpStr, MsgBox]]
;~ Local Enum $p = 33333333333333
;~ Opt("WinTitleMatchMode", 2)
;~ Local $a[3][4] = [ _
;~ [$c, $e, ObjCreate("shell.application"), WinGetHandle("Dump.au3")], _
;~ ['zzz', 1/3, True, 0x123456], _
;~ [$struct, 93, Null, $p] _
;~ ]
;~ _ConsoleWrite('Test example of moderate complexity' & @LF & $f($a) & @LF)
;~ Func _ConsoleWrite($s)
;~ ConsoleWrite(BinaryToString(StringToBinary($s, 4), 1))
;~ EndFunc
; _VarEqual() test
;~ Local $a = [['', 0x123456], [1, "A", -2.0]], $b = [[0, Ptr(0x123456)], ["1", "a", -2]]
;~ Local $ret
;~ $ret = _VarEqual($a, $b)
;~ ConsoleWrite("Method 1 : " & @error & ', ' & @extended & ', ' & $ret & @LF)
;~ $ret = _VarEqual($a, $b, 2)
;~ ConsoleWrite("Method 2 : " & @error & ', ' & @extended & ', ' & $ret & @LF)
;~ $ret = _VarEqual($a, $b, 4)
;~ ConsoleWrite("Method 4 : " & @error & ', ' & @extended & ', ' & $ret & @LF)
;~ $ret = _VarEqual($a, $b, 8)
;~ ConsoleWrite("Method 8 : " & @error & ', ' & @extended & ', ' & $ret & @LF)
;~ $ret = _VarEqual($a, $b, 15)
;~ ConsoleWrite("Method 15 : " & @error & ', ' & @extended & ', ' & $ret & @LF)