home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 6_2008-2009.ISO / data / zips / Hotel_Mana21340511142008.psc / HMS / Class / clsHuffman.cls < prev   
Text File  |  2006-09-11  |  19KB  |  682 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "clsHuffman"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = True
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. 'Huffman Encoding/Decoding Class
  15. '-------------------------------
  16. '
  17. '(c) 2000, Fredrik Qvarfort
  18. '
  19.  
  20. Option Explicit
  21.  
  22. 'Progress Values for the encoding routine
  23. Private Const PROGRESS_CALCFREQUENCY = 7
  24. Private Const PROGRESS_CALCCRC = 5
  25. Private Const PROGRESS_ENCODING = 88
  26.  
  27. 'Progress Values for the decoding routine
  28. Private Const PROGRESS_DECODING = 89
  29. Private Const PROGRESS_CHECKCRC = 11
  30.  
  31. 'Events
  32. Event Progress(Procent As Integer)
  33. Event EncodeFinish()
  34. Event DecodeFinish()
  35.  
  36. Private Type HUFFMANTREE
  37.   ParentNode As Integer
  38.   RightNode As Integer
  39.   LeftNode As Integer
  40.   Value As Integer
  41.   Weight As Long
  42. End Type
  43.  
  44. Private Type ByteArray
  45.   Count As Byte
  46.   Data() As Byte
  47. End Type
  48.  
  49. Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
  50.  
  51. Public Sub EncodeFile(SourceFile As String, DestFile As String)
  52. On Error GoTo errh
  53.   Dim ByteArray() As Byte
  54.   Dim Filenr As Integer
  55.   
  56.   'Make sure the source file exists
  57.   If (Not FileExist(SourceFile)) Then
  58.     Err.Raise vbObjectError, "clsHuffman.EncodeFile()", "Source file does not exist"
  59.   End If
  60.   
  61.   'Read the data from the sourcefile
  62.   Filenr = FreeFile
  63.   Open SourceFile For Binary As #Filenr
  64.   ReDim ByteArray(0 To LOF(Filenr) - 1)
  65.   Get #Filenr, , ByteArray()
  66.   Close #Filenr
  67.   
  68.   'Compress the data
  69.   Call EncodeByte(ByteArray(), UBound(ByteArray) + 1)
  70.   
  71.   'If the destination file exist we need to
  72.   'destroy it because opening it as binary
  73.   'will not clear the old data
  74.   If (FileExist(DestFile)) Then Kill DestFile
  75.   
  76.   'Save the destination string
  77.   Open DestFile For Binary As #Filenr
  78.   Put #Filenr, , ByteArray()
  79.   Close #Filenr
  80.   
  81.   RaiseEvent EncodeFinish
  82.   'Call MsgBox("Your database is now Backed up and saved." & vbCrLf & "Remember to Back your database everyday.", vbInformation)
  83.  
  84. Exit Sub
  85.  
  86. errh:
  87. If Err.Number = 71 Then
  88. Call MsgBox("There is no discette in drive A:" & vbCrLf & "Please insert a disk to backup your data" & vbCrLf & Err.Description, vbExclamation)
  89. Else
  90. MsgBox Err.Number & vbCrLf & Err.Description
  91. End If
  92. End Sub
  93. Public Sub DecodeFile(SourceFile As String, DestFile As String)
  94.  
  95.   Dim ByteArray() As Byte
  96.   Dim Filenr As Integer
  97.   
  98.   'Make sure the source file exists
  99.   If (Not FileExist(SourceFile)) Then
  100.     Err.Raise vbObjectError, "clsHuffman.DecodeFile()", "Source file does not exist"
  101.   End If
  102.   
  103.   'Read the data from the sourcefile
  104.   Filenr = FreeFile
  105.   Open SourceFile For Binary As #Filenr
  106.   ReDim ByteArray(0 To LOF(Filenr) - 1)
  107.   Get #Filenr, , ByteArray()
  108.   Close #Filenr
  109.   
  110.   'Uncompress the data
  111.   Call DecodeByte(ByteArray(), UBound(ByteArray) + 1)
  112.   
  113.   'If the destination file exist we need to
  114.   'destroy it because opening it as binary
  115.   'will not clear the old data
  116.   If (FileExist(DestFile)) Then Kill DestFile
  117.   
  118.   
  119.   
  120.   
  121.   
  122.   'Save the destination string
  123.   Open DestFile For Binary As #Filenr
  124.   Put #Filenr, , ByteArray()
  125.   Close #Filenr
  126.     
  127.     RaiseEvent DecodeFinish
  128. End Sub
  129. Private Sub CreateTree(Nodes() As HUFFMANTREE, NodesCount As Long, Char As Long, Bytes As ByteArray)
  130.  
  131.   Dim a As Integer
  132.   Dim NodeIndex As Long
  133.   
  134.   NodeIndex = 0
  135.   For a = 0 To (Bytes.Count - 1)
  136.     If (Bytes.Data(a) = 0) Then
  137.       'Left node
  138.       If (Nodes(NodeIndex).LeftNode = -1) Then
  139.         Nodes(NodeIndex).LeftNode = NodesCount
  140.         Nodes(NodesCount).ParentNode = NodeIndex
  141.         Nodes(NodesCount).LeftNode = -1
  142.         Nodes(NodesCount).RightNode = -1
  143.         Nodes(NodesCount).Value = -1
  144.         NodesCount = NodesCount + 1
  145.       End If
  146.       NodeIndex = Nodes(NodeIndex).LeftNode
  147.     ElseIf (Bytes.Data(a) = 1) Then
  148.       'Right node
  149.       If (Nodes(NodeIndex).RightNode = -1) Then
  150.         Nodes(NodeIndex).RightNode = NodesCount
  151.         Nodes(NodesCount).ParentNode = NodeIndex
  152.         Nodes(NodesCount).LeftNode = -1
  153.         Nodes(NodesCount).RightNode = -1
  154.         Nodes(NodesCount).Value = -1
  155.         NodesCount = NodesCount + 1
  156.       End If
  157.       NodeIndex = Nodes(NodeIndex).RightNode
  158.     Else
  159.       Stop
  160.     End If
  161.   Next
  162.   
  163.   Nodes(NodeIndex).Value = Char
  164.  
  165. End Sub
  166. Public Sub EncodeByte(ByteArray() As Byte, ByteLen As Long)
  167.   
  168.   Dim i As Long
  169.   Dim j As Long
  170.   Dim Char As Byte
  171.   Dim BitPos As Byte
  172.   Dim lNode1 As Long
  173.   Dim lNode2 As Long
  174.   Dim lNodes As Long
  175.   Dim lLength As Long
  176.   Dim Count As Integer
  177.   Dim lWeight1 As Long
  178.   Dim lWeight2 As Long
  179.   Dim Result() As Byte
  180.   Dim ByteValue As Byte
  181.   Dim ResultLen As Long
  182.   Dim Bytes As ByteArray
  183.   Dim NodesCount As Integer
  184.   Dim NewProgress As Integer
  185.   Dim CurrProgress As Integer
  186.   Dim BitValue(0 To 7) As Byte
  187.   Dim CharCount(0 To 255) As Long
  188.   Dim Nodes(0 To 511) As HUFFMANTREE
  189.   Dim CharValue(0 To 255) As ByteArray
  190.   
  191.   'If the source string is empty or contains
  192.   'only one character we return it uncompressed
  193.   'with the prefix string "HEO" & vbCr
  194.   If (ByteLen = 0) Then
  195.     ReDim Preserve ByteArray(0 To ByteLen + 3)
  196.     If (ByteLen > 0) Then
  197.       Call CopyMem(ByteArray(4), ByteArray(0), ByteLen)
  198.     End If
  199.     ByteArray(0) = 72 '"H"
  200.     ByteArray(1) = 69 '"E"
  201.     ByteArray(2) = 48 '"0"
  202.     ByteArray(3) = 13 'vbCr
  203.     Exit Sub
  204.   End If
  205.   
  206.   'Create the temporary result array and make
  207.   'space for identifier, checksum, textlen and
  208.   'the ASCII values inside the Huffman Tree
  209.   ReDim Result(0 To 522)
  210.   
  211.   'Prefix the destination string with the
  212.   '"HE3" & vbCr identification string
  213.   Result(0) = 72
  214.   Result(1) = 69
  215.   Result(2) = 51
  216.   Result(3) = 13
  217.   ResultLen = 4
  218.   
  219.   'Count the frequency of each ASCII code
  220.   For i = 0 To (ByteLen - 1)
  221.     CharCount(ByteArray(i)) = CharCount(ByteArray(i)) + 1
  222.     If (i Mod 1000 = 0) Then
  223.       NewProgress = i / ByteLen * PROGRESS_CALCFREQUENCY
  224.       If (NewProgress <> CurrProgress) Then
  225.         CurrProgress = NewProgress
  226.         RaiseEvent Progress(CurrProgress)
  227.       End If
  228.     End If
  229.   Next
  230.   
  231.   'Create a leaf for each character
  232.   For i = 0 To 255
  233.     If (CharCount(i) > 0) Then
  234.       With Nodes(NodesCount)
  235.         .Weight = CharCount(i)
  236.         .Value = i
  237.         .LeftNode = -1
  238.         .RightNode = -1
  239.         .ParentNode = -1
  240.       End With
  241.       NodesCount = NodesCount + 1
  242.     End If
  243.   Next
  244.   
  245.   'Create the Huffman Tree
  246.   For lNodes = NodesCount To 2 Step -1
  247.     'Get the two leafs with the smallest weights
  248.     lNode1 = -1: lNode2 = -1
  249.     For i = 0 To (NodesCount - 1)
  250.       If (Nodes(i).ParentNode = -1) Then
  251.         If (lNode1 = -1) Then
  252.           lWeight1 = Nodes(i).Weight
  253.           lNode1 = i
  254.         ElseIf (lNode2 = -1) Then
  255.           lWeight2 = Nodes(i).Weight
  256.           lNode2 = i
  257.         ElseIf (Nodes(i).Weight < lWeight1) Then
  258.           If (Nodes(i).Weight < lWeight2) Then
  259.             If (lWeight1 < lWeight2) Then
  260.               lWeight2 = Nodes(i).Weight
  261.               lNode2 = i
  262.             Else
  263.               lWeight1 = Nodes(i).Weight
  264.               lNode1 = i
  265.             End If
  266.           Else
  267.             lWeight1 = Nodes(i).Weight
  268.             lNode1 = i
  269.           End If
  270.         ElseIf (Nodes(i).Weight < lWeight2) Then
  271.           lWeight2 = Nodes(i).Weight
  272.           lNode2 = i
  273.         End If
  274.       End If
  275.     Next
  276.     
  277.     'Create a new leaf
  278.     With Nodes(NodesCount)
  279.       .Weight = lWeight1 + lWeight2
  280.       .LeftNode = lNode1
  281.       .RightNode = lNode2
  282.       .ParentNode = -1
  283.       .Value = -1
  284.     End With
  285.     
  286.     'Set the parentnodes of the two leafs
  287.     Nodes(lNode1).ParentNode = NodesCount
  288.     Nodes(lNode2).ParentNode = NodesCount
  289.     
  290.     'Increase the node counter
  291.     NodesCount = NodesCount + 1
  292.   Next
  293.  
  294.   'Traverse the tree to get the bit sequence
  295.   'for each character, make temporary room in
  296.   'the data array to hold max theoretical size
  297.   ReDim Bytes.Data(0 To 255)
  298.   Call CreateBitSequences(Nodes(), NodesCount - 1, Bytes, CharValue)
  299.   
  300.   'Calculate the length of the destination
  301.   'string after encoding
  302.   For i = 0 To 255
  303.     If (CharCount(i) > 0) Then
  304.       lLength = lLength + CharValue(i).Count * CharCount(i)
  305.     End If
  306.   Next
  307.   lLength = IIf(lLength Mod 8 = 0, lLength \ 8, lLength \ 8 + 1)
  308.   
  309.   'If the destination is larger than the source
  310.   'string we leave it uncompressed and prefix
  311.   'it with a 4 byte header ("HE0" & vbCr)
  312.   If ((lLength = 0) Or (lLength > ByteLen)) Then
  313.     ReDim Preserve ByteArray(0 To ByteLen + 3)
  314.     Call CopyMem(ByteArray(4), ByteArray(0), ByteLen)
  315.     ByteArray(0) = 72
  316.     ByteArray(1) = 69
  317.     ByteArray(2) = 48
  318.     ByteArray(3) = 13
  319.     Exit Sub
  320.   End If
  321.   
  322.   'Add a simple checksum value to the result
  323.   'header for corruption identification
  324.   Char = 0
  325.   For i = 0 To (ByteLen - 1)
  326.     Char = Char Xor ByteArray(i)
  327.     If (i Mod 10000 = 0) Then
  328.       NewProgress = i / ByteLen * PROGRESS_CALCCRC + PROGRESS_CALCFREQUENCY
  329.       If (NewProgress <> CurrProgress) Then
  330.         CurrProgress = NewProgress
  331.         RaiseEvent Progress(CurrProgress)
  332.       End If
  333.     End If
  334.   Next
  335.   Result(ResultLen) = Char
  336.   ResultLen = ResultLen + 1
  337.   
  338.   'Add the length of the source string to the
  339.   'header for corruption identification
  340.   Call CopyMem(Result(ResultLen), ByteLen, 4)
  341.   ResultLen = ResultLen + 4
  342.   
  343.   'Create a small array to hold the bit values,
  344.   'this is faster than calculating on-fly
  345.   For i = 0 To 7
  346.     BitValue(i) = 2 ^ i
  347.   Next
  348.   
  349.   'Store the number of characters used
  350.   Count = 0
  351.   For i = 0 To 255
  352.     If (CharValue(i).Count > 0) Then
  353.       Count = Count + 1
  354.     End If
  355.   Next
  356.   Call CopyMem(Result(ResultLen), Count, 2)
  357.   ResultLen = ResultLen + 2
  358.   
  359.   'Store the used characters and the length
  360.   'of their respective bit sequences
  361.   Count = 0
  362.   For i = 0 To 255
  363.     If (CharValue(i).Count > 0) Then
  364.       Result(ResultLen) = i
  365.       ResultLen = ResultLen + 1
  366.       Result(ResultLen) = CharValue(i).Count
  367.       ResultLen = ResultLen + 1
  368.       Count = Count + 16 + CharValue(i).Count
  369.     End If
  370.   Next
  371.   
  372.   'Make room for the Huffman Tree in the
  373.   'destination byte array
  374.   ReDim Preserve Result(0 To ResultLen + Count \ 8)
  375.   
  376.   'Store the Huffman Tree into the result
  377.   'converting the bit sequences into bytes
  378.   BitPos = 0
  379.   ByteValue = 0
  380.   For i = 0 To 255
  381.     With CharValue(i)
  382.       If (.Count > 0) Then
  383.         For j = 0 To (.Count - 1)
  384.           If (.Data(j)) Then ByteValue = ByteValue + BitValue(BitPos)
  385.           BitPos = BitPos + 1
  386.           If (BitPos = 8) Then
  387.             Result(ResultLen) = ByteValue
  388.             ResultLen = ResultLen + 1
  389.             ByteValue = 0
  390.             BitPos = 0
  391.           End If
  392.         Next
  393.       End If
  394.     End With
  395.   Next
  396.   If (BitPos > 0) Then
  397.     Result(ResultLen) = ByteValue
  398.     ResultLen = ResultLen + 1
  399.   End If
  400.   
  401.   'Resize the destination string to be able to
  402.   'contain the encoded string
  403.   ReDim Preserve Result(0 To ResultLen - 1 + lLength)
  404.   
  405.   'Now we can encode the data by exchanging each
  406.   'ASCII byte for its appropriate bit string.
  407.   Char = 0
  408.   BitPos = 0
  409.   For i = 0 To (ByteLen - 1)
  410.     With CharValue(ByteArray(i))
  411.       For j = 0 To (.Count - 1)
  412.         If (.Data(j) = 1) Then Char = Char + BitValue(BitPos)
  413.         BitPos = BitPos + 1
  414.         If (BitPos = 8) Then
  415.           Result(ResultLen) = Char
  416.           ResultLen = ResultLen + 1
  417.           BitPos = 0
  418.           Char = 0
  419.         End If
  420.       Next
  421.     End With
  422.     If (i Mod 10000 = 0) Then
  423.       NewProgress = i / ByteLen * PROGRESS_ENCODING + PROGRESS_CALCCRC + PROGRESS_CALCFREQUENCY
  424.       If (NewProgress <> CurrProgress) Then
  425.         CurrProgress = NewProgress
  426.         RaiseEvent Progress(CurrProgress)
  427.       End If
  428.     End If
  429.   Next
  430.  
  431.   'Add the last byte
  432.   If (BitPos > 0) Then
  433.     Result(ResultLen) = Char
  434.     ResultLen = ResultLen + 1
  435.   End If
  436.   
  437.   'Return the destination in string format
  438.   ReDim ByteArray(0 To ResultLen - 1)
  439.   Call CopyMem(ByteArray(0), Result(0), ResultLen)
  440.  
  441.   'Make sure we get a "100%" progress message
  442.   If (CurrProgress <> 100) Then
  443.     RaiseEvent Progress(100)
  444.   End If
  445.  
  446. End Sub
  447. Public Function DecodeString(Text As String) As String
  448.   
  449.   Dim ByteArray() As Byte
  450.   
  451.   'Convert the string to a byte array
  452.   ByteArray() = StrConv(Text, vbFromUnicode)
  453.   
  454.   'Compress the byte array
  455.   Call DecodeByte(ByteArray, Len(Text))
  456.   
  457.   'Convert the compressed byte array to a string
  458.   DecodeString = StrConv(ByteArray(), vbUnicode)
  459.   
  460. End Function
  461. Public Function EncodeString(Text As String) As String
  462.   
  463.   Dim ByteArray() As Byte
  464.   
  465.   'Convert the string to a byte array
  466.   ByteArray() = StrConv(Text, vbFromUnicode)
  467.   
  468.   'Compress the byte array
  469.   Call EncodeByte(ByteArray, Len(Text))
  470.   
  471.   'Convert the compressed byte array to a string
  472.   EncodeString = StrConv(ByteArray(), vbUnicode)
  473.   
  474. End Function
  475.  
  476. Public Sub DecodeByte(ByteArray() As Byte, ByteLen As Long)
  477.   
  478.   Dim i As Long
  479.   Dim j As Long
  480.   Dim Pos As Long
  481.   Dim Char As Byte
  482.   Dim CurrPos As Long
  483.   Dim Count As Integer
  484.   Dim CheckSum As Byte
  485.   Dim Result() As Byte
  486.   Dim BitPos As Integer
  487.   Dim NodeIndex As Long
  488.   Dim ByteValue As Byte
  489.   Dim ResultLen As Long
  490.   Dim NodesCount As Long
  491.   Dim lResultLen As Long
  492.   Dim NewProgress As Integer
  493.   Dim CurrProgress As Integer
  494.   Dim BitValue(0 To 7) As Byte
  495.   Dim Nodes(0 To 511) As HUFFMANTREE
  496.   Dim CharValue(0 To 255) As ByteArray
  497.   
  498.   If (ByteArray(0) <> 72) Or (ByteArray(1) <> 69) Or (ByteArray(3) <> 13) Then
  499.     'The source did not contain the identification
  500.     'string "HE?" & vbCr where ? is undefined at
  501.     'the moment (does not matter)
  502.   ElseIf (ByteArray(2) = 48) Then
  503.     'The text is uncompressed, return the substring
  504.     'Decode = Mid$(Text, 5)
  505.     Call CopyMem(ByteArray(0), ByteArray(4), ByteLen - 4)
  506.     ReDim Preserve ByteArray(0 To ByteLen - 5)
  507.     Exit Sub
  508.   ElseIf (ByteArray(2) <> 51) Then
  509.     'This is not a Huffman encoded string
  510.     Err.Raise vbObjectError, "HuffmanDecode()", "The data either was not compressed with HE3 or is corrupt (identification string not found)"
  511.     Exit Sub
  512.   End If
  513.   
  514.   CurrPos = 5
  515.     
  516.   'Extract the checksum
  517.   CheckSum = ByteArray(CurrPos - 1)
  518.   CurrPos = CurrPos + 1
  519.   
  520.   'Extract the length of the original string
  521.   Call CopyMem(ResultLen, ByteArray(CurrPos - 1), 4)
  522.   CurrPos = CurrPos + 4
  523.   lResultLen = ResultLen
  524.   
  525.   'If the compressed string is empty we can
  526.   'skip the function right here
  527.   If (ResultLen = 0) Then Exit Sub
  528.   
  529.   'Create the result array
  530.   ReDim Result(0 To ResultLen - 1)
  531.   
  532.   'Get the number of characters used
  533.   Call CopyMem(Count, ByteArray(CurrPos - 1), 2)
  534.   CurrPos = CurrPos + 2
  535.   
  536.   'Get the used characters and their
  537.   'respective bit sequence lengths
  538.   For i = 1 To Count
  539.     With CharValue(ByteArray(CurrPos - 1))
  540.       CurrPos = CurrPos + 1
  541.       .Count = ByteArray(CurrPos - 1)
  542.       CurrPos = CurrPos + 1
  543.       ReDim .Data(0 To .Count - 1)
  544.     End With
  545.   Next
  546.   
  547.   'Create a small array to hold the bit values,
  548.   'this is (still) faster than calculating on-fly
  549.   For i = 0 To 7
  550.     BitValue(i) = 2 ^ i
  551.   Next
  552.   
  553.   'Extract the Huffman Tree, converting the
  554.   'byte sequence to bit sequences
  555.   ByteValue = ByteArray(CurrPos - 1)
  556.   CurrPos = CurrPos + 1
  557.   BitPos = 0
  558.   For i = 0 To 255
  559.     With CharValue(i)
  560.       If (.Count > 0) Then
  561.         For j = 0 To (.Count - 1)
  562.           If (ByteValue And BitValue(BitPos)) Then .Data(j) = 1
  563.           BitPos = BitPos + 1
  564.           If (BitPos = 8) Then
  565.             ByteValue = ByteArray(CurrPos - 1)
  566.             CurrPos = CurrPos + 1
  567.             BitPos = 0
  568.           End If
  569.         Next
  570.       End If
  571.     End With
  572.   Next
  573.   If (BitPos = 0) Then CurrPos = CurrPos - 1
  574.   
  575.   'Create the Huffman Tree
  576.   NodesCount = 1
  577.   Nodes(0).LeftNode = -1
  578.   Nodes(0).RightNode = -1
  579.   Nodes(0).ParentNode = -1
  580.   Nodes(0).Value = -1
  581.   For i = 0 To 255
  582.     Call CreateTree(Nodes(), NodesCount, i, CharValue(i))
  583.   Next
  584.   
  585.   'Decode the actual data
  586.   ResultLen = 0
  587.   For CurrPos = CurrPos To ByteLen
  588.     ByteValue = ByteArray(CurrPos - 1)
  589.     For BitPos = 0 To 7
  590.       If (ByteValue And BitValue(BitPos)) Then
  591.         NodeIndex = Nodes(NodeIndex).RightNode
  592.       Else
  593.         NodeIndex = Nodes(NodeIndex).LeftNode
  594.       End If
  595.       If (Nodes(NodeIndex).Value > -1) Then
  596.         Result(ResultLen) = Nodes(NodeIndex).Value
  597.         ResultLen = ResultLen + 1
  598.         If (ResultLen = lResultLen) Then GoTo DecodeFinished
  599.         NodeIndex = 0
  600.       End If
  601.     Next
  602.     If (CurrPos Mod 10000 = 0) Then
  603.       NewProgress = CurrPos / ByteLen * PROGRESS_DECODING
  604.       If (NewProgress <> CurrProgress) Then
  605.         CurrProgress = NewProgress
  606.         RaiseEvent Progress(CurrProgress)
  607.       End If
  608.     End If
  609.   Next
  610. DecodeFinished:
  611.  
  612.   'Verify data to check for corruption.
  613.   Char = 0
  614.   For i = 0 To (ResultLen - 1)
  615.     Char = Char Xor Result(i)
  616.     If (i Mod 10000 = 0) Then
  617.       NewProgress = i / ResultLen * PROGRESS_CHECKCRC + PROGRESS_DECODING
  618.       If (NewProgress <> CurrProgress) Then
  619.         CurrProgress = NewProgress
  620.         RaiseEvent Progress(CurrProgress)
  621.       End If
  622.     End If
  623.   Next
  624.   If (Char <> CheckSum) Then
  625.     Err.Raise vbObjectError, "clsHuffman.Decode()", "The data might be corrupted (checksum did not match expected value)"
  626.   End If
  627.  
  628.   'Return the uncompressed string
  629.   ReDim ByteArray(0 To ResultLen - 1)
  630.   Call CopyMem(ByteArray(0), Result(0), ResultLen)
  631.   
  632.   'Make sure we get a "100%" progress message
  633.   If (CurrProgress <> 100) Then
  634.     RaiseEvent Progress(100)
  635.   End If
  636.   
  637. End Sub
  638. Private Sub CreateBitSequences(Nodes() As HUFFMANTREE, ByVal NodeIndex As Integer, Bytes As ByteArray, CharValue() As ByteArray)
  639.  
  640.   Dim NewBytes As ByteArray
  641.   
  642.   'If this is a leaf we set the characters bit
  643.   'sequence in the CharValue array
  644.   If (Nodes(NodeIndex).Value > -1) Then
  645.     CharValue(Nodes(NodeIndex).Value) = Bytes
  646.     Exit Sub
  647.   End If
  648.   
  649.   'Traverse the left child
  650.   If (Nodes(NodeIndex).LeftNode > -1) Then
  651.     NewBytes = Bytes
  652.     NewBytes.Data(NewBytes.Count) = 0
  653.     NewBytes.Count = NewBytes.Count + 1
  654.     Call CreateBitSequences(Nodes(), Nodes(NodeIndex).LeftNode, NewBytes, CharValue)
  655.   End If
  656.   
  657.   'Traverse the right child
  658.   If (Nodes(NodeIndex).RightNode > -1) Then
  659.     NewBytes = Bytes
  660.     NewBytes.Data(NewBytes.Count) = 1
  661.     NewBytes.Count = NewBytes.Count + 1
  662.     Call CreateBitSequences(Nodes(), Nodes(NodeIndex).RightNode, NewBytes, CharValue)
  663.   End If
  664.   
  665. End Sub
  666.  
  667. Private Function FileExist(Filename As String) As Boolean
  668.  
  669.   On Error GoTo FileDoesNotExist
  670.   
  671.   Call FileLen(Filename)
  672.   FileExist = True
  673.   Exit Function
  674.   
  675. FileDoesNotExist:
  676.   FileExist = False
  677.   
  678. End Function
  679.  
  680.  
  681.  
  682.