#include once "window9.bi"

Function Encode64(ByRef wsText As USTRING) As USTRING export
	#ifdef UNICODE
		dim as string bs64 = wsText.UTF8
	#else	
		dim as string bs64 = wsText
	#EndIf
	Dim as Integer j,k=0
	Dim as Integer l=len(bs64)
	if l=0 then return ""
	dim as string arr64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" & _
	"abcdefghijklmnopqrstuvwxyz" & _
	"0123456789+/"
	Dim as string  t64
	
	t64 = String(((l+2)\3)*4,"=")
	For j = 0 To l - ((l Mod 3)+1) Step 3
		t64[k+0] = arr64[(bs64[j+0] shr 2)]
		t64[k+1] = arr64[(((bs64[j+0] and 3) shl 4) + (bs64[j+1] shr 4))]
		t64[k+2] = arr64[(((bs64[j+1] and &H0F) shl 2) + (bs64[j+2] shr 6))]
		t64[k+3] = arr64[(bs64[j+2] and &H3F)]
		k += 4
	Next
	If (l mod 3) = 2 Then
		t64[k+0] = arr64[(bs64[j+0] shr 2)]
		t64[k+1] = arr64[(((bs64[j+0] and 3) shl 4) + (bs64[j+1] shr 4))]
		t64[k+2] = arr64[(((bs64[j+1] and &H0F) shl 2) + (bs64[j+2] shr 6))]
		t64[k+3]=61
	ElseIf (l mod 3) = 1 Then
		t64[k+0] = arr64[(bs64[j+0] shr 2)]
		t64[k+1] = arr64[((((bs64[j+0] and 3) shl 4) + (bs64[j+1] shr 4)))]
		t64[k+2]=61
		t64[k+3]=61
	End If
	#ifdef UNICODE
		dim as USTRING wsRet
		wsRet.UTF8 = t64
		return wsRet	
	#else	
		return t64
	#EndIf	
End Function

' decoder from EXT lib
function Decode64(ByRef wsText as USTRING) As USTRING export
	#ifdef UNICODE
		dim as string str_b64 = wsText.UTF8
	#else
		dim as string str_b64 = wsText
	#EndIf
	Dim As Integer sb64_len = Len(str_b64)
	If sb64_len < 4 Then Return ""
	Dim out_Str As String = String(((sb64_len \ 4) * 3), !"\0")
	static _decode_tbl(255) as ubyte => { _
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, _              ' 0..31
	0,0,0,0,0,0,0,0,0,0,0, _                    ' 32..42
	62,0,0,0,63, _                    ' 43 (+), 44..46, 47 (/)
	52,53,54,55,56,57,58,59,60,61, _                    ' 48..57 (0..9)
	0,0,0,0,0,0,0, _                    ' 58..64
	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25, _          ' 65..90 (A..Z)
	0,0,0,0,0,0, _                    ' 91..96
	26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,_ ' 97..122 (a..z)
	0,0,0,0,0 }                    ' 123..127
	
	Dim out_blen As Integer = 0
	for ctr64 as Integer = 0 to sb64_len - 1 Step 4
		dim as uinteger buf = (_decode_tbl(str_b64[ctr64+0]) shl 18) or _
		(_decode_tbl(str_b64[ctr64+1]) shl 12) or _
		(_decode_tbl(str_b64[ctr64+2]) shl  6) or _
		(_decode_tbl(str_b64[ctr64+3]))
		If str_b64[ctr64+2] = 61 And str_b64[ctr64+3] = 61 Then
			out_Str[out_blen+0] = buf shr 16
			out_blen += 1
			Exit for
		ElseIf str_b64[ctr64+2] <> 61 And str_b64[ctr64+3] = 61 Then
			out_Str[out_blen+0] = buf shr 16
			out_Str[out_blen+1] = (buf shr 8) and &hFF
			out_blen += 2
			Exit for
		EndIf
		out_Str[out_blen+0] = buf shr 16
		out_Str[out_blen+1] += (buf shr 8) and &hFF
		out_Str[out_blen+2] += buf and &hFF
		out_blen += 3
	Next
	#ifdef UNICODE
		dim as USTRING wsRet
		wsRet.UTF8 = Left(out_Str,out_blen)
		return wsRet		
	#else	
		return Left(out_Str,out_blen)
	#EndIf
end Function
