#AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_Compile_Both=n ;~ #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_Run_AU3Check=n #AutoIt3Wrapper_Version=B ; beta 3.3.15.0 or greater is mandatory #include-once #include #include #include Global Const $_TAB = ' ' Global $_DumpStr, $_DumpBin ; 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 dimension, map or DllStruct array element to be displayed in full Func _VarDump(ByRef $vVar, $iLimit = 20, $bFullStr = 0, $bFullBin = 0) If $iLimit < 3 Then $iLimit = 0 $_DumpStr = ($bFullStr ? __DumpFullStr : __DumpStr) $_DumpBin = ($bFullBin ? __DumpFullBin : __DumpBin) $sStr = $vVar Return (__VarDump($sStr, $iLimit)) EndFunc ;==>_VarDump Func __VarDump(ByRef $vVar, $iLimit, $sIndent = '', $sMore = '') Local $ret, $len, $ptr, $tmp Switch VarGetType($vVar) Case "String" $len = StringLen($vVar) If StringRegExp($vVar, '(?x)' & _ '(?(DEFINE) (? (?&ws) (?&value) (?&ws) ) )' & _ '(?(DEFINE) (? (?&ws) (?: (?&object) | (?&array) | (?&string) | (?&number) | true | false | null ) (?&ws) ) )' & _ '(?(DEFINE) (? \{ (?: (?&ws) | (?&member) (?: , (?&member) )* ) \} ) )' & _ '(?(DEFINE) (? (?&ws) (?&string) (?&ws) : (?&element) ) )' & _ '(?(DEFINE) (? \[ (?: (?&ws) | (?&value) (?: , (?&value) )* ) \] ) )' & _ '(?(DEFINE) (? " (?: \\ (?: ["\\/bnrt] | u [[:xdigit:]]{4} ) | [^[:cntrl:]\\"] )* " ) )' & _ '(?(DEFINE) (? [-+]? \d+ (?: \.\d+ )? (?: [Ee] [-+]? \d+ )? ) )' & _ '(?(DEFINE) (? [\x09\x0A\x0D\x20]* ) )' & _ '\A (?&element) \z') Then Return __DumpJSON($vVar, $sIndent) Else Return 'String (' & $len & ") " & $_DumpStr($vVar) EndIf Case "Double" Return 'Double ' & $vVar & (IsInt($vVar) ? '.0' : '') Case "Int32", "Int64" Return VarGetType($vVar) & ' ' & $vVar Case "Array" 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 $sMore = _StringRepeat(' ', StringLen($ret) - 1) If $iCells = 0 Then Return $ret & $_TAB & ' (array is empty)' Else Return $ret & @CRLF & __VarDumpArray($vVar, $iLimit, $sIndent, $sMore) EndIf Case "Binary" $len = BinaryLen($vVar) $ret = 'Binary (' & BinaryLen($vVar) & ') ' Return ($ret & $_DumpBin($vVar)) Case "Bool" Return 'Boolean ' & $vVar Case "Keyword" Return ('Keyword ' & ($vVar = Null ? 'Null' : ($vVar = Default ? 'Default' : 'Other keyword'))) Case "Ptr" Return (IsHWnd($vVar) ? 'HWnd ' : 'Pointer ' & $vVar) Case "Object" $tmp = 'Object' & @LF & $sMore & $sIndent & ' Name: ' & ObjName($vVar, $OBJ_NAME) $ret = ObjName($vVar, $OBJ_STRING) If Not @error Then $tmp &= @LF & $sMore & $sIndent & ' Description: ' & $ret $ret = ObjName($vVar, $OBJ_PROGID) If Not @error Then $tmp &= @LF & $sMore & $sIndent & ' ProgID: ' & $ret $ret = ObjName($vVar, $OBJ_FILE) If Not @error Then $tmp &= @LF & $sMore & $sIndent & ' Associated file: ' & $ret $ret = ObjName($vVar, $OBJ_MODULE) If Not @error Then $tmp &= @LF & $sMore & $sIndent & ' Owner/marshaller: ' & $ret $ret = ObjName($vVar, $OBJ_CLSID) If Not @error Then $tmp &= @LF & $sMore & $sIndent & ' CLSID: ' & $ret $ret = ObjName($vVar, $OBJ_IID) If Not @error Then $tmp &= @LF & $sMore & $sIndent & ' InterfaceID: ' & $ret Return $tmp Case "Function", "UserFunction" Return StringFormat('%-13s', VarGetType($vVar)) & FuncName($vVar) Case "DllStruct" $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, $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) & $_DumpBin($data) & @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 "Map" 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 EndSwitch EndFunc ;==>__VarDump Func __VarDumpArray(ByRef $aArray, $iLimit, $sIndent = $_TAB, $sMore = '') 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, $sMore) & @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, $sMore = '') 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, $sMore) & @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 __DumpBin(ByRef $vVar) Local $len = BinaryLen($vVar) Return (($len <= 32) ? $vVar : BinaryMid($vVar, 1, 16) & ' ... ' & StringTrimLeft(BinaryMid($vVar, $len - 15, 16), 2)) EndFunc ;==>__DumpBin Func __DumpFullStr(ByRef $vVar) $vVar = Execute("'" & StringRegExpReplace(StringReplace($vVar, "'", "''"), "([\p{Cc}])", "<0x' & Hex(AscW('$1'), 2) & '>") & "'") Return "'" & $vVar & "'" EndFunc ;==>__DumpFullStr Func __DumpFullBin(ByRef $vVar) Return $vVar EndFunc ;==>__DumpFullBin Func __DumpJSON(ByRef $vVar, $sIndent) Local $jstr = 'JSON_object' $sIndent &= $_TAB Do $vVar = StringRegExpReplace($vVar, '^(\s*\{\s*)', '') $jstr &= @CRLF & $sIndent & StringFormat('%-16s', '"' & __DumpJsonString($vVar) & '"') & ' --> ' & __DumpJsonValue($vVar, $sIndent) Until StringRegExp($vVar, '^\s*\}\s*') $vVar = StringRegExpReplace($vVar, '^(\s*\}\s*)', '') Return $jstr EndFunc ;==>__DumpJSON Func __DumpJsonString(ByRef $sStr) Local $aPair = StringRegExp($sStr, '(?x) \s* " (.*?) (?') $aPair[0] = StringReplace($aPair[0], '\f', '<0x0C>') $aPair[0] = StringReplace($aPair[0], '\n', '<0x0A>') $aPair[0] = StringReplace($aPair[0], '\r', '<0x0D>') $aPair[0] = StringReplace($aPair[0], '\t', '<0x09>') $aPair[0] = StringReplace($aPair[0], '\\', '\') ; must be last replace Return Execute("'" & StringRegExpReplace($aPair[0], '\\u(....)', "' & ChrW('0x' & '$1') & '") & "'") EndFunc ;==>__DumpJsonString Func __DumpJsonValue(ByRef $sStr, $sIndent) Local $jstr, $aPair Select Case StringLeft($sStr, 1) = ':' $sStr = StringRegExpReplace($sStr, ':\s*', '') $jstr &= __DumpJsonValue($sStr, $sIndent) ; & '*a' & @CRLF Case StringLeft($sStr, 1) = '"' $jstr &= "'" & __DumpJsonString($sStr) & "'" Case StringRegExp($sStr, '^[-+]?\d+') $aPair = StringRegExp($sStr, '(?x) ^ ( [-+]? \d+ (?: \.\d+ )? (?: [Ee] [-+]? \d+ )? ) (.*)', 1) $sStr = $aPair[1] $jstr &= Number($aPair[0]) ; & '*c' & @CRLF Case StringLeft($sStr, 1) = 't' $sStr = StringRegExpReplace($sStr, '^\w*\s*', '') $jstr &= 'JSON_true' ; & '*d' & @CRLF Case StringLeft($sStr, 1) = 'f' $sStr = StringRegExpReplace($sStr, '^\w*\s*', '') $jstr &= 'JSON_false' ; & '*e' & @CRLF Case StringLeft($sStr, 1) = 'n' $sStr = StringRegExpReplace($sStr, '^\w*\s*', '') $jstr &= 'JSON_null' ; & '*f' & @CRLF Case StringLeft($sStr, 1) = '[' $jstr &= 'JSON_array' $sIndent &= $_TAB Do $sStr = StringRegExpReplace($sStr, '^[\[,]\s*', '') $jstr &= @CRLF & $sIndent & __DumpJsonValue($sStr, $sIndent) Until StringRegExp($sStr, '^\s*\]\s*') $sStr = StringRegExpReplace($sStr, '^(\s*\]\s*)', '') Case StringLeft($sStr, 1) = '{' $jstr &= __DumpJSON($sStr, $sIndent) EndSelect Return $jstr EndFunc ;==>__DumpJsonValue Func _VarCmp(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 ;==>_VarCmp ; Unicode-aware ConsoleWrite Func _ConsoleWrite($s) ConsoleWrite(BinaryToString(StringToBinary($s, 4), 1)) EndFunc ;==>_ConsoleWrite #cs ; Example use 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) ;~ ; _VarCmp() test Local $a = [['', 0x123456], [1, "A", -2.0]], $b = [[0, Ptr(0x123456)], ["1", "a", -2]] Local $ret = _VarCmp($a, $b) ConsoleWrite("Method 1 : " & @error & ', ' & @extended & ', ' & $ret & @LF) $ret = _VarCmp($a, $b, 2) ConsoleWrite("Method 2 : " & @error & ', ' & @extended & ', ' & $ret & @LF) $ret = _VarCmp($a, $b, 4) ConsoleWrite("Method 4 : " & @error & ', ' & @extended & ', ' & $ret & @LF) $ret = _VarCmp($a, $b, 8) ConsoleWrite("Method 8 : " & @error & ', ' & @extended & ', ' & $ret & @LF) $ret = _VarCmp($a, $b, 15) ConsoleWrite("Method 15 : " & @error & ', ' & @extended & ', ' & $ret & @LF) Local $m[], $n[] $m[25] = ObjCreate("shell.application") $n["grhjiop jpgr 25"] = ObjCreate("shell.application") $m["tghjnio"] = $n ConsoleWrite(_VarDump($m) & @LF) #ce Local $a = '{"name":"value","a\u00B6b\tc":"DEF", "M''c Do xyz":132,"array" : [1,2,3, -4.5,0.123e56, "xx\rx",false,{"empty":""}] , "obj" : { "this" : "\"Forté\""},"this is":true,"or":null }' Local $b[] $b[43] = "hello" $b["next"] = "world" $b["js"] = $a Local $c = [123.456, "abc'def", ChrW, _StringExplode,'{"name1.0":"value1.0", "nested":{"name1.0":"value1.0", "name1.1":"value1.1", "name1.2":"value1.2", "name1.3":["aaa", 111,"555",false,[1,2,3]]}, "end": null}'] $b["nested"] = $c _ConsoleWrite(@LF & 'Dump example of Map including JSON' & @LF & @LF & _VarDump($b) & @LF)