Attribute VB_Name = "yEnc"
Option Explicit

Public Function yEncode(sString As String, Optional iPrefLen As Integer = 128) As String

    Dim bOut() As Byte, bIn() As Byte, lChar As Long, lPos As Long, bTest As Byte, lLine As Long
    
    If iPrefLen < 60 Then iPrefLen = 60     'Enforce max and min line lengths.
    If iPrefLen > 254 Then iPrefLen = 254
    
    bIn = StrConv(sString, vbFromUnicode)   'Load the input string.
    ReDim bOut(UBound(bIn) * 2)             'Make the output buffer.  Double size will almost always be enough.  2 extra
                                            'chars per 72 and worst case would be all characters escaped.  If so, use Base64.
    For lChar = 0 To UBound(bIn)
        bTest = (bIn(lChar) + 42) Mod 256   'Try the prefered transform.
        Select Case bTest
            Case 1 To 8, 11 To 12, 14 To 45, 47 To 60, 62 To 255    'Normal processing
                bOut(lPos) = bTest
                lPos = lPos + 1
                lLine = lLine + 1
            Case 46                         'Test for column one, escape if in that col.
                If lLine <> 0 Then
                    bOut(lPos) = bTest
                    lPos = lPos + 1
                    lLine = lLine + 1
                Else
                    bOut(lPos) = 61
                    bOut(lPos + 1) = (bTest + 64) Mod 256
                    lPos = lPos + 2
                    lLine = lLine + 2
                End If
            Case Else                       'Critical char, needs to be escaped.
                bOut(lPos) = 61
                bOut(lPos + 1) = (bTest + 64) Mod 256
                lPos = lPos + 2
                lLine = lLine + 2
        End Select
        If lLine >= iPrefLen Then           'Add a vbCrLf
            bOut(lPos) = 13
            bOut(lPos + 1) = 10
            lPos = lPos + 2
            lLine = 0
        End If
    Next lChar
    
    ReDim Preserve bOut(lPos - 1)           'Truncate the unused portion of the buffer.
    yEncode = StrConv(bOut, vbUnicode)      'Convert back to a string and return it.
    
End Function

Public Function yDecode(sString As String) As String

    Dim bOut() As Byte, bIn() As Byte, bTest As Byte, bEscaped As Boolean, lPos As Long, lChar As Long

    sString = Replace(sString, vbCr, vbNullString)      'Get rid of the vbCrLfs.  These could be in...
    sString = Replace(sString, vbLf, vbNullString)      'either order.

    bIn = StrConv(sString, vbFromUnicode)               'Load the input byte array.
    ReDim bOut(UBound(bIn))                             'There is no case where the output will be larger.
    
    For lChar = 0 To UBound(bIn)
        If bIn(lChar) <> 61 Then
            bTest = ((bIn(lChar) + 256) - 42) Mod 256
            If bEscaped Then
                bTest = ((bTest + 256) - 64) Mod 256
                bEscaped = False
            End If
            bOut(lPos) = bTest
            lPos = lPos + 1
        Else
            bEscaped = True
        End If
    Next lChar

    ReDim Preserve bOut(lPos - 1)                       'Truncate the unused portion of the buffer.
    yDecode = StrConv(bOut, vbUnicode)                  'Convert back to a string and return.

End Function
