' Wildcard Pattern Matching — matches strings with * and ? wildcards
#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN() AS LONG
    LOCAL pattern AS STRING
    LOCAL text AS STRING
    LOCAL pIdx AS LONG
    LOCAL tIdx AS LONG
    LOCAL starIdx AS LONG
    LOCAL matchIdx AS LONG
    LOCAL matched AS LONG
    LOCAL pLen AS LONG
    LOCAL tLen AS LONG
    LOCAL pChar AS STRING
    LOCAL tChar AS STRING
    LOCAL testCount AS LONG
    LOCAL passCount AS LONG
    LOCAL failCount AS LONG
    LOCAL result AS STRING
    LOCAL status AS STRING
    testCount = 0
    passCount = 0
    failCount = 0
    PRINT "============================================"
    PRINT "      WILDCARD PATTERN MATCHING"
    PRINT "============================================"
    PRINT ""
    PRINT "* matches any sequence"
    PRINT "? matches any single character"
    PRINT ""
    text = "hello world"
    pattern = "hello*"
    testCount = testCount + 1
    pLen = LEN(pattern)
    tLen = LEN(text)
    pIdx = 1
    tIdx = 1
    starIdx = -1
    matchIdx = -1
    DO WHILE tIdx <= tLen
        IF pIdx <= pLen THEN
            pChar = MID$(pattern, pIdx, 1)
        ELSE
            pChar = ""
        END IF
        IF tIdx <= tLen THEN
            tChar = MID$(text, tIdx, 1)
        ELSE
            tChar = ""
        END IF
        IF pIdx <= pLen AND pChar = "*" THEN
            starIdx = pIdx
            matchIdx = tIdx
            pIdx = pIdx + 1
        ELSE
            IF pIdx <= pLen AND (pChar = "?" OR pChar = tChar) THEN
                pIdx = pIdx + 1
                tIdx = tIdx + 1
            ELSE
                IF starIdx <> -1 THEN
                    pIdx = starIdx + 1
                    matchIdx = matchIdx + 1
                    tIdx = matchIdx
                ELSE
                    matched = 0
                    EXIT DO
                END IF
            END IF
        END IF
    LOOP
    DO WHILE pIdx <= pLen AND MID$(pattern, pIdx, 1) = "*"
        pIdx = pIdx + 1
    LOOP
    IF pIdx > pLen THEN
        matched = 1
    ELSE
        matched = 0
    END IF
    IF matched = 1 THEN
        passCount = passCount + 1
        status = "PASS"
    ELSE
        failCount = failCount + 1
        status = "FAIL"
    END IF
    PRINT "Test " + STR$(testCount) + ": '" + pattern + "' vs '" + text + "' -> " + status
    text = "hello world"
    pattern = "*world"
    testCount = testCount + 1
    pLen = LEN(pattern)
    tLen = LEN(text)
    pIdx = 1
    tIdx = 1
    starIdx = -1
    matchIdx = -1
    DO WHILE tIdx <= tLen
        IF pIdx <= pLen THEN
            pChar = MID$(pattern, pIdx, 1)
        ELSE
            pChar = ""
        END IF
        IF tIdx <= tLen THEN
            tChar = MID$(text, tIdx, 1)
        ELSE
            tChar = ""
        END IF
        IF pIdx <= pLen AND pChar = "*" THEN
            starIdx = pIdx
            matchIdx = tIdx
            pIdx = pIdx + 1
        ELSE
            IF pIdx <= pLen AND (pChar = "?" OR pChar = tChar) THEN
                pIdx = pIdx + 1
                tIdx = tIdx + 1
            ELSE
                IF starIdx <> -1 THEN
                    pIdx = starIdx + 1
                    matchIdx = matchIdx + 1
                    tIdx = matchIdx
                ELSE
                    matched = 0
                    EXIT DO
                END IF
            END IF
        END IF
    LOOP
    DO WHILE pIdx <= pLen AND MID$(pattern, pIdx, 1) = "*"
        pIdx = pIdx + 1
    LOOP
    IF pIdx > pLen THEN
        matched = 1
    ELSE
        matched = 0
    END IF
    IF matched = 1 THEN
        passCount = passCount + 1
        status = "PASS"
    ELSE
        failCount = failCount + 1
        status = "FAIL"
    END IF
    PRINT "Test " + STR$(testCount) + ": '" + pattern + "' vs '" + text + "' -> " + status
    text = "hello world"
    pattern = "he?lo*"
    testCount = testCount + 1
    pLen = LEN(pattern)
    tLen = LEN(text)
    pIdx = 1
    tIdx = 1
    starIdx = -1
    matchIdx = -1
    DO WHILE tIdx <= tLen
        IF pIdx <= pLen THEN
            pChar = MID$(pattern, pIdx, 1)
        ELSE
            pChar = ""
        END IF
        IF tIdx <= tLen THEN
            tChar = MID$(text, tIdx, 1)
        ELSE
            tChar = ""
        END IF
        IF pIdx <= pLen AND pChar = "*" THEN
            starIdx = pIdx
            matchIdx = tIdx
            pIdx = pIdx + 1
        ELSE
            IF pIdx <= pLen AND (pChar = "?" OR pChar = tChar) THEN
                pIdx = pIdx + 1
                tIdx = tIdx + 1
            ELSE
                IF starIdx <> -1 THEN
                    pIdx = starIdx + 1
                    matchIdx = matchIdx + 1
                    tIdx = matchIdx
                ELSE
                    matched = 0
                    EXIT DO
                END IF
            END IF
        END IF
    LOOP
    DO WHILE pIdx <= pLen AND MID$(pattern, pIdx, 1) = "*"
        pIdx = pIdx + 1
    LOOP
    IF pIdx > pLen THEN
        matched = 1
    ELSE
        matched = 0
    END IF
    IF matched = 1 THEN
        passCount = passCount + 1
        status = "PASS"
    ELSE
        failCount = failCount + 1
        status = "FAIL"
    END IF
    PRINT "Test " + STR$(testCount) + ": '" + pattern + "' vs '" + text + "' -> " + status
    text = "test.txt"
    pattern = "*.txt"
    testCount = testCount + 1
    pLen = LEN(pattern)
    tLen = LEN(text)
    pIdx = 1
    tIdx = 1
    starIdx = -1
    matchIdx = -1
    DO WHILE tIdx <= tLen
        IF pIdx <= pLen THEN
            pChar = MID$(pattern, pIdx, 1)
        ELSE
            pChar = ""
        END IF
        IF tIdx <= tLen THEN
            tChar = MID$(text, tIdx, 1)
        ELSE
            tChar = ""
        END IF
        IF pIdx <= pLen AND pChar = "*" THEN
            starIdx = pIdx
            matchIdx = tIdx
            pIdx = pIdx + 1
        ELSE
            IF pIdx <= pLen AND (pChar = "?" OR pChar = tChar) THEN
                pIdx = pIdx + 1
                tIdx = tIdx + 1
            ELSE
                IF starIdx <> -1 THEN
                    pIdx = starIdx + 1
                    matchIdx = matchIdx + 1
                    tIdx = matchIdx
                ELSE
                    matched = 0
                    EXIT DO
                END IF
            END IF
        END IF
    LOOP
    DO WHILE pIdx <= pLen AND MID$(pattern, pIdx, 1) = "*"
        pIdx = pIdx + 1
    LOOP
    IF pIdx > pLen THEN
        matched = 1
    ELSE
        matched = 0
    END IF
    IF matched = 1 THEN
        passCount = passCount + 1
        status = "PASS"
    ELSE
        failCount = failCount + 1
        status = "FAIL"
    END IF
    PRINT "Test " + STR$(testCount) + ": '" + pattern + "' vs '" + text + "' -> " + status
    text = "document.pdf"
    pattern = "*.txt"
    testCount = testCount + 1
    pLen = LEN(pattern)
    tLen = LEN(text)
    pIdx = 1
    tIdx = 1
    starIdx = -1
    matchIdx = -1
    DO WHILE tIdx <= tLen
        IF pIdx <= pLen THEN
            pChar = MID$(pattern, pIdx, 1)
        ELSE
            pChar = ""
        END IF
        IF tIdx <= tLen THEN
            tChar = MID$(text, tIdx, 1)
        ELSE
            tChar = ""
        END IF
        IF pIdx <= pLen AND pChar = "*" THEN
            starIdx = pIdx
            matchIdx = tIdx
            pIdx = pIdx + 1
        ELSE
            IF pIdx <= pLen AND (pChar = "?" OR pChar = tChar) THEN
                pIdx = pIdx + 1
                tIdx = tIdx + 1
            ELSE
                IF starIdx <> -1 THEN
                    pIdx = starIdx + 1
                    matchIdx = matchIdx + 1
                    tIdx = matchIdx
                ELSE
                    matched = 0
                    EXIT DO
                END IF
            END IF
        END IF
    LOOP
    DO WHILE pIdx <= pLen AND MID$(pattern, pIdx, 1) = "*"
        pIdx = pIdx + 1
    LOOP
    IF pIdx > pLen THEN
        matched = 1
    ELSE
        matched = 0
    END IF
    IF matched = 1 THEN
        passCount = passCount + 1
        status = "PASS"
    ELSE
        failCount = failCount + 1
        status = "FAIL"
    END IF
    PRINT "Test " + STR$(testCount) + ": '" + pattern + "' vs '" + text + "' -> " + status
    text = "abc"
    pattern = "a*c"
    testCount = testCount + 1
    pLen = LEN(pattern)
    tLen = LEN(text)
    pIdx = 1
    tIdx = 1
    starIdx = -1
    matchIdx = -1
    DO WHILE tIdx <= tLen
        IF pIdx <= pLen THEN
            pChar = MID$(pattern, pIdx, 1)
        ELSE
            pChar = ""
        END IF
        IF tIdx <= tLen THEN
            tChar = MID$(text, tIdx, 1)
        ELSE
            tChar = ""
        END IF
        IF pIdx <= pLen AND pChar = "*" THEN
            starIdx = pIdx
            matchIdx = tIdx
            pIdx = pIdx + 1
        ELSE
            IF pIdx <= pLen AND (pChar = "?" OR pChar = tChar) THEN
                pIdx = pIdx + 1
                tIdx = tIdx + 1
            ELSE
                IF starIdx <> -1 THEN
                    pIdx = starIdx + 1
                    matchIdx = matchIdx + 1
                    tIdx = matchIdx
                ELSE
                    matched = 0
                    EXIT DO
                END IF
            END IF
        END IF
    LOOP
    DO WHILE pIdx <= pLen AND MID$(pattern, pIdx, 1) = "*"
        pIdx = pIdx + 1
    LOOP
    IF pIdx > pLen THEN
        matched = 1
    ELSE
        matched = 0
    END IF
    IF matched = 1 THEN
        passCount = passCount + 1
        status = "PASS"
    ELSE
        failCount = failCount + 1
        status = "FAIL"
    END IF
    PRINT "Test " + STR$(testCount) + ": '" + pattern + "' vs '" + text + "' -> " + status
    text = "abcd"
    pattern = "a?c?"
    testCount = testCount + 1
    pLen = LEN(pattern)
    tLen = LEN(text)
    pIdx = 1
    tIdx = 1
    starIdx = -1
    matchIdx = -1
    DO WHILE tIdx <= tLen
        IF pIdx <= pLen THEN
            pChar = MID$(pattern, pIdx, 1)
        ELSE
            pChar = ""
        END IF
        IF tIdx <= tLen THEN
            tChar = MID$(text, tIdx, 1)
        ELSE
            tChar = ""
        END IF
        IF pIdx <= pLen AND pChar = "*" THEN
            starIdx = pIdx
            matchIdx = tIdx
            pIdx = pIdx + 1
        ELSE
            IF pIdx <= pLen AND (pChar = "?" OR pChar = tChar) THEN
                pIdx = pIdx + 1
                tIdx = tIdx + 1
            ELSE
                IF starIdx <> -1 THEN
                    pIdx = starIdx + 1
                    matchIdx = matchIdx + 1
                    tIdx = matchIdx
                ELSE
                    matched = 0
                    EXIT DO
                END IF
            END IF
        END IF
    LOOP
    DO WHILE pIdx <= pLen AND MID$(pattern, pIdx, 1) = "*"
        pIdx = pIdx + 1
    LOOP
    IF pIdx > pLen THEN
        matched = 1
    ELSE
        matched = 0
    END IF
    IF matched = 1 THEN
        passCount = passCount + 1
        status = "PASS"
    ELSE
        failCount = failCount + 1
        status = "FAIL"
    END IF
    PRINT "Test " + STR$(testCount) + ": '" + pattern + "' vs '" + text + "' -> " + status
    text = "abcde"
    pattern = "a*e"
    testCount = testCount + 1
    pLen = LEN(pattern)
    tLen = LEN(text)
    pIdx = 1
    tIdx = 1
    starIdx = -1
    matchIdx = -1
    DO WHILE tIdx <= tLen
        IF pIdx <= pLen THEN
            pChar = MID$(pattern, pIdx, 1)
        ELSE
            pChar = ""
        END IF
        IF tIdx <= tLen THEN
            tChar = MID$(text, tIdx, 1)
        ELSE
            tChar = ""
        END IF
        IF pIdx <= pLen AND pChar = "*" THEN
            starIdx = pIdx
            matchIdx = tIdx
            pIdx = pIdx + 1
        ELSE
            IF pIdx <= pLen AND (pChar = "?" OR pChar = tChar) THEN
                pIdx = pIdx + 1
                tIdx = tIdx + 1
            ELSE
                IF starIdx <> -1 THEN
                    pIdx = starIdx + 1
                    matchIdx = matchIdx + 1
                    tIdx = matchIdx
                ELSE
                    matched = 0
                    EXIT DO
                END IF
            END IF
        END IF
    LOOP
    DO WHILE pIdx <= pLen AND MID$(pattern, pIdx, 1) = "*"
        pIdx = pIdx + 1
    LOOP
    IF pIdx > pLen THEN
        matched = 1
    ELSE
        matched = 0
    END IF
    IF matched = 1 THEN
        passCount = passCount + 1
        status = "PASS"
    ELSE
        failCount = failCount + 1
        status = "FAIL"
    END IF
    PRINT "Test " + STR$(testCount) + ": '" + pattern + "' vs '" + text + "' -> " + status
    PRINT ""
    PRINT "Results: " + STR$(passCount) + " passed, " + STR$(failCount) + " failed"
    FUNCTION = 0
END FUNCTION
