Private Type SafeArray1D
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
cElements As Long
lLbound As Long
End Type
Private Const FADF_AUTO As Long = &H1
Private Const FADF_FIXEDSIZE As Long = &H10
' UnRem if not declared elsewhere
'Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dst As Any, src As Any, ByVal nBytes As Long)
'Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long
Public Function Compress07(Text As String, ByVal Comp As String, Optional Compare As VbCompareMethod = vbBinaryCompare) As String
' By Guy Gervais, ggervais@videotron.ca, 20 Nov 2001
' - Requires a reference to the Split03.tlb
Dim txt() As Integer
Dim SAtxt As SafeArray1D
Dim cmp() As Integer
Dim SAcmp As SafeArray1D
Dim ret() As Integer
Dim SAret As SafeArray1D
Dim iLtxt As Long
Dim iLcmp As Long
Dim iUBtxt As Long
Dim iUBcmp As Long
Dim iDiff As Long
Dim i As Long
Dim j As Long
Dim Ptr As Long
Dim iMatch As Long
Dim iPoison As Long
' Init
iLtxt = Len(Text)
iLcmp = Len(Comp)
If iLtxt = 0 Then Exit Function
If iLcmp = 0 Then
Compress07 = Text
Exit Function
End If
' Text
With SAtxt
.cDims = 1
.cbElements = 2&
.cElements = iLtxt
.fFeatures = FADF_AUTO Or FADF_FIXEDSIZE
.pvData = StrPtr(Text)
End With
CopyMemory ByVal VarPtrArray(txt), VarPtr(SAtxt), 4
iUBtxt = UBound(txt)
' Comp
With SAcmp
.cDims = 1
.cbElements = 2&
.cElements = iLcmp
.fFeatures = FADF_AUTO Or FADF_FIXEDSIZE
.pvData = StrPtr(Comp)
End With
CopyMemory ByVal VarPtrArray(cmp), VarPtr(SAcmp), 4
iUBcmp = UBound(cmp)
' Alloc return string
Compress07 = StringHelpers.SysAllocStringLen(ByVal 0&, iLtxt)
' Return
With SAret
.cDims = 1
.cbElements = 2&
.cElements = iLtxt
.fFeatures = FADF_AUTO Or FADF_FIXEDSIZE
.pvData = StrPtr(Compress07)
End With
CopyMemory ByVal VarPtrArray(ret), VarPtr(SAret), 4
iDiff = iUBtxt - iUBcmp
Ptr = 0
iPoison = -1
If Compare Then
' Switch Comp string to Uppercase
For i = 0 To iUBcmp
Select Case cmp(i)
Case 97 To 122, 224 To 246, 248 To 254
cmp(i) = cmp(i) And 223&
End Select
Next
' Text compress
For i = 0 To iUBtxt
Select Case txt(i)
Case 97 To 122, 224 To 246, 248 To 254
iMatch = ((txt(i) And 223&) = cmp(0))
Case Else
iMatch = (txt(i) = cmp(0))
End Select
If iMatch Then
If iLcmp > 1 Then
' Check for complete match
For j = 1 To iUBcmp
Select Case txt(i + j)
Case 97 To 122, 224 To 246, 248 To 254
If (txt(i + j) And 223&) <> cmp(j) Then GoTo TxtSkip
Case Else
If txt(i + j) <> cmp(j) Then GoTo TxtSkip
End Select
Next
Else
' Special optimization when Len(Comp) = 1
Do
If i = iDiff Then
i = i + 1
Exit Do
End If
i = i + 1
Select Case txt(i)
Case 97 To 122, 224 To 246, 248 To 254
If (txt(i) And 223&) <> cmp(0) Then Exit Do
Case Else
If txt(i) <> cmp(0) Then Exit Do
End Select
Loop
i = i - 1
End If
If i = iPoison Then
Ptr = Ptr - iLcmp
End If
If iPoison <= i Then iPoison = i + iLcmp
End If
TxtSkip:
ret(Ptr) = txt(i)
Ptr = Ptr + 1
Next
Else
' Binary compress
For i = 0 To iUBtxt
If (txt(i) = cmp(0)) Then
If iLcmp > 1 Then
' Check for complete match
If i <= iDiff Then
For j = 1 To iUBcmp
If txt(i + j) <> cmp(j) Then GoTo BinSkip
Next
Else
GoTo BinSkip
End If
Else
' Special optimization when Len(Comp) = 1
Do
If i = iDiff Then
i = i + 1
Exit Do
End If
i = i + 1
If txt(i) <> cmp(0) Then Exit Do
Loop
i = i - 1
End If
If i = iPoison Then
Ptr = Ptr - iLcmp
End If
If iPoison <= i Then iPoison = i + iLcmp
End If
BinSkip:
ret(Ptr) = txt(i)
Ptr = Ptr + 1
Next
End If
' Clean up
SAtxt.pvData = 0
SAcmp.pvData = 0
SAret.pvData = 0
' Trim
Compress07 = Left$(Compress07, Ptr)
End Function
|