Resolved Base32 Decode.

Cecil

19+ years progress programming and still learning.
Has anyone ever written a base32 decode function/method in the ABL?
 

Cecil

19+ years progress programming and still learning.
I think I have figured it out.

Code:
Function charToValue returns integer (input charByte as character):

    DEFINE VARIABLE inCharByte AS INTEGER     NO-UNDO.
            
    inCharByte = asc(charByte).

    //65-90 == uppercase letters
    if inCharByte < 91 and inCharByte > 64 then
        return inCharByte - 65.
    
    //50-55 == numbers 2-7
    if inCharByte < 56 and inCharByte > 49 then
        return inCharByte - 24.
    
    //97-122 == lowercase letters
    if(inCharByte < 123 and inCharByte > 96) then
        return inCharByte - 97.

    return ?.
end function.

FUNCTION bitOR RETURNS INTEGER (INPUT X AS INTEGER, INPUT Y AS INTEGER):
   DEFINE VARIABLE b1 AS INTEGER NO-UNDO.
   DEFINE VARIABLE b2 AS INTEGER NO-UNDO.
   DEFINE VARIABLE n  AS INTEGER NO-UNDO.
   DEFINE VARIABLE Z  AS INTEGER NO-UNDO.

   DO n = 1 TO 32:
     ASSIGN
       b1 = GET-BITS(X, n, 1)
       b2 = GET-BITS(Y, n, 1)
       .
       IF b1 = 1 OR b2 = 1 THEN
        PUT-BITS(Z, n, 1) = 1.
   END.

   RETURN Z.
END FUNCTION.

Function arithmeticLeftShift return integer (input x as integer, input z as integer):

    DEFINE VARIABLE buff AS INTEGER     NO-UNDO.
    DEFINE VARIABLE ishift AS INTEGER     NO-UNDO.
    DEFINE variable y AS INTEGER     NO-UNDO.
    
    Do ishift = 1 to z:
    
        put-bits(y, 2, 31) = get-bits(x, 1, 31).   
        put-bits(y, 1, 1)  = 0.  // The empty position in the least significant bit is filled with a zero.
    
        x = y.
    
    End.
    
    return x.

end function.


Function arithmeticRightShift return integer (input x as integer, input z as integer):

    DEFINE VARIABLE buff AS INTEGER     NO-UNDO.
    DEFINE VARIABLE ishift AS INTEGER     NO-UNDO.
    DEFINE variable y AS INTEGER     NO-UNDO.
    
    Do ishift = 1 to z:
    
        put-bits(y, 32, 1) = get-bits(x, 32, 1).   //The empty position in the most significant bit is filled with a copy of the original MSB
        put-bits(y, 1, 31) = get-bits(x, 2, 31).
    
        x = y.
    
    End.
    
    return x.
end function.


Function base32decode return memptr (input base32EncodedValue as character):

    DEFINE VARIABLE returnArray     AS MEMPTR      NO-UNDO.
    
    DEFINE VARIABLE cCharByte       AS CHARACTER   NO-UNDO.
    
    DEFINE VARIABLE iValue          AS INTEGER     NO-UNDO.   
    DEFINE VARIABLE iCharIndex      AS INTEGER     NO-UNDO.
    DEFINE VARIABLE iLength         AS INTEGER     NO-UNDO.
    DEFINE VARIABLE iByteCount      AS INTEGER     NO-UNDO.
    DEFINE VARIABLE iBitsRemaining  AS INTEGER     NO-UNDO.
    DEFINE VARIABLE iMask           AS INTEGER     NO-UNDO.
    DEFINE VARIABLE iCurrentByte    AS INTEGER     NO-UNDO.
    DEFINE VARIABLE iBytePosition   AS INTEGER     NO-UNDO.
    
    set-byte-order(returnArray ) = big-endian.
    
    // Terminiate if no value has be inputted 
    if base32EncodedValue eq "" Then
        return ?.
    
    assign
        //base32EncodedValue = lc(base32EncodedValue)
        base32EncodedValue = replace(base32EncodedValue,' ','')
        base32EncodedValue = replace(base32EncodedValue,'=','')
        .
        
    assign   
        iLength    = length(base32EncodedValue, "RAW")   
        iByteCount = truncate(iLength * 5 / 8, 0)
        .
    
    set-size(returnArray ) = 0.
    set-size(returnArray ) = iByteCount.     
    
    assign
        iBitsRemaining = 8
        iMask          = 0
        iCurrentByte   = 0
        iBytePosition  = 0.
                                  
    CHARACTER_BYTE:
    do iCharIndex = 1 to iLength:
    
        cCharByte = substring(base32EncodedValue, iCharIndex, 1, "RAW").
        
        iValue = charToValue(input cCharByte).
        
        // Ignore invalid charactes and move on.
        if iValue eq ? Then
            next CHARACTER_BYTE.
        
        If iBitsRemaining gt 5 Then
        Do:
        
            iMask = arithmeticLeftShift(iValue , (iBitsRemaining - 5) ).
        
            iCurrentByte = bitOR(iCurrentByte, iMask).
        
            iBitsRemaining = iBitsRemaining - 5.
            
        end.
        else
        do:
            
            iMask = arithmeticRightShift(iValue , (5 - iBitsRemaining) ).
        
            iCurrentByte = bitOR(iCurrentByte, iMask).
        
            iBytePosition  = iBytePosition + 1.
            put-byte(returnArray, iBytePosition) = iCurrentByte.
            
            iCurrentByte = arithmeticLeftShift(iValue , (3 + iBitsRemaining) ).
            
            iBitsRemaining = iBitsRemaining + 3.       
        end.
    End.
    
    if iBytePosition ne iByteCount then
    do:
        //iBytePosition  = iBytePosition + 1.
        put-byte(returnArray, iBytePosition + 1) = iCurrentByte.
        
    end.
    
    return returnArray.
    
    // Garbage collection
    finally:
        set-size(returnArray) = 0.
    end finally.
    
end.



/************* MAIN BLOCK ****************/


DEFINE VARIABLE mBase32Decoded AS MEMPTR      NO-UNDO.

etime(true).

set-size(mBase32Decoded) = 0.

mBase32Decoded = base32decode(input "jbsw y3dp ehpk 3pxp").

message 'SIZE:' get-size(mBase32Decoded).
message 'HEX:' string(hex-encode(mBase32Decoded)) .
message 'etime:' etime .

// Garbage collection
finally:

    set-size(mBase32Decoded) = 0.

end finally.
 
Top