Jump to content
Sign in to follow this  
therks

A function to determine variable type

Recommended Posts

therks

Edit: (2016-08-03) In case anyone somehow ends up here in the future, you don't need to use user functions to get variable types, AutoIt has VarGetType() for that. However if you are looking for a function to show all variable details, you can use the following.

#include-once

; #INDEX# =======================================================================================================================
; Title .........: Variable
; AutoIt Version : 3.2.13.5+
; Language ......: English
; Description ...: Functions for dumping variable information.
; Author(s) .....: Rob Saunders (rksaunders (at) gmail (dot) com)
; ===============================================================================================================================

; #CURRENT# =====================================================================================================================
; _VarDump
; _ExprDump
; ===============================================================================================================================

; #INTERNAL_USE_ONLY#============================================================================================================
; _VarDumpArray
; _VarDumpStruct
; ===============================================================================================================================

; #FUNCTION# ====================================================================================================================
; Name...........: _VarDump
; Description ...: This function returns information about a variable. Does not reset @error or @extended.
; Syntax.........: _VarDump(ByRef Const $vVar, $vDumpType = Default)
; Parameters ....: $vVar         - The variable to analyze.
;                  $vDumpType    - How to display the information. See Notes for keywords.
; Return values .: String: Information about the variable. This is returned regardless of the $vDumpType parameter.
; Author ........: Rob Saunders (rksaunders (at) gmail (dot) com)
; Remarks .......: $vVar is passed by reference. If you want to pass an expression use the wrapper function provided: _ExprDump()
;                  Use one of the following keywords for the $vDumpType parameter:
;                      1, ConsoleWrite, Console, CW    = ConsoleWrite()
;                      2, MsgBox, Msg, Box, MB         = MsgBox()
;                      3, ToolTip, Tip, TT             = ToolTip()
;                      4, Clipboard, Clip, CB          = ClipPut()
;                      5, GUI, Window, Text            = Display in an edit control in a GUI window created on the fly
;                  You can add an asterisk "*" to the keyword to also return @ScriptLineNumber, @error, and @extended values. ie: "cw*"
; ===============================================================================================================================
Func _VarDump(ByRef Const $vVar, $vDumpType = '', $sIndent = '', $iLineNum = @ScriptLineNumber, $iError = @error, $iExtended = @extended)
    Local $sVarDump, $sVarInfo
    $vDumpType = StringReplace($vDumpType, '*', '')
    If @extended Then
        $sVarInfo = '*** Line: ' & $iLineNum & ', @error: ' & $iError & ', @extended: ' & $iExtended
    EndIf
    Local $sVarType = VarGetType($vVar)
    Switch $sVarType
        Case 'Array'
            $sVarDump &= 'Array(' & @CRLF & _VarDumpArray($vVar, $sIndent & @TAB) & @CRLF & $sIndent & ')'
        Case 'DllStruct'
            $sVarDump &= 'DllStruct(' & @CRLF & _VarDumpStruct($vVar, $sIndent & @TAB) & @CRLF & $sIndent & ')'
        Case 'Binary'
            $sVarDump &= 'Binary(' & BinaryLen($vVar) & ') ' & $vVar
        Case 'Object'
            $sVarDump &= 'Object(' & ObjName($vVar) & ')'
        Case 'String'
            $sVarDump &= 'String(' & StringLen($vVar) & ') ' & $vVar
        Case 'Ptr'
            If IsHWnd($vVar) Then
                $sVarDump &= 'HWnd(' & $vVar & ')'
            Else
                $sVarDump &= 'Ptr(' & $vVar & ')'
            EndIf
        Case Else
            $sVarDump &= $sVarType & '(' & $vVar & ')'
    EndSwitch

    If $sVarInfo And StringRegExp($sVarDump, '[\r\n]') Then
        $sVarDump = $sVarInfo & @CRLF & $sVarDump
    ElseIf $sVarInfo Then
        $sVarDump = $sVarDump & ' ' & $sVarInfo
    EndIf

    Switch $vDumpType
        Case 1, 'ConsoleWrite', 'Console', 'CW'
            ConsoleWrite($sVarDump & @CRLF)
        Case 2, 'MsgBox', 'Msg', 'Box', 'MB'
            MsgBox(0x2040, 'VarDump', $sVarDump)
        Case 3, 'ToolTip', 'Tip', 'TT'
            ToolTip($sVarDump)
        Case 4, 'Clipboard', 'Clip', 'CB'
            ClipPut($sVarDump)
        Case 5, 'GUI', 'Window', 'Text'
            Local $iGUIOnEventMode = Opt('GUIOnEventMode', 0)
            Local $guiVarDump = GUICreate('VarDump', 300, 200, Default, Default, 0xCF0000) ; $WS_OVERLAPPEDWINDOW
            GUICtrlCreateEdit($sVarDump, 0, 0, 300, 200)
                GUICtrlSetResizing(-1, 102) ; $GUI_DOCKBORDERS
            GUISetState(@SW_SHOW, $guiVarDump)
            Do
            Until GUIGetMsg() = -3 ; $GUI_EVENT_CLOSE
            GUIDelete($guiVarDump)
            Opt('GUIOnEventMode', $iGUIOnEventMode)
    EndSwitch

    Return SetError($iError, $iExtended, StringReplace($sVarDump, Chr(0), ' '))
EndFunc

; #FUNCTION# ====================================================================================================================
; Name...........: _ExprDump
; Description ...: This function returns information about an expression/variable. Does not reset @error or @extended.
; Syntax.........: _ExprDump(ByRef $vVar, $vDumpType = Default)
; Parameters ....: $vVar         - The variable/expression to analyze.
;                  $vDumpType    - How to display the information. See _VarDump remarks for keywords.
; Return values .: String: Information about the expression/variable. This is returned regardless of the $vDumpType parameter.
; Author ........: Rob Saunders (rksaunders (at) gmail (dot) com)
; Remarks .......: If you want to analyze an expression instead of a variable use this function. Otherwise use _VarDump().
; ===============================================================================================================================
Func _ExprDump($vVar, $vDumpType = Default, $iLineNum = @ScriptLineNumber, $iError = @error, $iExtended = @extended)
    Local $vReturn = _VarDump($vVar, $vDumpType, '', $iLineNum, $iError, $iExtended)
    Return SetError(@error, @extended, $vReturn)
EndFunc

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _VarDumpArray
; Description ...: Details an array variable.
; Syntax.........: _VarDumpArray(ByRef Const $aArray)
; Parameters ....: $aArray - array to analyze.
; Return values .: String: Structured output of array contents.
; Author ........: Rob Saunders (rksaunders (at) gmail (dot) com)
; ===============================================================================================================================
Func _VarDumpArray(ByRef Const $aArray, $sIndent = '')
    If Not IsArray($aArray) Then
        ; This should only happen if end user calls function directly on non-array
        Return $sIndent & '!! Variable is not array'
    EndIf

    Local $iDimensions = UBound($aArray, 0) ; How many dimensions in array
    If $iDimensions < 1 Then
        ; This should be impossible, but error check for safety
        Return $sIndent & '!! Array has 0 dimensions?'
    EndIf

    Local $aIndexes[$iDimensions] ; Tracker for reading indexes
    Local $aUBounds[$iDimensions] ; List of dimension sizes
    For $i = 0 To $iDimensions - 1
        $aIndexes[$i] = 0
        $aUBounds[$i] = UBound($aArray, $i + 1) ; Store each dimension size
        If $aUBounds[$i] < 1 Then ; Again, should be impossible
            Return $sIndent & '!! Array dimension [' & $i + 1 & '] size is ' & $aUBounds[$i]
        EndIf
    Next

    Local $sArrayIndex ; Indexing string for individual item reading (ie: "[1][2][3]")
    Local $sArrayRead ; Value of array item
    Local $bDone ; Indicates if overall array has finished parsing
    Local $sDump ; Output string
    While 1
        $bDone = True ; Default to true, flag false if dimension read is not done

        ; Reset and build indexing string
        $sArrayIndex = ''
        For $i = 0 To $iDimensions - 1
            $sArrayIndex &= '[' & $aIndexes[$i] & ']'
            If $aIndexes[$i] < $aUBounds[$i] - 1 Then $bDone = False ; Indexing has not reached end of dimension: NOT done
        Next

        $sArrayRead = Execute('$aArray' & $sArrayIndex) ; Read the darn value already!
        If @error Then ; Item read failed, cancel the whole listing
            $sDump &= $sIndent & $sArrayIndex & ' !! Error reading index'
            ExitLoop
        Else
            ; Add the index and value to the output string
            $sDump &= $sIndent & $sArrayIndex & ' => ' & _VarDump($sArrayRead, '', $sIndent)

            If $bDone Then
                Return $sDump
            Else
                ; If not done, line break and loop again
                $sDump &= @CRLF
            EndIf
        EndIf

        ; Ok, I didn't comment this before and it took me forever to figure out what was going on so this is going to be verbose.
        ; The reason this FOR loop goes backwards is because it's stepping through the last dimension first and working it's way back.
        ; Just like when you increase a number, you increment the right-most digit first, ie: the "one's place".
        ; So for example, if we have an array of [X][X][X] - it starts with the third dimension [ ][ ][X] and steps through it one at a time,
        ; like this: [0][0][0], [0][0][1], [0][0][2], etc. If the index hasn't hit the dimension's ubound then the FOR loop exits, so all that
        ; gets incremented is that one dimension index. However, if it has met or exceeded that dimension's ubound, then it resets it to 0 and
        ; the FOR loop gets to continue to the next dimension up (ie: [ ][X][ ]), and now we get [0][1][0], [0][1][1], [0][1][2], etc.
        For $i = $iDimensions - 1 To 0 Step -1
            $aIndexes[$i] += 1
            If $aIndexes[$i] >= $aUBounds[$i] Then
                $aIndexes[$i] = 0
                If $i = $iDimensions - 1 Then $sDump &= @CRLF
                ; The above line puts an extra line break between groups of the last dimension. ie:
                ; [0][0][0] => String(0)
                ; [0][0][1] => String(0)
                ; [0][0][2] => String(0)
                ;
                ; [0][1][0] => String(0)
                ; [0][1][1] => String(0)
                ; [0][1][2] => String(0)
            Else
                ExitLoop
            EndIf
        Next
    WEnd
    Return $sDump
EndFunc

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _VarDumpStruct
; Description ...: Details a struct variable.
; Syntax.........: VarDumpStruct(ByRef $tStruct)
; Parameters ....: $tStruct - struct to analyze.
; Return values .: String: Structured output of struct details/contents.
; Author ........: Rob Saunders (rksaunders (at) gmail (dot) com)
; ===============================================================================================================================
Func _VarDumpStruct(ByRef Const $tStruct, $sIndent = '')
    Local $iElement = 1, $vRead, $vTest
    ; Do the initial $sDump contents - Standard fare for any struct
    Local $sDump = _
        $sIndent & '[Size] => ' & DllStructGetSize($tStruct) & @CRLF & _
        $sIndent & '[Ptr] => ' & DllStructGetPtr($tStruct)
    While 1
        $vRead = DllStructGetData($tStruct, $iElement)
        If @error = 2 Then ExitLoop ; If we've overstepped $iElement we're done

        $vTest = VarGetType($vRead)
        If $vTest = 'String' Or $vTest = 'Binary' Then
            ; Test the vartype for String or Binary, in which case we dump now because we already have the full contents
            $sDump &= @CRLF & $sIndent & '[' & $iElement & '] => ' & _VarDump($vRead, '', $sIndent)
        Else
            ; Here we'll test to see if the element is an array by looking for an index of 2.
            DllStructGetData($tStruct, $iElement, 2)
            If @error Then
                ; @error means no index, which means no array, which means we can just dump the stored $vRead from above
                $sDump &= @CRLF & $sIndent & '[' & $iElement & '] => ' & _VarDump($vRead, '', $sIndent)
            Else
                ; If we get no @error then that means that index 2 was valid, so we'll just start from 1 and work our way up til we @error again
                Local $sSubDump, $iIndex = 1, $iCount = 0, $iNonEmpties = 0
                While 1
                    $vRead = DllStructGetData($tStruct, $iElement, $iIndex)
                    If @error Then ExitLoop ; And that's the limit of this array, so we're done.
                    If $vRead Then
                        ; We're skipping empty indices just to cut down on some of the clutter from large structs
                        $sSubDump &= @CRLF & @TAB & $sIndent & '[' & $iIndex & '] => ' & _VarDump($vRead)
                        $iNonEmpties += 1
                    EndIf
                    $iIndex += 1
                WEnd
                $iIndex -= 1
                $sDump &= @CRLF & $sIndent & '[' & $iElement & '] => Array('
                If $iNonEmpties < $iIndex Then
                    $sDump &= @CRLF & $sIndent & @TAB & '> Skipping empty indices (' & ($iIndex-$iNonEmpties) & '/' & $iIndex & ')'
                EndIf
                $sDump &= $sSubDump & @CRLF & $sIndent & ')'
            EndIf
        EndIf
        $iElement += 1
    WEnd
    Return $sDump
EndFunc

 

 

This topic started in Feature Requests as I didn't think a UDF would be possible.

But if you skip along you'll see that one has been created. I'm still working on it.

Original post follows...

---------------------------------------

I think for the purposes of debugging it would be really handy if AutoIt had a function that simply gives you information on a variable. I use this function in PHP (called var_dump) all the time. Even if we didn't have it output the actual data within the variable, just giving us the type would be nice.

Edited by therks
Time travel

Share this post


Link to post
Share on other sites
Siao

It woudn't be too hard to write such function yourself, using IsArray/IsObject/IsBinary/IsBool/etc...


"be smart, drink your wine"

Share this post


Link to post
Share on other sites
therks

Yeah it's true, I won't deny it. I just thought it might be a useful built-in function.

Func var_dump(ByRef $vVar)
    Select
        Case IsArray($vVar)
            Return 'Array'
        Case IsBinary($vVar)
            Return 'Binary'
        Case IsBool($vVar)
            Return 'Boolean'
        Case IsDllStruct($vVar)
            Return 'Struct'
        Case IsFloat($vVar)
            Return 'Float'
        Case IsHWnd($vVar)
            Return 'HWnd'
        Case IsInt($vVar)
            Return 'Integer'
        Case IsKeyword($vVar)
            Return 'Keyword'
        Case IsObj($vVar)
            Return 'Object'
        Case IsString($vVar)
            Return 'String'
        Case Else
            Return 'Unknown'
    EndSelect
EndFunc

Did I miss anything? (I left out IsNumber for obvious reasons :))

Share this post


Link to post
Share on other sites
Siao

Did I miss anything?

I guess no. Although personally I wouldn't like "" being reported as string, even if Autoit recognizes it as such. And you could also recurse through a recognized array, to be it more like that PHP function, something like this:

Dim $a[4] = [1, Binary("0x01"), "h"]
Dim $b[3] = [Default, WinGetHandle("Program Manager"), $a]
Dim $c[3] = [-5.5, $b, True]
$x = var_dump($c)
ConsoleWrite($x & @CRLF)

Func var_dump($vVar)
    Local $sRet = "", $sTmp, $i
    Select
        Case IsArray($vVar)
            $sRet = "Array[" & UBound($vVar) & "]:"
            For $i = 0 To UBound($vVar)-1
                $sTmp = var_dump($vVar[$i])
                If StringInStr($sTmp, "Array") Then $sTmp = StringReplace($sTmp, @CRLF, @CRLF&@TAB)
                $sRet &= @CRLF & @TAB & "[" & $i & "]" & $sTmp
            Next
        Case IsString($vVar) AND $vVar <> ""
            $sRet = "String"
        Case IsFloat($vVar) OR IsInt($vVar)
            $sRet = "Number"
        Case IsBinary($vVar)
            $sRet = "Binary"
        Case IsBool($vVar)
            $sRet = "Boolean"
        Case IsObj($vVar)
            $sRet = "Object"
        Case IsDllStruct($vVar)
            $sRet = "DllStruct"
        Case IsHWnd($vVar)
            $sRet = "HWnd"
        Case IsKeyword($vVar)
            $sRet = "Keyword"
        Case Else
            $sRet = "Empty/Unknown"
    EndSelect
    Return $sRet
EndFunc

Edit: fixed StringReplace tabbing.

Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
Share on other sites
therks

Yeah I thought about that, but since we can't have real dynamic functions for cycling through arrays I just dropped the idea.

Share this post


Link to post
Share on other sites
martin

Yeah I thought about that, but since we can't have real dynamic functions for cycling through arrays I just dropped the idea.

What's a 'real dynamic function'?

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
therks

Well, I mean like, we can't have one function you can write that you can just toss any array at and have it output the results.

For example, if you throw a 2d array at his function it will choke. So you could rewrite it for 2d, but then if you throw 3d at it, that would choke, and so on.

PHP's arrays work in a totally different way, they aren't really 2 dimensional in the way AutoIt's are, instead you have arrays whose items are arrays, so you could have this:

$a = array();
$a[0] = 'hello';
$a[1] = 'world';
$a[2] = array();
$a[2][0] = 'sub hello';
$a[2][1] = 'sub world';

And if you var_dump that, you get:

array(3) {
  [0]=>
  string(5) "hello"
  [1]=>
  string(5) "world"
  [2]=>
  array(2) {
    [0]=>
    string(9) "sub hello"
    [1]=>
    string(9) "sub world"
  }
}

And writing your own function to loop through that array would be as simple as (pseudo-code):

Func PrintVariable($variable)
  If IsArray($variable) Then
    For $i = 0 to UBound($variable) - 1
      If IsArray($variable[$i]) Then
        PrintVariable($variable[$i])
      Else
        ConsoleWrite($variable[$i] & @CRLF)
      EndIf
    Next
  Else
    ConsoleWrite($variable & @CRLF)
  EndIf
EndFunc

But like I said, AutoIt's arrays are totally different, so you can't do anything like that to loop through it's multi-dim arrays.

Share this post


Link to post
Share on other sites
flyingboz

But like I said, AutoIt's arrays are totally different, so you can't do anything like that to loop through it's multi-dim arrays.

Didn't anybody tell you never to say never???

Check out the options involved with Ubound(). You can get the number of dimensions, and then iterate to get the number of elements therein.

The exercise of implementation is left to the student :)


Reading the help file before you post... Not only will it make you look smarter, it will make you smarter.

Share this post


Link to post
Share on other sites
therks

Okay... so when did Execute change to allow us to read arrays? I could swear that was a problem before...

Anyway, I just realized that code like the following works just fine:

Dim $array1[2][2] = [ [ 'Cloud', 'Squall' ], [ 'Aerith', 'Rinoa' ] ]
ConsoleWrite(Execute("$array1[1][1]"))

So all my insane ramblings about it being impossible are just that.. insane ramblings. Don't listen to me anymore. :)

Sorry flyingboz.

No no, it still can't be done. Because you'll always have to rewrite the array reference itself if the dimensions change.

Let's take this example...

Dim $array1[2][2] = [ [ 'Cloud', 'Squall' ], [ 'Aerith', 'Rinoa' ] ]
Dim $array2[2][2][2] = [ [ [ 'Cloud', 'Squall' ], [ 'Aerith', 'Rinoa' ] ], [ [ 'Sephiroth', 'Seifer' ], [ 'JENOVA', 'Edea' ] ] ]

ArrayDump($array1)
ArrayDump($array2)

Func ArrayDump(ByRef $array)
    Local $subs = UBound($array, 0)
    Local $tabs
    If $subs = 1 Then
        ConsoleWrite('array:' & @CRLF)
        $tabs = @TAB
        For $a = 0 to UBound($array, 1) - 1
            ConsoleWrite($tabs & $array[$a] & @CRLF)
        Next
    ElseIf $subs = 2 Then
        ConsoleWrite('array:' & @CRLF)
        For $a = 0 to UBound($array, 1) - 1
            $tabs = @TAB
            ConsoleWrite($tabs & $a & ':' & @CRLF)
            For $b = 0 to UBound($array, 2) - 1
                $tabs = @TAB & @TAB
                ConsoleWrite($tabs & $array[$a][$b] & @CRLF)
            Next
        Next
    ElseIf $subs = 3 Then; A new section will have to be added here for every amount of subscript...
        ConsoleWrite('array:' & @CRLF)
        For $a = 0 to UBound($array, 1) - 1
            $tabs = @TAB
            ConsoleWrite($tabs & $a & ':' & @CRLF)
            For $b = 0 to UBound($array, 2) - 1
                $tabs = @TAB & @TAB
                ConsoleWrite($tabs & $b & ':' & @CRLF)
                For $c = 0 to UBound($array, 3) - 1
                    $tabs = @TAB & @TAB & @TAB
                    ConsoleWrite($tabs & $array[$a][$b][$c] & @CRLF)
                Next
            Next
        Next
    EndIf
EndFunc

That piece of code works fine, but if I decide I need to dump $array[2][2][2][2] in there, it's going to choke (or rather, the way I have it written it just won't do anything).

Now, I'm sure I could probably avoid repetition in that code by doing recursion through another function, thereby making the for-loops themselves dynamic, but no matter which way you hack it, it all boils down to $array[$a][$b][$c]. Because that's the line that we can't make truly dynamic. If you have a 2 subscript array or a 200 subscript array (though I doubt that's even possible) that line has to be rewritten for every eventuality.

Edited by Saunders

Share this post


Link to post
Share on other sites
flyingboz

No problem :)

I have been bitten by the language moving from under my feet too. What a great thing to have a problem with, that the language is even more capable than you thought!

my array_walk udf by default displays the value for every element in the array. However, if an optional second parameter is specified, I return the specified element of the array only. This second parameter must be a vector (1d array) or a comma delimited string (that I turn into a vector), with the zeroth element matching the number of dimensions of the array.

If you're interested, let me know and I'll try to track it down and post it or a snippet thereof.

The big extension that my array_walk udf still needs is if the elements in the arrays are themselves arrays, I haven't decided how to handle that case. PHP, IIRC just prints [array] in the location....


Reading the help file before you post... Not only will it make you look smarter, it will make you smarter.

Share this post


Link to post
Share on other sites
therks

Yeah actually if you can find it I would like to see that. An array walk function would be very cool.

Share this post


Link to post
Share on other sites
therks

Nevermind, I figured it out myself. :)

I wrote up this function for an array walk:

Func _ArrayWalk(ByRef $aArray, $sFunction)
    Local $sArrayFetch, $sArrayRead, $bDone
    Local $iSubscripts = UBound($aArray, 0)
    Local $aUBounds[$iSubscripts]
    Local $aCounts[$iSubscripts]
    $iSubscripts -= 1
    For $i = 0 To $iSubscripts
        $aUBounds[$i] = UBound($aArray, $i + 1) - 1
        $aCounts[$i] = 0
    Next
    While 1
        $bDone = True
        $sArrayFetch = ''
        For $i = 0 To $iSubscripts
            $sArrayFetch &= '[' & $aCounts[$i] & ']'
            If $aCounts[$i] < $aUBounds[$i] Then $bDone = False
        Next
        
        $sArrayRead = Execute('$aArray' & $sArrayFetch)
        If @error Then
            ExitLoop
        Else
            Call($sFunction, $sArrayFetch, $sArrayRead)
            If $bDone Then ExitLoop
        EndIf
        
        For $i = $iSubscripts To 0 Step -1
            $aCounts[$i] += 1
            If $aCounts[$i] > $aUBounds[$i] Then
                $aCounts[$i] = 0
            Else
                ExitLoop
            EndIf
        Next
    WEnd
EndFunc

And it works like so:

Dim $array1[2][2] = [ [ 'Cloud', 'Squall' ], [ 'Aerith', 'Rinoa' ] ]
Dim $array2[2][2][2] = [ [ [ 'Cloud', 'Squall' ], [ 'Aerith', 'Rinoa' ] ], [ [ 'Sephiroth', 'Seifer' ], [ 'JENOVA', 'Edea' ] ] ]

ConsoleWrite('2 subscript array:' & @CRLF)
_ArrayWalk($array1, '_DumpToConsole')
ConsoleWrite(@CRLF & '3 subscript array:' & @CRLF)
_ArrayWalk($array2, '_DumpToConsole')

Func _DumpToConsole($sKey, $vValue)
    ConsoleWrite($sKey & ' => ' & $vValue & @CRLF)
EndFunc

And the output of that, looks like this:

2 subscript array:
[0][0] => Cloud
[0][1] => Squall
[1][0] => Aerith
[1][1] => Rinoa

3 subscript array:
[0][0][0] => Cloud
[0][0][1] => Squall
[0][1][0] => Aerith
[0][1][1] => Rinoa
[1][0][0] => Sephiroth
[1][0][1] => Seifer
[1][1][0] => JENOVA
[1][1][1] => Edea

Share this post


Link to post
Share on other sites
lordofthestrings

pretty nice code you demonstrate there... works like a charm..


Share this post


Link to post
Share on other sites
therks

Oh, I meant to post this too, but forgot.

The following code is essentially exactly what I was asking for when I started this thread.

Func _VarDump(ByRef $vVar, $sIndent = '')
    Select
        Case IsDllStruct($vVar)
            Return 'Struct(' & DllStructGetSize($vVar) & ')'
        Case IsArray($vVar)
            Return 'Array' & @CRLF & _VarDumpArray($vVar, $sIndent)
        Case IsBinary($vVar)
            Return 'Binary(' & BinaryLen($vVar) & ')'
        Case IsBool($vVar)
            Return 'Boolean(' & $vVar & ')'
        Case IsFloat($vVar)
            Return 'Float(' & $vVar & ')'
        Case IsHWnd($vVar)
            Return 'HWnd(' & $vVar & ')'
        Case IsInt($vVar)
            Return 'Integer(' & $vVar & ')'
        Case IsKeyword($vVar)
            Return 'Keyword(' & $vVar & ')'
        Case IsObj($vVar)
            Return 'Object(' & ObjName($vVar) & ')'
        Case IsString($vVar)
            Return 'String(' & StringLen($vVar) & ') ' & $vVar
        Case Else
            Return 'Unknown(' & $vVar & ')'
    EndSelect
EndFunc

Func _VarDumpArray(ByRef $aArray, $sIndent = '')
    Local $sDump
    Local $sArrayFetch, $sArrayRead, $bDone
    Local $iSubscripts = UBound($aArray, 0)
    Local $aUBounds[$iSubscripts]
    Local $aCounts[$iSubscripts]
    $iSubscripts -= 1
    For $i = 0 To $iSubscripts
        $aUBounds[$i] = UBound($aArray, $i + 1) - 1
        $aCounts[$i] = 0
    Next
    $sIndent &= @TAB
    While 1
        $bDone = True
        $sArrayFetch = ''
        For $i = 0 To $iSubscripts
            $sArrayFetch &= '[' & $aCounts[$i] & ']'
            If $aCounts[$i] < $aUBounds[$i] Then $bDone = False
        Next
        
        $sArrayRead = Execute('$aArray' & $sArrayFetch)
        If @error Then
            ExitLoop
        Else
            $sDump &= $sIndent & $sArrayFetch & ' => ' & _VarDump($sArrayRead, $sIndent)
            If Not $bDone Then
                $sDump &= @CRLF
            Else
                Return $sDump
            EndIf
        EndIf
        
        For $i = $iSubscripts To 0 Step -1
            $aCounts[$i] += 1
            If $aCounts[$i] > $aUBounds[$i] Then
                $aCounts[$i] = 0
            Else
                ExitLoop
            EndIf
        Next
    WEnd
EndFunc

And some example code:

Local $aProcList = ProcessList('svchost.exe')
Local $aWinList = WinList('[CLASS:CabinetWClass]')
Local $aChild[6] = [ True, 19, WinGetPos(''), 'Uh oh', Default, $aWinList ]
Local $aParent[5] = [ Binary('0x200a0d'), $aChild, 5.5, DllStructCreate('int;char[128]'), $aProcList ]

ConsoleWrite(_VarDump($aParent))

Share this post


Link to post
Share on other sites
flyingboz

Nicely done, Saunders --

I got hung up on some other stuff and forgot about the post I promised you. Sry.


Reading the help file before you post... Not only will it make you look smarter, it will make you smarter.

Share this post


Link to post
Share on other sites
Uten

Really nice piece of mind bending work @Saunders.

May I suggest you do the required work (write a help file section, comment some code, create some helpfile samples) to get it accepted as an official UDF? You are so close anyway..:)

Share this post


Link to post
Share on other sites
Richard Robertson

It's pretty, but what kind of variable would be unknown?

Share this post


Link to post
Share on other sites
Uten

It's pretty, but what kind of variable would be unknown?

At least you will get a notice if it is not handled..:)

Share this post


Link to post
Share on other sites
therks

Yeah that's pretty much it. I wanted to cover all my bases, so this way at least it will tell you, "We don't know wtf it is..."

@Uten, Re: UDF - I might just do that. I'm lazy though, so I might not. But if I remember one day when I'm not doing anything else. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×