修改后的LZ77压缩解压源码

修改后的LZ77压缩解压源码
    这份代码跟 上一次相比,修正了以下部分:

    1、可修改的Window Size。压缩流会把Window Size写进去,解压流能够自动获取。
    2、发现冗余的地方,每一个标记的压缩块节省了一位。
    3、如果用户一次性写入的字节不够多则会缓存起来,上一版本则是直接压缩完。这样会丢失某些原本可以压缩的数据,因此修正。

    这次修改主要用于缩小压缩后的数据的尺寸。

    头文件:
  1  /* ******************************************************************************
  2  Vczh Library++ 2.0
  3  数据结构::压缩流
  4  开发者:陈梓瀚
  5 
  6  接口:
  7  类:
  8    VL_CompressedStream                    :压缩流
  9    VL_LZ77Stream                            :LZ77压缩流
 10    VL_LZWStream                            :LZW压缩流
 11    VL_HuffmanStream                        :Canonical Huffman压缩流
 12  函数:
 13  ****************************************************************************** */
 14  #ifndef VL_COMPRESSION
 15  #define  VL_COMPRESSION
 16 
 17  #include  " VL_Stream.h "
 18  #include  " VL_DataAccess.h "
 19 
 20  namespace  vl
 21  {
 22       namespace  stream
 23      {
 24           using   namespace  collection;
 25 
 26  /* ********************************************************************************************************
 27  压缩流
 28  ******************************************************************************************************** */
 29 
 30           class  VL_CompressedStream :  public  VL_Base ,  public  IVL_Stream
 31          {
 32           public :
 33               enum  VLE_OpenMode
 34              {
 35                  vomRead,
 36                  vomWrite,
 37              };
 38 
 39               class  Compressor :  public  IVL_Interface
 40              {
 41               public :
 42                   virtual   void             SetStream(IVL_Stream *  Stream) = 0 ;
 43                   virtual  VInt            Write(VPointer Data , VInt ByteCount) = 0 ;
 44              };
 45 
 46               class  Decompressor :  public  IVL_Interface
 47              {
 48               public :
 49                   virtual   void             SetStream(IVL_Stream *  Stream) = 0 ;
 50                   virtual  VInt            Read(VPointer Data , VInt ByteCount) = 0 ;
 51              };
 52           protected :
 53              IVL_Stream *                     FStream;
 54              VBool                        FOwned;
 55              VLE_OpenMode                FMode;
 56              VSize                        FPosition;
 57              Compressor *                     FCompressor;
 58              Decompressor *                 FDecompressor;
 59 
 60              VBuffer                        FPeekBuffer;
 61              VInt                        FPeekBufferSize;
 62              VInt                        FAvailablePeekSize;
 63 
 64               void                         Init(IVL_Stream *  Stream , VBool Owned , Compressor *  aCompressor);
 65               void                         Init(IVL_Stream *  Stream , VBool Owned , Decompressor *  aDecompressor);
 66 
 67              VL_CompressedStream();
 68           public :
 69               ~ VL_CompressedStream();
 70 
 71              VBool                        CanRead();
 72              VBool                        CanPeek();
 73              VBool                        CanWrite();
 74              VBool                        CanClose();
 75              VBool                        CanSeek();
 76              VBool                        CanGrow();
 77              VInt                        Read(VPointer Data , VInt ByteCount);
 78              VInt                        Peek(VPointer Data , VInt ByteCount);
 79              VInt                        Write(VPointer Data , VInt ByteCount);
 80               void                         Close();
 81              VBool                        IsAvailable();
 82              VSize                        Position();
 83              VSize                        Size();
 84              VSize                        MaxWriteSize();
 85               void                         SeekFromBegin(VSize Offset);
 86               void                         SeekFromEnd(VSize Offset);
 87               void                         Seek(VSize Offset);
 88              VBool                        IsEnd();
 89          };
 90 
 91           class  VL_LZ77Stream :  public  VL_CompressedStream
 92          {
 93           public :
 94               enum  VLE_WindowMode
 95              {
 96                  vwm128 = 7 ,
 97                  vwm256,
 98                  vwm512,
 99                  vwm1024,
100                  vwm2048,
101                  vwmAuto = 0 ,
102                  vwmMin = vwm128,
103                  vwmMax = vwm2048
104 
105              };
106 
107              VL_LZ77Stream(IVL_Stream *  Stream , VLE_OpenMode OpenMode , VLE_WindowMode WindowMode = vwmAuto , VBool Owned = false );
108          };
109 
110  /* ********************************************************************************************************
111  LZ77压缩算法
112 
113  第一个字节:window level, window size = 2 ^ window level
114  压缩块描述:
115  [0:wild][A:byte count-1][data]
116  [1:encoded][A:byte count-1][B:index]
117  A : 0 - (WindowSize-1)
118  B : 0 - (WindowSize-1)
119  ******************************************************************************************************** */
120 
121           namespace  LZ77Algorithms
122          {
123               class  AlgorithmBase :  public  VL_Base
124              {
125               protected :
126 
127                  VInt                        WindowSize;
128                  VInt                        MaxBlockSize;
129                  VInt                        DoubleMaxBlockSize;
130                  VInt                        ByteCountBitCount;
131                  VInt                        ByteIndexBitCount;
132 
133                  VBuffer                        FWindow;                     /* 滑动窗口,尺寸=WindowSize*3 */
134                  VSize                        FPosition;                     /* 当前位置 */
135                  VInt                        FUsedWindowSize;             /* 窗口有效数据大小 */
136                  VSize                        FWindowStartPosition;         /* 窗口的起始位置 */
137 
138                  AlgorithmBase(VInt WindowSizeLevel);                     /* 窗口尺寸为2的WindowSizeLevel次方 */
139                   ~ AlgorithmBase();
140              };
141 
142               class  Compressor :  public  AlgorithmBase ,  public  VL_CompressedStream::Compressor
143              {
144               protected :
145                  VL_BitWriter *                 FBitWriter;
146                  VInt                        FUsedFullWindowSize;         /* 缓冲区有效数据大小 */
147 
148                  VInt                        CompressAndWrite(VInt ByteCount);
149               public :
150                  Compressor(VInt WindowSizeLevel);
151                   ~ Compressor();
152 
153                   void                         SetStream(IVL_Stream *  Stream);
154                  VInt                        Write(VPointer Data , VInt ByteCount);
155              };
156 
157               class  Decompressor :  public  AlgorithmBase ,  public  VL_CompressedStream::Decompressor
158              {
159               protected :
160                  VL_BitReader *                 FReader;
161 
162                  VInt                        DecompressBlock();
163               public :
164                  Decompressor(VInt WindowSizeLevel);
165                   ~ Decompressor();
166 
167                   void                         SetStream(IVL_Stream *  Stream);
168                  VInt                        Read(VPointer Data , VInt ByteCount);
169              };
170 
171          }
172      }
173  }
174 
175  #endif

    实现文件:
  1  #include  " VL_Compression.h "
  2 
  3  namespace  vl
  4  {
  5       namespace  stream
  6      {
  7 
  8  /* ********************************************************************************************************
  9  VL_CompressedStream
 10  ******************************************************************************************************** */
 11 
 12           void  VL_CompressedStream::Init(IVL_Stream *  Stream , VBool Owned , Compressor *  aCompressor)
 13          {
 14              FStream = Stream;
 15              FOwned = Owned;
 16              FMode = vomWrite;
 17              FCompressor = aCompressor;
 18              FCompressor -> SetStream(FStream);
 19              FDecompressor = 0 ;
 20          }
 21 
 22           void  VL_CompressedStream::Init(IVL_Stream *  Stream , VBool Owned , Decompressor *  aDecompressor)
 23          {
 24              FStream = Stream;
 25              FOwned = Owned;
 26              FMode = vomRead;
 27              FCompressor = 0 ;
 28              FDecompressor = aDecompressor;
 29              FDecompressor -> SetStream(FStream);
 30          }
 31 
 32          VL_CompressedStream::VL_CompressedStream()
 33          {
 34              FStream = 0 ;
 35              FOwned = false ;
 36              FPosition = 0 ;
 37 
 38              FPeekBuffer = 0 ;
 39              FPeekBufferSize = 0 ;
 40              FAvailablePeekSize = 0 ;
 41          }
 42 
 43          VL_CompressedStream:: ~ VL_CompressedStream()
 44          {
 45              Close();
 46          }
 47 
 48          VBool VL_CompressedStream::CanRead()
 49          {
 50               return  IsAvailable()  &&  (FMode == vomRead)  &&  FStream -> CanRead();
 51          }
 52 
 53          VBool VL_CompressedStream::CanPeek()
 54          {
 55               return  IsAvailable()  &&  (FMode == vomRead)  &&  FStream -> CanRead();
 56          }
 57 
 58          VBool VL_CompressedStream::CanWrite()
 59          {
 60               return  IsAvailable()  &&  (FMode == vomWrite)  &&  FStream -> CanWrite();
 61          }
 62 
 63          VBool VL_CompressedStream::CanClose()
 64          {
 65               return  IsAvailable()  &&  FStream -> CanClose();
 66          }
 67 
 68          VBool VL_CompressedStream::CanSeek()
 69          {
 70               return   false ;
 71          }
 72 
 73          VBool VL_CompressedStream::CanGrow()
 74          {
 75               return  CanWrite();
 76          }
 77 
 78          VInt VL_CompressedStream::Read(VPointer Data , VInt ByteCount)
 79          {
 80               if (CanRead())
 81              {
 82                   if ( ! FAvailablePeekSize)
 83                  {
 84                      ByteCount = FDecompressor -> Read(Data,ByteCount);
 85                      FPosition += ByteCount;
 86                       return  ByteCount;
 87                  }
 88                   else   if (FAvailablePeekSize >= ByteCount)
 89                  {
 90                      memcpy(Data,FPeekBuffer,ByteCount);
 91                      FAvailablePeekSize -= ByteCount;
 92                      memmove(FPeekBuffer,FPeekBuffer + ByteCount,FAvailablePeekSize);
 93                      FPosition += ByteCount;
 94                       return  ByteCount;
 95                  }
 96                   else
 97                  {
 98                      VBuffer DataBuffer = (VBuffer)Data;
 99                      memcpy(DataBuffer,FPeekBuffer,FAvailablePeekSize);
100                      ByteCount = FAvailablePeekSize + FDecompressor -> Read(DataBuffer + FAvailablePeekSize,ByteCount - FAvailablePeekSize);
101                      FAvailablePeekSize = 0 ;
102                      FPosition += ByteCount;
103                       return  ByteCount;
104                  }
105              }
106               else
107              {
108                   return   - 1 ;
109              }
110          }
111 
112          VInt VL_CompressedStream::Peek(VPointer Data , VInt ByteCount)
113          {
114               if (CanPeek())
115              {
116                  VInt ExtendSize = ByteCount - FAvailablePeekSize;
117                   if (ExtendSize > 0 )
118                  {
119                       if (FPeekBufferSize < ByteCount)
120                      {
121                          VBuffer NewPeekBuffer = new  VByte[ByteCount];
122                           if (FPeekBuffer)
123                          {
124                              memcpy(NewPeekBuffer,FPeekBuffer,FAvailablePeekSize);
125                              delete[] FPeekBuffer;
126                          }
127                          FPeekBuffer = NewPeekBuffer;
128                          FPeekBufferSize = ByteCount;
129                      }
130                      FAvailablePeekSize += FDecompressor -> Read(FPeekBuffer + FAvailablePeekSize,ExtendSize);
131                  }
132                   if (FAvailablePeekSize < ByteCount)
133                  {
134                      ByteCount = FAvailablePeekSize;
135                  }
136                  memcpy(Data,FPeekBuffer,ByteCount);
137                   return  ByteCount;
138              }
139               else
140              {
141                   return   - 1 ;
142              }
143          }
144 
145          VInt VL_CompressedStream::Write(VPointer Data , VInt ByteCount)
146          {
147               if (CanWrite())
148              {
149                  ByteCount = FCompressor -> Write(Data,ByteCount);
150                  FPosition += ByteCount;
151                   return  ByteCount;
152              }
153               else
154              {
155                   return   - 1 ;
156              }
157          }
158 
159           void  VL_CompressedStream::Close()
160          {
161               if (FCompressor)
162              {
163                  delete FCompressor;
164                  FCompressor = 0 ;
165              }
166               if (FDecompressor)
167              {
168                  delete FDecompressor;
169                  FDecompressor = 0 ;
170              }
171               if (FPeekBuffer)
172              {
173                  delete[] FPeekBuffer;
174                  FPeekBuffer = 0 ;
175              }
176               if (FStream)
177              {
178                   if (FOwned)
179                  {
180                      FStream -> Close();
181                      delete FStream;
182                      FOwned = false ;
183                  }
184                  FStream = 0 ;
185              }
186          }
187 
188          VBool VL_CompressedStream::IsAvailable()
189          {
190               return  FStream  &&  FStream -> IsAvailable();
191          }
192 
193          VSize VL_CompressedStream::Position()
194          {
195               return  IsAvailable() ? FPosition: - 1 ;
196          }
197 
198          VSize VL_CompressedStream::Size()
199          {
200               return   - 1 ;
201          }
202 
203          VSize VL_CompressedStream::MaxWriteSize()
204          {
205               return   - 1 ;
206          }
207 
208           void  VL_CompressedStream::SeekFromBegin(VSize Offset)
209          {
210          }
211 
212           void  VL_CompressedStream::SeekFromEnd(VSize Offset)
213          {
214          }
215 
216           void  VL_CompressedStream::Seek(VSize Offset)
217          {
218          }
219 
220          VBool VL_CompressedStream::IsEnd()
221          {
222               return  IsAvailable() ? FStream -> IsEnd(): true ;
223          }
224 
225  /* ********************************************************************************************************
226  VL_LZ77Stream
227  ******************************************************************************************************** */
228 
229          VL_LZ77Stream::VL_LZ77Stream(IVL_Stream *  Stream , VLE_OpenMode OpenMode , VLE_WindowMode WindowMode , VBool Owned)
230          {
231               switch (OpenMode)
232              {
233               case  vomRead:
234                   if (WindowMode == vwmAuto)
235                  {
236                      VByte BitCount = 0 ;
237                       if (Stream -> Read( & BitCount, sizeof (BitCount)) == sizeof (BitCount))
238                      {
239                           if (BitCount >= vwmMin  &&  BitCount <= vwmMax)
240                          {
241                              Init(Stream,Owned, new  LZ77Algorithms::Decompressor(BitCount));
242                          }
243                      }
244                  }
245                   break ;
246               case  vomWrite:
247                   if (WindowMode == vwmAuto)
248                  {
249                      WindowMode = vwm1024;
250                  }
251                   if (WindowMode >= vwmMin  &&  WindowMode <= vwmMax)
252                  {
253                      VByte BitCount = (VByte)WindowMode;
254                      Stream -> Write( & BitCount, sizeof (BitCount));
255                      Init(Stream,Owned, new  LZ77Algorithms::Compressor(WindowMode));
256                  }
257                   break ;
258              }
259          }
260 
261  /* ********************************************************************************************************
262  LZ77Algorithms::AlgorithmBase
263  ******************************************************************************************************** */
264 
265           namespace  LZ77Algorithms
266          {
267 
268              AlgorithmBase::AlgorithmBase(VInt WindowSizeLevel)
269              {
270                  WindowSize = 1 << WindowSizeLevel;
271                  MaxBlockSize = WindowSize;
272                  DoubleMaxBlockSize = MaxBlockSize * 2 ;
273                  ByteCountBitCount = WindowSizeLevel;
274                  ByteIndexBitCount = WindowSizeLevel;
275 
276                  FWindow = new  VByte[WindowSize * 3 ];
277                  FPosition = 0 ;
278                  FUsedWindowSize = 0 ;
279                  FWindowStartPosition = 0 ;
280              }
281 
282              AlgorithmBase:: ~ AlgorithmBase()
283              {
284                  delete[] FWindow;
285              }
286 
287  /* ********************************************************************************************************
288  LZ77Algorithms::Compressor
289  ******************************************************************************************************** */
290 
291               struct  CompressionRecord
292              {
293                  VBool Compressed;
294                  VInt Start;
295                  VInt Size;
296              };
297 
298               //  2 <= compressed size <= extended size
299              CompressionRecord TestCompression(VBuffer Window , VInt WindowSize , VInt ExtendedSize)
300              {
301                  CompressionRecord Record;
302                  Record.Compressed = false ;
303                  Record.Start = 0 ;
304                  Record.Size = 1 ;
305                   for (VInt i = 0 ;i < WindowSize;i ++ )
306                  {
307                      VBuffer Read1 = Window + i;
308                      VBuffer Read2 = Window + WindowSize;
309                      VInt CurrentSize = 0 ;
310                       while (CurrentSize < ExtendedSize  &&   * Read1 ++==* Read2 ++ )
311                      {
312                          CurrentSize ++ ;
313                      }
314                       if (CurrentSize > Record.Size)
315                      {
316                          Record.Compressed = true ;
317                          Record.Start = i;
318                          Record.Size = CurrentSize;
319                           if (CurrentSize == ExtendedSize)
320                          {
321                               break ;
322                          }
323                      }
324                  }
325                   return  Record;
326              }
327 
328               //  1 <= byte count <= window size
329               //  0 <= compressed index < window size
330               //  2 <= compressed size <= window size
331               //  1 <= uncompressed size <= window size
332              VInt Compressor::CompressAndWrite(VInt ByteCount)
333              {
334                  VInt SelectedStart =- 1 ;
335                  VInt EncodedLength =- 1 ;
336                   if (ByteCount > DoubleMaxBlockSize)
337                  {
338                      ByteCount = DoubleMaxBlockSize;
339                  }
340 
341                  VInt UncompressedBlockSize = 0 ;
342                  VInt CompressedBlockStart = 0 ;
343                  VInt CompressedBlockSize = 0 ;
344                  VInt MaxUncompressedSize = MaxBlockSize < ByteCount ? MaxBlockSize:ByteCount;
345                   while (UncompressedBlockSize < MaxUncompressedSize)
346                  {
347                      VInt ExtendedSize = ByteCount - UncompressedBlockSize;
348                       if (ExtendedSize > MaxBlockSize)
349                      {
350                          ExtendedSize = MaxBlockSize;
351                      }
352 
353                      VBuffer VirtualWindow = FWindow;
354                      VInt VirtualWindowSize = FUsedWindowSize + UncompressedBlockSize;
355                       if (VirtualWindowSize > WindowSize)
356                      {
357                          VirtualWindow += VirtualWindowSize - WindowSize;
358                          VirtualWindowSize = WindowSize;
359                      }
360 
361                      CompressionRecord Record = TestCompression(VirtualWindow,VirtualWindowSize,ExtendedSize);
362                       if (Record.Compressed)
363                      {
364                          CompressedBlockStart = Record.Start;
365                          CompressedBlockSize = Record.Size;
366                           break ;
367                      }
368                       else
369                      {
370                          UncompressedBlockSize ++ ;
371                      }
372                  }
373 
374                   if (UncompressedBlockSize)
375                  {
376                      FBitWriter -> WriteBit( false );
377                      FBitWriter -> WriteNumber(UncompressedBlockSize - 1 ,ByteCountBitCount);
378                       for (VInt i = 0 ;i < UncompressedBlockSize;i ++ )
379                      {
380                          FBitWriter -> WriteNumber(FWindow[FUsedWindowSize + i], 8 );
381                      }
382                      FPosition += UncompressedBlockSize;
383                  }
384                   if (CompressedBlockSize)
385                  {
386                      FBitWriter -> WriteBit( true );
387                      FBitWriter -> WriteNumber(CompressedBlockSize - 1 ,ByteCountBitCount);
388                      FBitWriter -> WriteNumber(CompressedBlockStart,ByteIndexBitCount);
389                      FPosition += CompressedBlockSize;
390                  }
391 
392                  ByteCount = UncompressedBlockSize + CompressedBlockSize;
393                  FUsedWindowSize += ByteCount;
394                   if (FUsedWindowSize > WindowSize)
395                  {
396                      VInt Remain = FUsedWindowSize - WindowSize;
397                      VInt CopySize = FUsedFullWindowSize - Remain;
398 
399                      memmove(FWindow,FWindow + Remain,CopySize);
400                      FUsedWindowSize = WindowSize;
401                      FWindowStartPosition += Remain;
402                      FUsedFullWindowSize = CopySize;
403                  }
404                   return  ByteCount;
405              }
406 
407              Compressor::Compressor(VInt WindowSizeLevel):AlgorithmBase(WindowSizeLevel)
408              {
409                  FBitWriter = 0 ;
410                  FUsedFullWindowSize = 0 ;
411              }
412 
413              Compressor:: ~ Compressor()
414              {
415                   while (FUsedFullWindowSize > FUsedWindowSize)
416                  {
417                      VInt Size = CompressAndWrite(FUsedFullWindowSize - FUsedWindowSize);
418                       if (Size == 0 )
419                      {
420                           break ;
421                      }
422                  }
423                  SetStream( 0 );
424              }
425 
426               void  Compressor::SetStream(IVL_Stream *  Stream)
427              {
428                   if (FBitWriter)
429                  {
430                      delete FBitWriter;
431                      FBitWriter = 0 ;
432                  }
433                   if (Stream)
434                  {
435                      FBitWriter = new  VL_BitWriter(Stream, false );
436                  }
437              }
438 
439              VInt Compressor::Write(VPointer Data , VInt ByteCount)
440              {
441                  VInt WrittenCount = 0 ;
442                  VBuffer DataBuffer = (VBuffer)Data;
443                   while (WrittenCount < ByteCount)
444                  {
445                      VInt CopySize = WindowSize * 3 - FUsedFullWindowSize;
446                       if (CopySize)
447                      {
448                          VInt DataSize = ByteCount - WrittenCount;
449                           if (CopySize > DataSize)
450                          {
451                              CopySize = DataSize;
452                          }
453                          memcpy(FWindow + FUsedFullWindowSize,DataBuffer,CopySize);
454                          DataBuffer += CopySize;
455                          FUsedFullWindowSize += CopySize;
456                          WrittenCount += CopySize;
457                      }
458 
459                      VInt Size = CompressAndWrite(FUsedFullWindowSize - FUsedWindowSize);
460                       if (Size == 0 )
461                      {
462                           break ;
463                      }
464                  }
465                   return  WrittenCount;
466              }
467 
468  /* ********************************************************************************************************
469  LZ77Algorithms::Decompressor
470  ******************************************************************************************************** */
471 
472              VInt Decompressor::DecompressBlock()
473              {
474                  VBool BlockCompressed = false ;
475                  VUInt BlockSize = 0 ;
476                   if ( ! FReader -> ReadBit(BlockCompressed))
477                  {
478                       return   0 ;
479                  }
480                   if ( ! FReader -> ReadNumber(BlockSize,ByteCountBitCount))
481                  {
482                       return   0 ;
483                  }
484                  BlockSize ++ ;
485                   if (BlockCompressed)
486                  {
487                      VUInt BlockStart = 0 ;
488                       if ( ! FReader -> ReadNumber(BlockStart,ByteIndexBitCount))
489                      {
490                           return   0 ;
491                      }
492                      VBuffer Dest = FWindow + FUsedWindowSize;
493                      VBuffer Src = FWindow + BlockStart;
494                      VInt Counter = BlockSize;
495                       while (Counter -- )
496                      {
497                           * Dest ++=* Src ++ ;
498                      }
499                  }
500                   else
501                  {
502                      VUInt ByteContent = 0 ;
503                      VBuffer WriteEntry = FWindow + FUsedWindowSize;
504                      VInt Counter = BlockSize;
505                       while (Counter -- )
506                      {
507                           if ( ! FReader -> ReadNumber(ByteContent, 8 ))
508                          {
509                               return   0 ;
510                          }
511                           * WriteEntry ++= (VByte)ByteContent;
512                      }
513                  }
514                  FUsedWindowSize += BlockSize;
515                   if (FUsedWindowSize > WindowSize)
516                  {
517                      VInt MoveSize = FUsedWindowSize - WindowSize;
518                      memmove(FWindow,FWindow + MoveSize,WindowSize);
519                      FUsedWindowSize = WindowSize;
520                      FWindowStartPosition += MoveSize;
521                  }
522                   return  BlockSize;
523              }
524 
525              Decompressor::Decompressor(VInt WindowSizeLevel):AlgorithmBase(WindowSizeLevel)
526              {
527                  FReader = 0 ;
528              }
529 
530              Decompressor:: ~ Decompressor()
531              {
532                  SetStream( 0 );
533              }
534 
535               void  Decompressor::SetStream(IVL_Stream *  Stream)
536              {
537                   if (FReader)
538                  {
539                      delete FReader;
540                      FReader = 0 ;
541                  }
542                   if (Stream)
543                  {
544                      FReader = new  VL_BitReader(Stream, false );
545                  }
546              }
547 
548              VInt Decompressor::Read(VPointer Data , VInt ByteCount)
549              {
550                  VBuffer Buffer = (VBuffer)Data;
551                  VInt WrittenCount = 0 ;
552                   while (WrittenCount < ByteCount)
553                  {
554                       if (FWindowStartPosition + FUsedWindowSize == FPosition)
555                      {
556                           if (DecompressBlock() == 0 )
557                          {
558                               break ;
559                          }
560                      }
561 
562                      VInt NeedCount = ByteCount - WrittenCount;
563                      VInt AllowSize = (VInt)(FWindowStartPosition + FUsedWindowSize - FPosition);
564                      VInt ReadSize = NeedCount < AllowSize ? NeedCount:AllowSize;
565                       if (ReadSize)
566                      {
567                          memcpy(Buffer,FWindow + (FPosition - FWindowStartPosition),ReadSize);
568                          WrittenCount += ReadSize;
569                          Buffer += ReadSize;
570                          FPosition += ReadSize;
571                      }
572                       else
573                      {
574                           break ;
575                      }
576                  }
577                   return  WrittenCount;
578              }
579 
580          }
581 
582      }
583  }

你可能感兴趣的:(修改后的LZ77压缩解压源码)