' Base64 encoding/decoding: ASC/CHR$/bit shifts, URL-safe variant
#COMPILE EXE
#DIM ALL

SUB Base64Encode(BYVAL data AS STRING, BYREF result AS STRING)
    LOCAL b64 AS STRING
    LOCAL i AS LONG
    LOCAL n AS LONG
    LOCAL padding AS LONG
    LOCAL b0 AS LONG
    LOCAL b1 AS LONG
    LOCAL b2 AS LONG
    LOCAL c AS LONG
    LOCAL r AS STRING
    b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    n = LEN(data)
    padding = (3 - (n MOD 3)) MOD 3
    r = ""
    i = 1
    DO WHILE i <= n
        b0 = ASC(MID$(data, i, 1))
        i = i + 1
        IF i <= n THEN b1 = ASC(MID$(data, i, 1)) ELSE b1 = 0
        i = i + 1
        IF i <= n THEN b2 = ASC(MID$(data, i, 1)) ELSE b2 = 0
        i = i + 1
        c = (b0 / 4) + 1
        r = r & MID$(b64, c, 1)
        c = ((b0 AND 3) * 16) OR (b1 / 16) + 1
        r = r & MID$(b64, c, 1)
        c = ((b1 AND 15) * 4) OR (b2 / 64) + 1
        r = r & MID$(b64, c, 1)
        c = (b2 AND 63) + 1
        r = r & MID$(b64, c, 1)
    LOOP
    IF padding >= 1 THEN r = LEFT$(r, LEN(r) - 1) & "="
    IF padding >= 2 THEN r = LEFT$(r, LEN(r) - 2) & "=="
    result = r
END SUB

SUB Base64Decode(BYVAL encoded AS STRING, BYREF result AS STRING)
    LOCAL b64 AS STRING
    LOCAL i AS LONG
    LOCAL n AS LONG
    LOCAL v0 AS LONG
    LOCAL v1 AS LONG
    LOCAL v2 AS LONG
    LOCAL v3 AS LONG
    LOCAL c0 AS LONG
    LOCAL c1 AS LONG
    LOCAL c2 AS LONG
    LOCAL r AS STRING
    LOCAL ch AS STRING
    b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    n = LEN(encoded)
    r = ""
    i = 1
    DO WHILE i <= n
        v0 = INSTR(b64, MID$(encoded, i, 1)) - 1
        i = i + 1
        v1 = INSTR(b64, MID$(encoded, i, 1)) - 1
        i = i + 1
        v2 = INSTR(b64, MID$(encoded, i, 1)) - 1
        i = i + 1
        v3 = INSTR(b64, MID$(encoded, i, 1)) - 1
        i = i + 1
        c0 = (v0 * 4) OR (v1 / 16)
        c1 = ((v1 AND 15) * 16) OR (v2 / 4)
        c2 = ((v2 AND 3) * 64) OR v3
        r = r & CHR$(c0)
        ch = MID$(encoded, i - 1, 1)
        IF v2 >= 0 AND ch <> "=" THEN r = r & CHR$(c1)
        ch = MID$(encoded, i, 1)
        IF v3 >= 0 AND ch <> "=" THEN r = r & CHR$(c2)
    LOOP
    result = r
END SUB

SUB HexToBase64(BYVAL hexStr AS STRING, BYREF result AS STRING)
    LOCAL i AS LONG
    LOCAL n AS LONG
    LOCAL b AS LONG
    LOCAL data AS STRING
    LOCAL h AS STRING
    LOCAL encoded AS STRING
    hexStr = UCASE$(REPLACE$(hexStr, " ", ""))
    n = LEN(hexStr) / 2
    data = ""
    FOR i = 1 TO n
        h = "&H" & MID$(hexStr, (i - 1) * 2 + 1, 2)
        b = VAL(h)
        IF b < 0 THEN b = b + 256
        data = data & CHR$(b)
    NEXT i
    CALL Base64Encode(data, encoded)
    result = encoded
END SUB

FUNCTION PBMAIN() AS LONG
    LOCAL original AS STRING
    LOCAL encoded AS STRING
    LOCAL decoded AS STRING
    LOCAL b64result AS STRING
    PRINT "=== Base64 Encoding ==="
    PRINT
    original = "Hello World"
    CALL Base64Encode(original, encoded)
    CALL Base64Decode(encoded, decoded)
    PRINT "Original: " & original
    PRINT "Encoded: " & encoded
    PRINT "Decoded: " & decoded
    IF original = decoded THEN PRINT "Match: PASS" ELSE PRINT "Match: FAIL"
    PRINT
    original = "Base64 encoding test for PBXB64 compiler"
    CALL Base64Encode(original, encoded)
    CALL Base64Decode(encoded, decoded)
    PRINT "Original: " & original
    PRINT "Encoded: " & LEFT$(encoded, 24) & "..."
    IF original = decoded THEN PRINT "Match: PASS" ELSE PRINT "Match: FAIL"
    PRINT
    original = CHR$(0) & CHR$(255) & CHR$(128) & CHR$(64) & CHR$(1) & CHR$(2)
    CALL Base64Encode(original, encoded)
    CALL Base64Decode(encoded, decoded)
    PRINT "Binary (" & FORMAT$(LEN(original)) & " bytes): " & encoded
    IF original = decoded THEN PRINT "Match: PASS" ELSE PRINT "Match: FAIL"
    PRINT
    CALL HexToBase64("48656C6C6F", b64result)
    PRINT "48656C6C6F -> " & b64result
    PRINT
    PRINT "Base64 tests complete."
    FUNCTION = 0
END FUNCTION
