%SHIFT85 = 33 '// Ascii85 轮班编码字节由 33 将它们移到可接受的范围内的 ASCII 字符集
Function DivideEx(dwRemainder As Dword, ByVal dwDividend As Dword, ByVal dwDivisor As Dword) As Dword
#REGISTER None
! mov ebx, dwRemainder
! mov edx, 0
! mov eax, dwDividend
! mov ecx, dwDivisor
! div ecx
! mov Dword Ptr [ebx], edx
! mov Function, eax
End Function
Function SafeAsc85Str(sBuf As String) As String '// 返回仅包含有效的 Ascii85 编码字符,再加上页眉 & 页脚剥离的 sBuf 的安全版本
#REGISTER All
Local bPtr As Byte Ptr, i, lEnd As Long, sOut As String
If Len(sBuf) = 0 Then Exit Function
If Left$(sBuf, 2) = "<~" Then
i = 3: bPtr = StrPtr(sBuf) + 2
Else
i = 1: bPtr = StrPtr(sBuf)
End If
If Right$(sBuf,2) = "~>" Then lEnd = Len(sBuf) - 2 Else lEnd = Len(sBuf)
For i = i To lEnd
If (@bPtr => 33 And @bPtr <= 117) Or @bPtr = 122 Then sOut = sOut & Chr$(@bPtr) '// 有效的字符
Incr bPtr
Next i
Function = sOut
End Function
Function Bin4toA85 (sBufMax4 As String) As String '// 编码 4 个字节,则返回一个 1 5 字节的字符串
#REGISTER None
Register dwBlock As Dword
Local b, lPad, dwRemainder As Long, sIn4 As String, sOut5 As String
If Len(sBufMax4) = 0 Or Len(sBufMax4) > 4 Then Exit Function '无效的输入的大小
sIn4 = sBufMax4
lPad = 4 - (Len(sIn4) Mod 4)
If lPad < 4 Then sIn4 = sIn4 & Left$(Chr$(0,0,0), lPad)
dwBlock = CvDwd(sIn4)
If dwBlock = &h00000000 And lPad = 4 Then
Function = "z": Exit Function
Else
sOut5 = ""
! mov eax, dwBlock ;/
! bswap eax ;| change dwBlock to big-endian
! mov dwBlock, eax ;\
For b = 1 To 5
dwBlock = DivideEx(ByVal VarPtr(dwRemainder), ByVal dwBlock, 85)
sOut5 = Chr$(dwRemainder + %SHIFT85) & sOut5
Next b
End If
If lPad < 4 Then sOut5 = Left$(sOut5, 5 - lPad)
Function = sOut5
End Function
Function A85toBin4 (sEncMax5 As String) As String '// 解码 5 个字节,则返回一个 1 到 4 字节的字符串
#REGISTER None
Register i As Long, dwBlock As Dword
Local sOut, sIn5, sTmp As String, bPtr As Byte Ptr, b, lPad As Long
If Len(sEncMax5) = 0 Or Len(sEncMax5) > 5 Then Exit Function '无效的输入的大小
sIn5 = sEncMax5
If Left$(sIn5,1) = "z" Then Function = MkDwd$(&h00000000): Exit Function
lPad = 5 - Len(sIn5)
If lPad > 0 Then sIn5 = Left$(sIn5 & "uuuuu", 5)
bPtr = StrPtr(sIn5) + 4
dwBlock = @bPtr - %SHIFT85
For b = 1 To 4
Decr bPtr
dwBlock = dwBlock + ((@bPtr - %SHIFT85) * (85 ^ b))
Next b
! mov eax, dwBlock ;/
! bswap eax ;| revert dwBlock to little-endian
! mov dwBlock, eax ;\
If lPad > 0 Then sOut = sOut & Left$(MkDwd$(dwBlock), 4 - lPad) Else sOut = sOut & MkDwd$(dwBlock)
Function = sOut
End Function
'### MAIN WRAPPER FUNCTIONS ################################################################################
Function Ascii85Encode (sDataIn As String) As String '编码
Local sEnc As String, i As Long
If Len(sDataIn) = 0 Then Exit Function
i = 1
Do Until i > Len(sDataIn)
sEnc = sEnc & Bin4toA85( Mid$(sDataIn, i, 4) )
i = i + 4
Loop
Function = "<~" & sEnc & "~>"
End Function
Function Ascii85Decode (ByVal sDataIn As String) As String ' 解码
Local sDec As String, i As Long, sData As String
If Len(sDataIn) = 0 Then Exit Function
sData = SafeAsc85Str(sDataIn)
i = 1
Do Until i > Len(sData)
If Mid$(sData,i,1) = "z" Then
sDec = sDec & MkDwd$(&h00000000)
Incr i
Else
sDec = sDec & A85toBin4( Mid$(sData, i, 5) )
i = i + 5
End If
Loop
Function = sDec
End Function