LoginLogin

Base64 Decoder

Root / Programming Questions / [.]

DevinF06Created:
I need some help making a Base64 Decoder

VAR BASE64$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
'Converting a base 64 character in to a number from 0 to 63:
'(This isn't the most efficient method but it's the simplest)
DEF READ_B64_DIGIT(D$)
 VAR D=INSTR(BASE64$,D$[I])
 IF D<0 THEN
  PRINT "Illegal character found"
  BEEP
  STOP
 ENDIF
 RETURN D
END

DEF DECODE_B64(B64$)
 IF LEN(B64$) MOD 4 THEN
  PRINT "Length must be a multiple of 4"
  BEEP
  STOP
 ENDIF
 
 DIM RET[0]
 VAR TEMP,TEMP_SIZE
 VAR I
 FOR I=0 TO LEN(B64$)-1
  IF B64$[I]=="=" THEN BREAK
  TEMP=TEMP<<6 OR READ_B64_DIGIT(B64$[I])
  INC TEMP_SIZE,6
  IF TEMP_SIZE>=8 THEN
   DEC TEMP_SIZE,8
   PUSH RET,TEMP>>TEMP_SIZE AND 255
  ENDIF
 NEXT
 
 RETURN RET
END
Basically the way this works is that each base 64 character contains 6 bits of information, and you need to output a list of 8-bit values. So it reads the base 64 string, and keeps track of the 6 bits from each character. When it has at least 8 bits, it takes the oldest 8 bits and adds them to the output array.

I am too slow. Do you want my example, it has a encoder and a decoder? Well, just in case and so my effort wasn't in vain, here it is. Please excuse any type-os as I manually retyped this in. If you wanted it to work with arrays instead, it shouldn't be too hard to adapt. So, what do you need Base64 for? I hope I didn't just do your homework.
OPTION STRICT
VAR BASE64_INDEX$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
VAR TEST$ = "Hello world! This is a test of the Base64 Encoder / Decoder." + CHR$(10) + "I used " + CHR$(34) + "http://en.wikipedia.org/wiki/Base_64" + CHR$(34) + " as a implementation reference. It will encode / decode string."

VAR  RESULT$ = ""

RESULT$ = ENCODE_BASE64(TEST$)
PRINT RESULT$

RESULT$ = DECODE_BASE64(RESULT$)
PRINT RESULT$
END

DEF ENCODE_BASE64(VALUE$)
 VAR MAX_WIDTH = 40
 VAR LINE_LEN = 0
 VAR MSG_LEN = LEN(VALUE$)
 VAR RET$ = ""
 VAR I, J, IDX
 VAR TEMP$, WORK$ = ""

 FOR 1 = 0 TO MSG_LEN - 1 STEP 3
  WORK$ = WORK$ + BIN$(ASC(MID$(VALUE$, I, 1)), 8)
  IF I + 1 < MSG_LEN THEN
   WORK$ = WORK$ + BIN$(ASC(MID$(VALUE$, I + 1, 1)), 8)
  ENDIF
  IF I + 2 < MSG_LEN THEN
   WORK$ = WORK$ + BIN$(ASC(MID$(VALUE$, I + 2, 1)), 8)
  ENDIF

  FOR J = 0 TO 3
   IF LEN(WORK$) >= 6 THEN
    TEMP$ = LEFT$(WORK$, 6)
    WORK$ = MID$(WORK$, 6, LEN(WORK$) - 6)
    IDX = VAL("&B" + TEMP$)
    RET$ = RET$ + MID$(BASE64_INDEX$, IDX, 1)
   ELSEIF LEN(WORKI$) >= 1 THEN
    TEMP$ = LEFT$(WORK$ + "000000", 6)
    WORK$ = ""
    IDX = VAL("&B" + TEMP$)
    RET$ = RET$ + MID$(BASE64_INDEX$, IDX, 1)
   ELSE
    RET$ = RET$ + "="
   ENDIF
   LINE_LEN = LINE_LEN + 1
   IF LINE_LEN >= MAX_WIDTH THEN
    LINE_LEN = 0
    RET$ = RET$ + CHR$(10) 'Enter key
   ENDIF
  NEXT J
 NEXT i
 RETURN RET$
END

DEF DECODE_BASE64(VALUE$)
 VAR I, J, CH$, RET$ = "", WORK$ = ""
 VAR TEMP$, MAX_LEN

 IF RIGHT$(VALUE$, 2) = "==" THEN
   MAX_LEN = LEN(VALUE$) - 2
 IF RIGHT$(VALUE$, 1) = "=" THEN
   MAX_LEN = LEN(VALUE$) - 1
 ELSE
   MAX_LEN = LEN(VALUE$) 
 ENDIF

 FOR I = 0 TO MAX_LEN - 1
  CH$ = MID$(VALUE$, I, 1)
   J = INSTR(BASE64_INDEX$, CH$)
  IF J >= 0 THEN
   WORK$ = WORK$ + BIN$(J, 6)
  ENDIF

  WHILE LEN(WORK$) >= 8
   TEMP$ = LEFT$(WORK$, 8)
   WORK$ = MID$(WORK$, 8, LEN(WORK$) - 8)
   RET$ = RET$ + CHR$(VAL("&B" + TEMP$))
  WEND
 NEXT i

 RETURN RET$
END

Again like the comment at the top of the code says, wikipedia is your friend. https://en.wikipedia.org/wiki/Base_64

The encoder wasn't a problem, I just indexed the characters ("ABCDEF..."[VAL("&B"+...)]) Anyway, I now have an idea to make my Base64 decoder actually work EDIT: I had to fix some things, but now it's done