Opensource base64 functions

Share your advanced PureBasic knowledge/code with the community.
User avatar
Hroudtwolf
Addict
Addict
Posts: 803
Joined: Sat Feb 12, 2005 3:35 am
Location: Germany(Hessen)
Contact:

Opensource base64 functions

Post by Hroudtwolf »

Hi,

The following code shows an PB implementation of the base64 de-/encoder algorithms.

Best regards
Hroudtwolf

(The indentation will be OK after pasting into your editor.)

Code: Select all

; By Hroudtwolf
; 2009-09-03 (ISO 8601)
; PureBasic 4.4x
; Linux, Windows, OS X

EnableExplicit

; ***********************************************************************************
; Simple dataset structure for accessing strictly on ASCII character
; independent by character encoding mode. 
; ***********************************************************************************
Structure ASCII
	a.a
EndStructure

; ***********************************************************************************
; Public function.
; ***********************************************************************************
; Parameters:
; 		*ptrData		-	Pointer the the datablock which you want to encode.
;		nSize			-	Size of the datablock in bytes.
;
; Description:
; 		Use it to encode data to Base64 string.
;
; Return:
; 		Base64 string on success.
; ***********************************************************************************
Procedure.s Base64_Encode ( *ptrData.ASCII , nSize.i )
	Static 		Dim 	cLockUp		.c ( 64 )
	Static 				blInit		.i
	Static 				nI				.i
	Protected			*ptrEnd					= *ptrData + nSize
	Protected 	Dim	bInput		.b ( 3 )
	Protected 	Dim	cOutput		.a ( 4 )
	Protected			sOutput		.s
	Protected			nBlockSize	.i
	
	If Not ( blInit )
		blInit = #True

		; Creating static look up table.
		CopyMemory ( @ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" , @ cLockUp ( 0 ) , 64 * SizeOf ( CHARACTER ) )
	EndIf
	
	While ( *ptrData < *ptrEnd )
		nBlockSize = 0
		; Filling input table.
		For nI = 0 To 2
			If ( *ptrData < *ptrEnd )
				nBlockSize + 1
				bInput ( nI ) = *ptrData\a
				*ptrData + SizeOf ( ASCII )
			Else
				bInput ( nI ) = 0
			EndIf
		Next nI
		
		; Encoding of 3 bytes to 4 6-bit characters.
		If ( nBlockSize )
			cOutput ( 0 ) = cLockUp ( bInput ( 0 ) >> 2 )
			cOutput ( 1 ) = cLockUp ( ( ( bInput ( 0 ) & $03 ) << 4)  | ( ( bInput ( 1 ) & $f0 ) >> 4 ) )
			
			If ( nSize > 1 )
				cOutput ( 2 ) = cLockUp ( ( ( bInput ( 1 ) & $0f ) << 2 ) | ( ( bInput ( 2 ) & $c0 ) >> 6 ) )
			Else
				cOutput ( 2 ) = '='
			EndIf 
			
			If ( nSize > 2 )
				cOutput ( 3 ) = cLockUp ( bInput ( 2 ) & $3f )
			Else
				cOutput ( 3 ) = '='
			EndIf
			For nI = 0 To 3 
				sOutput + Chr ( cOutput ( nI ) )
			Next nI
		EndIf
	Wend
	
	ProcedureReturn sOutput
EndProcedure

; ***********************************************************************************
; Public function.
; ***********************************************************************************
; Parameters:
; 		sInput		-	Input base64 string.
;
; Description:
; 		Use it to decode a base64 string to binary data.
; 		Warning!!! You are full accountability about the returned datablock.
;
; Return:
; 		Pointer to a decoded memory block on success. Otherwise NULL.
; ***********************************************************************************
Procedure.i Base64_Decode ( sInput.s )
	Static 		Dim 	cLockUp			.c ( 81 )
	Static 				blInit			.i
	Protected			*ptrData			.CHARACTER 	= @ sInput
	Protected			nSize				.i				= Len ( sInput ) + 1
	Protected			*ptrEnd							= *ptrData + ( nSize * SizeOf ( CHARACTER ) )
	Protected			nValue			.b
	Protected			nPartSize		.f				= ( nSize - ( nSize / 3.333 ) ) * SizeOf ( CHARACTER ) 
	Protected			*ptrOutput		.BYTE			= AllocateMemory ( Int ( nPartSize ) )
	Protected			*ptrOutputStart				= *ptrOutput
	Protected 	Dim	cInput			.a ( 4 )
	Protected 	Dim	bOutput			.b ( 3 )
	Protected			nBlockSize		.i
	Protected			nI					.i
 
	If Not ( *ptrData )
		ProcedureReturn #Null
	EndIf

	If Not blInit
		blInit = #True
		
		; Creating static look up table.
		CopyMemory ( @ "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\]^_`abcdefghijklmnopq" , @ cLockUp ( 0 ) , 80 * SizeOf ( CHARACTER ) )
	EndIf
	
	While ( *ptrData < *ptrEnd )
		
		nBlockSize = 0
		
		For nI = 0 To 3
			If ( *ptrData < *ptrEnd )
				nValue = 0
				While ( *ptrData < *ptrEnd And Not nValue )
					; Reading a character from base64 string.
					nValue = *ptrData\c : *ptrData + SizeOf ( CHARACTER )
			 
			 		; Adjust of the lookup value.
					If ( nValue < 43 Or nValue > 122 )
						nValue = 0
					Else
						nValue = cLockUp ( nValue - 43 )
					EndIf

					; Detecting the end of the input.							
					If ( nValue = '$' )
				  		nValue = 0 
				   Else
				    	nValue = nValue - 61
				   EndIf
 
				Wend
	 			
	 			; Filling input table.
				If ( *ptrData < *ptrEnd )
					nBlockSize + 1
		 
					If ( nValue )
						cInput ( nI ) = nValue - 1
					EndIf 
				EndIf					
			Else
				Break
			EndIf	
		
		Next nI
		  
		; Decoding of 4 6-bit characters to 3 bytes.  
		If nBlockSize 
			bOutput ( 0 ) = ( cInput ( 0 ) << 2 | cInput ( 1 ) >> 4 ) 
			bOutput ( 1 ) = ( cInput ( 1 ) << 4 | cInput ( 2 ) >> 2 )
			bOutput ( 2 ) = ( ( ( cInput ( 2 ) << 6 ) & $C0 ) | cInput ( 3 ) )
			nI = 0
			; Writting of the decoded byte to the output buffer.
			While ( nI < ( nBlockSize - 1 ) )
				*ptrOutput\b = bOutput ( nI ) 
				*ptrOutput	 + SizeOf ( BYTE )
				nI				 + 1
			Wend
		EndIf
	Wend
	
	ProcedureReturn *ptrOutputStart
EndProcedure

;--- Test

Define.s sInput	= "Feel the pure power! PureBasic."
Define.i	nInput	= StringByteLength ( sInput )
Define.s sBase64 


sBase64 = Base64_Encode ( @ sInput , nInput )

Debug "Encoded: " + sBase64
Debug "Decoded:" + PeekS ( Base64_Decode ( sBase64 ) , nInput )
infratec
Always Here
Always Here
Posts: 7623
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Post by infratec »

Hi Hroudtwolf,

nice code, but why should someone us it?
The functions already exists in PB:

Base64Encoder()
Base64Decoder()

But it is good to learn something.

Bernd
User avatar
Hroudtwolf
Addict
Addict
Posts: 803
Joined: Sat Feb 12, 2005 3:35 am
Location: Germany(Hessen)
Contact:

Post by Hroudtwolf »

Hi,
nice code, but why should someone us it?
It is more for looking (code) than using.

Sometimes you got to reinvent the wheel if you want to learn how it was made.

Best regards

Wolf
User avatar
talisman
Enthusiast
Enthusiast
Posts: 231
Joined: Sat May 23, 2009 9:33 am

Post by talisman »

This is definitely useful for me, thank you very much. I am in the middle of doing a report and essay of various encryption algorithms. Base64 is a good start, much appreciated, believe me! :o
Post Reply