Jump to content

Recommended Posts

Posted

I had a dissatisfaction with IsNumber so this function was born: 

; AutoIt Data Type Checker - Single Main Function + Demo Helper
; Main function contains ALL logic, helper function only for demo/testing
; Parameters:
;   $vInput - Variable/value to check (any type)
;   $bStrictMode - Boolean (optional): True for strict hex checking (even length), False for loose (default: False)
;   $bShowDebug - Boolean (optional): True to show debug info, False to hide (default: False)
; Returns:
;  -1 = Unknown type
;   0 = String types (Empty, Path, URL, Email, Numeric String, Alphabetic String)
;   1 = Number types (Integer, Float, Number, String Integer, String Float, String Number)
;   2 = Binary/Hex types (Binary, Hex String)
;   4 = Boolean types (Boolean, String Boolean)
;   5 = Array, 6 = Map, 7 = Pointer, 8 = DLL Struct, 9 = Window Handle, 10 = Object
Func CheckDataType($vInput, $bStrictMode = False, $bShowDebug = False)
    ; ============================================================================
    ; SHOW DEBUG INFO
    ; ============================================================================
    If $bShowDebug Then
        ConsoleWrite("- [DEBUG] Input: " & VarGetType($vInput) & " '" & String($vInput) & "' | Mode: " & ($bStrictMode ? "Strict" : "Loose") & @CRLF)
    EndIf

    ; ============================================================================
    ; CHECK AUTOIT OBJECT TYPES FIRST (Highest Priority)
    ; ============================================================================
    If IsArray($vInput) Then
        If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: IsArray() = True -> Array (5)" & @CRLF)
        Return 5
    EndIf

    If IsMap($vInput) Then
        If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: IsMap() = True -> Map (6)" & @CRLF)
        Return 6
    EndIf

    If IsPtr($vInput) Then
        If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: IsPtr() = True -> Pointer (7)" & @CRLF)
        Return 7
    EndIf

    If IsDllStruct($vInput) Then
        If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: IsDllStruct() = True -> DLL Struct (8)" & @CRLF)
        Return 8
    EndIf

    If IsHWnd($vInput) Then
        If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: IsHWnd() = True -> Window Handle (9)" & @CRLF)
        Return 9
    EndIf

    If IsObj($vInput) Then
        If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: IsObj() = True -> Object (10)" & @CRLF)
        Return 10
    EndIf

    ; ============================================================================
    ; CHECK BINARY TYPES
    ; ============================================================================
    If IsBinary($vInput) Then
        If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: IsBinary() = True -> Binary/Hex (2)" & @CRLF)
        Return 2
    EndIf

    ; ============================================================================
    ; CHECK BOOLEAN TYPES
    ; ============================================================================
    If IsBool($vInput) Then
        If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: IsBool() = True -> Boolean (4)" & @CRLF)
        Return 4
    EndIf

    ; ============================================================================
    ; CHECK NUMBER TYPES (Built-in IsNumber is most reliable)
    ; ============================================================================
    If IsNumber($vInput) Then
        If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: IsNumber() = True -> Number (1)" & @CRLF)
        Return 1
    EndIf

    ; ============================================================================
    ; STRING ANALYSIS (Most Complex Part)
    ; ============================================================================
    If IsString($vInput) Then
        If $bShowDebug Then ConsoleWrite("- [DEBUG] Processing as string..." & @CRLF)

        ; ------------------------------------------------------------------------
        ; CHECK STRING NUMBERS (Highest Priority for Strings)
        ; ------------------------------------------------------------------------
        ; Check AutoIt built-in string number functions first
        If StringIsInt($vInput) Or StringIsFloat($vInput) Then
            If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: StringIsInt/Float = True -> Number (1)" & @CRLF)
            Return 1
        EndIf

        ; Check simple number conversion
        Local $fNumValue = Number($vInput)
        If (String($fNumValue) = StringStripWS($vInput, 8)) And (StringStripWS($vInput, 8) <> "") Then
            If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: String convertible to number -> Number (1)" & @CRLF)
            Return 1
        EndIf

        ; ------------------------------------------------------------------------
        ; CHECK INTERNATIONAL NUMBER FORMATS (Inline Logic)
        ; ------------------------------------------------------------------------
        ; Remove leading/trailing spaces for international number checking
        Local $sClean = StringStripWS($vInput, 3)
        If $sClean <> "" Then
            ; Check for optional negative sign
            Local $sNumberPart = $sClean
            If StringLeft($sNumberPart, 1) = "-" Then
                $sNumberPart = StringMid($sNumberPart, 2)
            EndIf

            ; US Format: 1,234.56 or 1,234,567.89 (comma thousands, dot decimal)
            Local $sUSPattern = "^[0-9]{1,3}(,[0-9]{3})*(\.[0-9]+)?$"
            If StringRegExp($sNumberPart, $sUSPattern) Then
                If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: US number format -> Number (1)" & @CRLF)
                Return 1
            EndIf

            ; EU Format: 1.234,56 or 1.234.567,89 (dot thousands, comma decimal)
            Local $sEUPattern = "^[0-9]{1,3}(\.[0-9]{3})*(,[0-9]+)?$"
            If StringRegExp($sNumberPart, $sEUPattern) Then
                If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: EU number format -> Number (1)" & @CRLF)
                Return 1
            EndIf

            ; Thousands separator only: 1,234 or 1.234 (no decimal part)
            If StringRegExp($sNumberPart, "^[0-9]{1,3}[,\.][0-9]{3}([,\.][0-9]{3})*$") Then
                If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: Thousands separator format -> Number (1)" & @CRLF)
                Return 1
            EndIf

            ; Simple EU decimal: 1,5 (comma as decimal separator)
            If StringRegExp($sNumberPart, "^[0-9]+,[0-9]+$") Then
                If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: EU decimal format -> Number (1)" & @CRLF)
                Return 1
            EndIf
        EndIf

        ; ------------------------------------------------------------------------
        ; CHECK BOOLEAN-LIKE STRINGS
        ; ------------------------------------------------------------------------
        Local $sLowerInput = StringLower(StringStripWS($vInput, 3))
        If $sLowerInput = "true" Or $sLowerInput = "false" Then
            If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: Boolean-like string -> Boolean (4)" & @CRLF)
            Return 4
        EndIf

        ; ------------------------------------------------------------------------
        ; CHECK HEXADECIMAL STRINGS (Inline Logic)
        ; ------------------------------------------------------------------------
        Local $bIsHex = False

        If $bStrictMode Then
            If $bShowDebug Then ConsoleWrite("- [DEBUG] Using strict hex checking (even length required)..." & @CRLF)

            ; Strict mode: ALL hex must have even length
            ; Check hex with prefix: 0x + even number of hex digits
            Local $sStrictHexWithPrefixPattern = "^0[xX][0-9A-Fa-f]+$"
            If StringRegExp($vInput, $sStrictHexWithPrefixPattern) Then
                ; Check if hex part (after 0x) has even length
                Local $sHexPart = StringMid($vInput, 3) ; Remove "0x" or "0X"
                If Mod(StringLen($sHexPart), 2) = 0 Then
                    If $bShowDebug Then ConsoleWrite("- [DEBUG] Hex with prefix has even length (" & StringLen($sHexPart) & ") -> Valid" & @CRLF)
                    $bIsHex = True
                Else
                    If $bShowDebug Then ConsoleWrite("- [DEBUG] Hex with prefix has odd length (" & StringLen($sHexPart) & ") -> Invalid" & @CRLF)
                EndIf
            EndIf

            ; Check hex without prefix: must be even length and at least 2 characters
            If Not $bIsHex Then
                Local $sStrictHexWithoutPrefixPattern = "^[0-9A-Fa-f]{2,}$"
                If StringRegExp($vInput, $sStrictHexWithoutPrefixPattern) And Mod(StringLen($vInput), 2) = 0 Then
                    If $bShowDebug Then ConsoleWrite("- [DEBUG] Hex without prefix has even length (" & StringLen($vInput) & ") -> Valid" & @CRLF)
                    $bIsHex = True
                EndIf
            EndIf

            ; Debug info for failed strict hex
            If Not $bIsHex And $bShowDebug And StringRegExp($vInput, "^[0-9A-Fa-f]+$") Then
                ConsoleWrite("- [DEBUG] Valid hex characters but odd length (" & StringLen($vInput) & ") -> Invalid in strict mode" & @CRLF)
            EndIf

        Else
            If $bShowDebug Then ConsoleWrite("- [DEBUG] Using loose hex checking (any length allowed)..." & @CRLF)

            ; Loose mode: accept any valid hex format (any length)
            Local $sHexWithPrefixPattern = "^0[xX][0-9A-Fa-f]+$"
            Local $sHexWithoutPrefixPattern = "^[0-9A-Fa-f]+$"

            If StringRegExp($vInput, $sHexWithPrefixPattern) Or StringRegExp($vInput, $sHexWithoutPrefixPattern) Then
                If $bShowDebug Then ConsoleWrite("- [DEBUG] Hex pattern matched (any length) -> Valid" & @CRLF)
                $bIsHex = True
            EndIf
        EndIf

        ; Return hex result if found
        If $bIsHex Then
            If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: Hexadecimal string -> Binary/Hex (2)" & @CRLF)
            Return 2
        EndIf

        ; ------------------------------------------------------------------------
        ; ALL OTHER STRING TYPES RETURN 0 (including special detection for debug)
        ; ------------------------------------------------------------------------
        If $bShowDebug Then
            If (StringStripWS($vInput, 8) == "") Then
                ConsoleWrite("- [DEBUG] Result: Empty string -> String Type (0)" & @CRLF)
            ElseIf StringRegExp($vInput, "^[a-zA-Z]:\\") Then
                ConsoleWrite("- [DEBUG] Result: Windows path detected -> String Type (0)" & @CRLF)
            ElseIf StringRegExp($vInput, "^https?://") Then
                ConsoleWrite("- [DEBUG] Result: URL detected -> String Type (0)" & @CRLF)
            ElseIf StringRegExp($vInput, "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$") Then
                ConsoleWrite("- [DEBUG] Result: Email detected -> String Type (0)" & @CRLF)
            ElseIf StringRegExp($vInput, "^[0-9]+$") Then
                ConsoleWrite("- [DEBUG] Result: All digits string -> String Type (0)" & @CRLF)
            ElseIf StringRegExp($vInput, "^[a-zA-Z]+$") Then
                ConsoleWrite("- [DEBUG] Result: All alphabetic -> String Type (0)" & @CRLF)
            Else
                ConsoleWrite("- [DEBUG] Result: Generic string -> String Type (0)" & @CRLF)
            EndIf
        EndIf
        Return 0
    EndIf

    ; ============================================================================
    ; DEFAULT FOR UNKNOWN TYPES
    ; ============================================================================
    If $bShowDebug Then ConsoleWrite("- [DEBUG] Result: Unknown type (-1)" & @CRLF)
    Return -1
EndFunc   ;==>CheckDataType

; ============================================================================
; HELPER FUNCTION FOR DEMO/TESTING ONLY (Not part of main functionality)
; ============================================================================
; Helper function to convert result code to readable name for demo purposes
Func GetDataTypeName($iCode)
    Switch $iCode
        Case 0
            Return "String Type"
        Case 1
            Return "Number Type"
        Case 2
            Return "Binary/Hex Type"
        Case 4
            Return "Boolean Type"
        Case 5
            Return "Array"
        Case 6
            Return "Map"
        Case 7
            Return "Pointer"
        Case 8
            Return "DLL Struct"
        Case 9
            Return "Window Handle"
        Case 10
            Return "Object"
        Case Else
            Return "Unknown (" & $iCode & ")"
    EndSwitch
EndFunc   ;==>GetDataTypeName

; === TEST EXAMPLES ===
ConsoleWrite("!=== COMPACT TYPE CHECKING RESULTS ===" & @CRLF)

; Test various data types including hex with different lengths
Local $aTestValues[] = [123, 12.34, "123", "12.34", "Hello", "0xFF", "ABCD", "ABC", "A", "true", "false", "", _
        "C:\Windows\System32", "https://www.google.com", "user@example.com", "12345", _
        "1,234", "1.234", "1,234.56", "1.234,56", "1,234,567.89", "1.234.567,89", "12,5", _
        "0xABC", "0xABCD", "F", "FF", "123ABC", "ABCDEF"]

ConsoleWrite("+ Testing without debug (Loose mode):" & @CRLF)
For $i = 0 To UBound($aTestValues) - 1
    Local $result = CheckDataType($aTestValues[$i], False, False)
    ConsoleWrite("- '" & String($aTestValues[$i]) & "' -> " & GetDataTypeName($result) & " (" & $result & ")" & @CRLF)
Next

ConsoleWrite(@CRLF & "!=== DETAILED DEBUG FOR HEX CASES ===" & @CRLF)

; Test with debug for hex cases in both modes
Local $debugTests[] = ["ABC", "ABCD", "0xABC", "0xABCD", "F", "FF"]
For $i = 0 To UBound($debugTests) - 1
    ConsoleWrite(@CRLF & "+ Debug test for '" & $debugTests[$i] & "' (Loose mode):" & @CRLF)
    Local $result = CheckDataType($debugTests[$i], False, True)
    ConsoleWrite("+ Debug test for '" & $debugTests[$i] & "' (Strict mode):" & @CRLF)
    Local $result2 = CheckDataType($debugTests[$i], True, True)
Next

; === USAGE EXAMPLES ===
ConsoleWrite(@CRLF & "!=== USAGE EXAMPLES ===" & @CRLF)

; Test with actual AutoIt data types
Local $myArray[3] = [1, 2, 3]
Local $myMap[]
$myMap["key"] = "value"

ConsoleWrite("- Array: " & GetDataTypeName(CheckDataType($myArray)) & @CRLF)
ConsoleWrite("- Map: " & GetDataTypeName(CheckDataType($myMap)) & @CRLF)
ConsoleWrite("- Integer: " & GetDataTypeName(CheckDataType(42)) & @CRLF)
ConsoleWrite("- Float: " & GetDataTypeName(CheckDataType(3.14159)) & @CRLF)
ConsoleWrite("- String int: " & GetDataTypeName(CheckDataType("42")) & @CRLF)
ConsoleWrite("- Hex loose: " & GetDataTypeName(CheckDataType("0xFF")) & @CRLF)
ConsoleWrite("- Hex strict ABC: " & GetDataTypeName(CheckDataType("ABC", True)) & @CRLF)
ConsoleWrite("- Hex strict ABCD: " & GetDataTypeName(CheckDataType("ABCD", True)) & @CRLF)
ConsoleWrite("- Boolean true: " & GetDataTypeName(CheckDataType(True)) & @CRLF)
ConsoleWrite("- String bool: " & GetDataTypeName(CheckDataType("true")) & @CRLF)
ConsoleWrite("- International numbers: " & GetDataTypeName(CheckDataType("1,234.56")) & @CRLF)
ConsoleWrite("- EU format: " & GetDataTypeName(CheckDataType("1.234,56")) & @CRLF)
ConsoleWrite("- Thousands only: " & GetDataTypeName(CheckDataType("1,234")) & @CRLF)

:)

Regards,
 

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...