Decoding BASE64 in ALGOL68

Decided to see if I could come up with a routine in ALGOL68 to decode BASE64 encoded strings, partly because I’d recently had to implement this in Powershell and partly because I just felt like it.

In doing so I think I discovered (or possibly rediscovered) some of the ‘unusual’ features that can make ALGOL68 a bit of a challenge. I think I could make the code quite a lot shorter by manipulating the output directly instead of using a buffer, so I’m not entirely happy with the result, however it works and is relatively easy to follow.

It is probably worth remembering that in ALGOL68 arrays subscripts start at one not zero and that variable and function names can contain spaces, so IF (char in string(text[index], offset, list)) THEN  is perfectly valid (the function returns TRUE/FALSE depending on whether or not a match was found, and modifies the value of the second parameter (passed by reference) to indicate the start of the sub-string.

It is very different from some modern languages but it lends it self to some nice clean looking code, unfortunately in this case is promptly obfuscated by the shenanigans needed to allow bit-wise operations on integer values! I know I could have overloaded the logical operators with a new implementation to handle integer types, and I was very tempted but I decided to keep things short and simple!

 ALGOL68RS – decode.a68
PROGRAM decode
{  
  Copyright(C)2020      MT
 
  Decodes a BASE64 encoded string.

  https://en.wikipedia.org/wiki/Base64
  
  This  program  is free software: you can redistribute it and/or modify  it
  under the terms of the GNU General Public License as published by the Free
  Software Foundation, either version 3 of the License, or  (at your option)
  any later version.
 
  This  program  is  distributed  in the hope that it will  be  useful,  but
  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  or  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General  Public  License 
  for more details.
 
  You  should  have received a copy of the GNU General Public License  along
  with this program.  If not, see <http://www.gnu.org/licenses/>.

  23 Mar 20 0.1   001 - Initial version with an operator to convert integers
                        into roman numberals -MT
}
 
BEGIN
 
  PROC decode = (STRING text) STRING:
  BEGIN
 
    STRING list = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                  "abcdefghijklmnopqrstuvwxyz"
                  "0123456789+/=";
    STRING output := "";
    [3]INT buffer;
    INT offset := 0, index := 1, count := 1, counter := 1
 
    WHILE (index <= UPB text) DO
      IF (char in string(text[index], offset, list)) THEN 
        IF (text[index] /= "="THEN
          IF ((index MOD 4) = 1THEN
            buffer := (000);
            count := 1;
            buffer[count] := ABS(BIN((offset - 1) * 4) AND BIN 255{ shl 2 }
          ELIF ((index MOD 4) = 2THEN
            buffer[count] := buffer[count] + (offset - 1) % 16{ shr 4 }
            count +:= 1;
            buffer[count] := ABS(BIN ((buffer[count] + (offset - 1) * 16)) AND BIN 255{ shl 4 }
          ELIF ((index MOD 4) = 3THEN
            buffer[count] := buffer[count] + (offset - 1) % 4{ shr 2 }
            count +:= 1;
            buffer[count] := ABS(BIN((buffer[count] + (offset - 1) * 64)) AND BIN 255{ shl 6 }
          ELIF ((index MOD 4) = 0THEN
            buffer[count] := ABS(BIN(buffer[count] + (offset - 1)) AND BIN 255) ;
            FOR counter FROM 1 TO count DO
              output +:= REPR ABS buffer[counter]
            OD
          FI
        ELSE 
          count -:= 1;
          FOR counter FROM 1 TO count DO
            output +:= REPR ABS buffer[counter]
          OD;
          index := UPB text
        FI
      FI;
      index +:= 1
    OD;
    output
  END; {decode} 
 
  STRING text;
 
  text := "bWlrZTYzMnQud29yZHByZXNzLmNvbQ=";
 
  print (("""" + text + """"newlinenewline, decode (text), newlinenewline));
 
  text := "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"
          "IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg"
          "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu"
          "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo"
          "ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=";
 
  print (("""" + text + """"newlinenewline, decode (text), newlinenewline))
 
END
FINISH.

If I compile, link, and run the program I get the following output – though sadly not on a VT330!

$ algol decode
$ link decode
$ run decode
"bWlrZTYzMnQud29yZHByZXNzLmNvbQ="
 
mike632t.wordpress.com
 
"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGl
jaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmV
yYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="
 
Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by 
a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal plea
sure.
 

This entry was posted in Linux. Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.