Code archives/Algorithms/Base64 Encoding

This code has been declared by its author to be Public Domain code.

Download source code

Base64 Encoding by N2006
If you don't know what Base64 is, chances are you don't need it. If you do, chances are you already know how to use it. However, I didn't know what it was or how to use it, but someone asked so I wrote the bloody thing up anyways. Defiance, you'd better wake the heck up and check this.

For a quick example:
SuperStrict

Repeat
    Local in$ = Input( "Encode> " )
    If in.ToLower( ) = "q" Then Exit
    
    Local a@ Ptr = in.ToCString( )
    
    Local enc$ = EncodeBase64( a, in.Length )
    Print "ENCODED"
    Print "<<<"+enc+">>>"
    Local dec@[] = DecodeBase64( enc )
    Print "DECODED"
    Print "<<<"+String.FromBytes( dec, dec.Length )+">>>"
    
    MemFree( a )
Forever
SuperStrict

Private

Const etable$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
Global dtable@[256]
For Local __di:Int = 0 To etable.Length-1
    dtable[etable[__di]] = __di
Next

Public

Function EncodeBase64$( in@ Ptr, sizein:Int )
    If sizein <= 0 Then Return Null
    Local out:Byte[64]
    Local s$
    
    Local p@ Ptr = out
    Local cc% = 0
    
    For Local i% = 0 To sizein-1 Step 3
        Local c1@, c2@
        c1 = in[i]&$FF
        c2 = in[i+1]&$FF
        
        p[0] = etable[in[0] Shr 2]
        If i+1 < sizein Then
            p[1] = etable[((in[0] & $3) Shl 4) | ((in[1] & $F0) Shr 4)]
            If i+2 < sizein Then
                p[2] = etable[((in[1] & $F) Shl 2) | ((in[2] & $C0) Shr 6)]
                p[3] = etable[in[2] & $3F]
            ElseIf i+1 < sizein Then
                p[2] = etable[((in[1] & $F) Shl 2)]
            EndIf
        Else
            p[1] = etable[((in[0] & $3) Shl 4)]
        EndIf
        
        in :+ 3
        p :+ 4
        cc :+ 4
        If cc = 64 Then
            s :+ String.FromBytes(out,cc)
            p = out
            cc = 0
        EndIf
    Next
    Select sizein Mod 3
        Case 0
            s :+ String.FromBytes(out, cc)
        Case 1
            s :+ String.FromBytes(out, cc-2)+"=="
        Case 2
            s :+ String.FromBytes(out, cc-1)+"="
    End Select
    Return s
End Function

' Assumes you're passing a valid string to it
Function DecodeBase64:Byte[]( in$ )
    Local f% = in.Find("=")
    in = in.Replace("=","~0")
    Local rm% = 0
    If f = -1 Then
        rm = 0
        f = in.Length-1
    ElseIf f = in.Length-1 Then
        rm = 1
    ElseIf f = in.Length-2 Then
        rm = 2
    EndIf
    Local out@[((in.Length/4)*3)-rm]
    Local p@ Ptr = out
    Local bc% = 0
    For Local cc:Int = 0 To f Step 4
        p[0] = (dtable[in[cc]] Shl 2) | (dtable[in[cc+1]] Shr 4)
        If out.Length > (bc+1) Then p[1] = ((dtable[in[cc+1]] & $F) Shl 4) | ((dtable[in[cc+2]]&$3C) Shr 2)
        If out.Length > (bc+2) Then p[2] = ((dtable[in[cc+2]] & $3) Shl 6) | dtable[in[cc+3]]
        bc :+ 3
        p :+ 3
    Next
    Return out
End Function

Comments

flounder220012006
Good job. you might also want to try a base 128 encoder, this is one that i made for blitz to include resources in the source (its also not really been tested on many computers):
Function base128(filename$,dest$)
     basekey$=" !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}©ÀÁÂÃÄÅÈÉÊËÒÓÖÙÚàáâãäåèéëñòóôõöùúüýÿ"
     bitsleft=24
     bitline%=0
	 size=FileSize(filename)-1
	 in=ReadFile(filename)
	 out=WriteFile(dest)
	 outline=0
	 WriteInt out,1635017028
	 WriteByte out,32
	 WriteByte out,34
	 For i=0 To size
          bitline=bitline Or (ReadByte(in) Shl bitsleft)
          bitsleft=bitsleft-8
          While(bitsleft<18)
               WriteByte out,Asc(Mid(basekey,((bitline Shr 31) And 1)*64+((bitline Shr 30) And 1)*32+((bitline Shr 29) And 1)*16+((bitline Shr 28) And 1)*8+((bitline Shr 27) And 1)*4+((bitline Shr 26) And 1)*2+((bitline Shr 25) And 1)+1,1))
               outline=outline+1
			   If (outline=128)
			        outline=0
					WriteByte out,34
					WriteByte out,13
					WriteByte out,10
					WriteInt out,1635017028
					WriteByte out,32
					WriteByte out,34
			   EndIf
			   bitsleft=bitsleft+7
               bitline=bitline Shl 7
          Wend
     Next
     If (bitsleft<>24)
          WriteByte out,Asc(Mid(basekey,((bitline Shr 31) And 1)*64+((bitline Shr 30) And 1)*32+((bitline Shr 29) And 1)*16+((bitline Shr 28) And 1)*8+((bitline Shr 27) And 1)*4+((bitline Shr 26) And 1)*2+((bitline Shr 25) And 1)+1,1))
          outline=outline+1
          If (outline=128)
			    outline=0
				WriteByte out,34
				WriteByte out,13
				WriteByte out,10
				WriteInt out,1635017028
				WriteByte out,32
				WriteByte out,34
		  EndIf
     EndIf
	 WriteByte out,32
     WriteByte out,34
	 CloseFile(in)
	 CloseFile(out)
End Function

Dim base128dekey(0)

Function debase128(dest$)
     Dim base128dekey(256)
     basekey$=" !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}©ÀÁÂÃÄÅÈÉÊËÒÓÖÙÚàáâãäåèéëñòóôõöùúüýÿ"
     For i=0 To 127
          base128dekey(Asc(Mid(basekey,i+1,1)))=i Shl 1
     Next
     bitsleft=24
     bitline%=0
	 out=WriteFile(dest)
	 lin$=""
	 For i=0 To 127
	     lin=lin+"a"
	 Next
     While (Len(lin)=128)
          Read lin
          For i=0 To Len(lin)-1
               bitline=bitline Or (base128dekey(Asc(Mid(lin,i+1,1))) Shl bitsleft)
               bitsleft=bitsleft-7
               While(bitsleft<17)
	                WriteByte out,((bitline Shr 31) And 1)*128+((bitline Shr 30) And 1)*64+((bitline Shr 29) And 1)*32+((bitline Shr 28) And 1)*16+((bitline Shr 27) And 1)*8+((bitline Shr 26) And 1)*4+((bitline Shr 25) And 1)*2+((bitline Shr 24) And 1)
                    bitsleft=bitsleft+8
                    bitline=bitline Shl 8
               Wend
          Next
     Wend
	 CloseFile(out)
	 Dim base128dekey(0)
End Function



Jim Teeuwen2006
*wakes up* Nice work noel. Ive been breaking my head over this for a while while writing up my XML lib.


- regards, Defiance


Jake L.2008
The EncodeBase64() function crashes sometimes with an unnamed MAV (even in Debugmode) in the line:

c1 = in[i]&$FF


This is really weird. The crash occured on different i values, even with the same data provided. Is there a known problem when using Pixmap.PixelPtr(0,0)? (that's the data I want to encode). The size and anything else seems to be ok as it runs most of the time. But approx. every 6. or 7. run the code fails.

Very strange...


Code Archives Forum