Opensource base64 functions
Posted: Thu Sep 03, 2009 1:54 pm
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.)
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 )