Task: Base64 decode data





Java: 
module Base64
    {
    @Inject Console console;
    void run()
        {
        String orig  = \|VG8gZXJyIGlzIGh1bWFuLCBidXQgdG8gcmVhbGx5IGZvdWwgdGhpbmdzIHVwIH\
                        |lvdSBuZWVkIGEgY29tcHV0ZXIuCiAgICAtLSBQYXVsIFIuIEVocmxpY2g=
                       ;
        Byte[] bytes = decode(orig);
        String text  = encode(bytes, pad=True);
        assert text == orig;
        console.print($"base64={text}, bytes={bytes}");
        }

    static Byte[] read(Iterator<Char> stream)
        {
        Int    charLen    = 0;
        charLen := stream.knownSize();
        Byte[] byteBuf    = new Byte[](charLen * 6 / 8);
        Byte   prevBits   = 0;
        Int    prevCount  = 0;
        while (Char ch := stream.next())
            {
            if (Byte newBits := isBase64(ch, assertTrash=True))
                {
                if (prevCount == 0)
                    {
                    prevBits  = newBits;
                    prevCount = 6;
                    }
                else
                    {
                    byteBuf.add((prevBits << 8-prevCount) | (newBits >> prevCount-2));
                    prevBits   = newBits;
                    prevCount -= 2;
                    }
                }
            }

        return byteBuf.freeze(True);
        }

    static void write(Byte[] value, Appender<Char> stream, Boolean pad=False, Int? lineLength=Null)
        {
        lineLength ?:= Int.maxvalue;

        Int    lineOffset = 0;
        Int    totalChars = 0;
        Byte   prevByte   = 0;
        Int    prevCount  = 0;          
        Int    byteOffset = 0;
        Int    byteLength = value.size;
        while (True)
            {
            
            Byte sixBits;
            if (byteOffset >= byteLength)
                {
                if (prevCount == 0)
                    {
                    break;
                    }
                sixBits   = prevByte << 6 - prevCount;
                prevCount = 0;
                }
            else if (prevCount == 6)
                {
                sixBits   = prevByte << 6 - prevCount;
                prevCount = 0;
                }
            else
                {
                Byte nextByte = value[byteOffset++];
                sixBits    = (prevByte << 6 - prevCount) | (nextByte >> 2 + prevCount);
                prevByte   = nextByte;
                prevCount += 2;
                }

            if (lineOffset >= lineLength)
                {
                stream.add('\r').add('\n');
                totalChars += lineOffset;
                lineOffset  = 0;
                }

            stream.add(base64(sixBits & 0b111111));
            ++lineOffset;
            }

        if (pad)
            {
            totalChars += lineOffset;
            for (Int i = 0, Int padCount = 4 - (totalChars & 0b11) & 0b11; i < padCount; ++i)
                {
                if (lineOffset >= lineLength)
                    {
                    stream.add('\r').add('\n');
                    lineOffset  = 0;
                    }

                stream.add('=');
                ++lineOffset;
                }
            }
        }

    static String encode(Byte[] value, Boolean pad=False, Int? lineLength=Null)
        {
        
        Int byteLen = value.size;
        Int charLen = (byteLen * 8 + 5) / 6;
        if (pad)
            {
            charLen += 4 - (charLen & 0b11) & 0b11;
            }
        if (lineLength != Null)
            {
            charLen += ((charLen + lineLength - 1) / lineLength - 1).maxOf(0) * 2;
            }

        StringBuffer charBuf = new StringBuffer(charLen);
        write(value, charBuf, pad, lineLength);
        return charBuf.toString();
        }

    static Byte[] decode(String text)
        {
        Int    charLen    = text.size;
        Byte[] byteBuf    = new Byte[](charLen * 6 / 8);
        Byte   prevBits   = 0;
        Int    prevCount  = 0;
        for (Int offset = 0; offset < charLen; ++offset)
            {
            if (Byte newBits := isBase64(text[offset], assertTrash=True))
                {
                if (prevCount == 0)
                    {
                    prevBits  = newBits;
                    prevCount = 6;
                    }
                else
                    {
                    byteBuf.add((prevBits << 8-prevCount) | (newBits >> prevCount-2));
                    prevBits   = newBits;
                    prevCount -= 2;
                    }
                }
            }

        return byteBuf.freeze(True);
        }

    
    static Byte valOf(Char ch)
        {
        return switch (ch)
            {
            case 'A'..'Z': (ch - 'A').toUInt8();
            case 'a'..'z': (ch - 'a').toUInt8() + 26;
            case '0'..'9': (ch - '0').toUInt8() + 52;
            case '+': 62;
            case '/': 63;

            case '=':        assert as $"Unexpected padding character in Base64: {ch.quoted()}";
            case '\r', '\n': assert as $"Unexpected newline character in Base64: {ch.quoted()}";
            default:         assert as $"Invalid Base64 character: {ch.quoted()}";
            };
        }

    
    static conditional Byte isBase64(Char ch, Boolean assertTrash=False)
        {
        return switch (ch)
            {
            case 'A'..'Z': (True, (ch - 'A').toUInt8());
            case 'a'..'z': (True, (ch - 'a').toUInt8() + 26);
            case '0'..'9': (True, (ch - '0').toUInt8() + 52);
            case '+': (True, 62);
            case '/': (True, 63);

            case '=':           
            case '\r', '\n':    
                False;

            default: assertTrash ? assert as $"Invalid Base64 character: {ch.quoted()}" : False;
            };
        }

    
    static Char base64(Byte byte)
        {
        return switch (byte)
            {
            case  0 ..< 26: 'A'+byte;
            case 26 ..< 52: 'a'+(byte-26);
            case 52 ..< 62: '0'+(byte-52);
            case 62: '+';
            case 63: '/';
            default: assert:bounds as $"byte={byte}";
            };
        }
    }




VB: Option _Explicit

Dim As String udata, decoded
udata = "VG8gZXJyIGlzIGh1bWFuLCBidXQgdG8gcmVhbGx5IGZvdWwgdGhpbmdzIHVwIHlvdSBuZWVkIGEgY29tcHV0ZXIuCiAgICAtLVBhdWwgUi5FaHJsaWNo"

decoded = decode(udata)

Print udata
Print decoded

Function findIndex& (value As _Unsigned _Byte)
    If Asc("A") <= value And value <= Asc("Z") Then
        findIndex = value - Asc("A")
        Exit Function
    End If
    If Asc("a") <= value And value <= Asc("z") Then
        findIndex = value - Asc("a") + 26
        Exit Function
    End If
    If Asc("0") <= value And value <= Asc("9") Then
        findIndex = value - Asc("0") + 52
        Exit Function
    End If
    If value = Asc("+") Then
        findIndex = 62
        Exit Function
    End If
    If value = Asc("/") Then
        findIndex = 63
        Exit Function
    End If
    findIndex = -1
End Function

Function encode$ (source As String)
    Dim As String Base64: Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    Dim As _Unsigned _Integer64 length: length = Len(source)
    Dim As _Unsigned _Integer64 it, strend
    Dim As Long acc
    Dim As String sink
    strend = length
    While it <> strend
        Dim As _Unsigned _Byte b1, b2, b3, b4
        it = it + 1
        b1 = Asc(Mid$(source, it, 1))
        sink = sink + Mid$(Base64, _SHR(b1, 2), 1)
        acc = _SHL(b1 And &H3, 4)
        If it <> strend Then
            it = it + 1
            b2 = Asc(Mid$(source, it, 1))
            acc = acc Or _SHR(b2, 4)
            sink = sink + Mid$(Base64, acc, 1)
            acc = _SHL(b2 And &HF, 2)
            If it <> strend Then
                it = it + 1
                b3 = Asc(Mid$(source, it, 1))
                acc = acc Or _SHR(b3, 6)
                sink = sink + Mid$(Base64, acc, 1)
                sink = sink + Mid$(Base64, b3 And &H3F, 1)
            Else
                sink = sink + Mid$(Base64, acc, 1)
                sink = sink + "="
            End If
        Else
            sink = sink + Mid$(Base64, acc, 1)
            sink = sink + "="
            sink = sink + "="
        End If
    Wend
    encode = sink
End Function

Function decode$ (source As String)
    Dim As _Unsigned _Integer64 length: length = Len(source)
    Dim As _Unsigned _Integer64 it, strend
    Dim As Long acc
    Dim As String sink
    strend = length
    While it <> strend
        Dim As _Unsigned _Byte b1, b2, b3, b4
        it = it + 1
        b1 = Asc(Mid$(source, it, 1))
        it = it + 1
        b2 = Asc(Mid$(source, it, 1))
        it = it + 1
        b3 = Asc(Mid$(source, it, 1))
        it = it + 1
        b4 = Asc(Mid$(source, it, 1))
        Dim As Long i1, i2
        i1 = findIndex(b1)
        i2 = findIndex(b2)
        acc = _SHL(i1, 2)
        acc = acc Or _SHR(i2, 4)
        sink = sink + Chr$(acc)
        If b3 <> Asc("=") Then
            Dim As Long i3
            i3 = findIndex(b3)
            acc = _SHL(i2 And &HF, 4)
            acc = acc Or _SHR(i3, 2)
            sink = sink + Chr$(acc)
            If b4 <> Asc("=") Then
                Dim As Long i4
                i4 = findIndex(b4)
                acc = _SHL(i3 And &H3, 6)
                acc = acc Or i4
                sink = sink + Chr$(acc)
            End If
        End If
    Wend
    decode = sink
End Function