【字符】 Base85 编码 & 解码

  勇芳 2017-4-5 10216

%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


因国家互联网安全管理要求,关闭回帖功能。大家需要留言,请使用【勇芳软件客服】即时联系勇芳点此打开->>勇芳软件客服
返回
联系勇芳
发新帖 搜索 反馈 回顶部