{DOS-text Реализация кодека для сжатия буфера в ОЗУ методом Лемпеля-Зива 1) constructor Init(iSizeInNodes:tIndex); - размещение словаря в iSizeInNodes символов. ПРИМЕЧАНИЕ. Метод Лемпеля-Зива обрабатывает поток данных (последовательность байт). Ниже описаны процедуры обработки буфера в ОЗУ, эти процедуры позволяют упаковывать данные "порциями", для упаковки всех данных, 1) данные считываются в промежуточный буфер (порция) и 2) передаются процедурам упаковки/распаковки. Но на самом деле эти процедуры: 1) считывают из буфера последовательно байты и передают их в ByteToCodes/CodeToBytes; 2) записывают результат в выходной буфер. Главная функция этих процедур - плотная запись и непрерывное считывание порций данных (кодов) не кратных 8 битам (байту), см. также модуль LzBitBuf. 2) procedure EncodeReset - начать новое кодирование. Сбрасывает словарь и полностью очищает буфер переноса. 3) function Encode(const AInBuffer; - буфер со исходными данными AInBufSize:tBufferIndex; - размер буфера с исходными данными var AEncodedSize:tBufferIndex; - размер закодированной части, !!!может быть меньше AInBufSize, если все не влазит в AOutBuffer var AOutBuffer; - кодированный буфер AOutBufSize:tBufferIndex; - размер кодированного буфера var AOutDataSize:tBufferIndex - размер кодированных данных в буфере ):boolean; - кодирование буфера AInBuffer в AOutBuffer. При кодировании в AOutBuffer записываются только полные байты, неполные остаются в промежуточном буфере переноса (менее 1-го байта). В буфере переноса может остаться больше данных, если закончилось место в AOutBuffer. Оставшиеся данные будут записаны в AOutBuffer при следующем вызове Encode. 4) procedure DecodeReset; - начать новое декодирование. Сбрасывает словарь и полностью очищает буфер переноса. 5) function Decode(const ACodedBuffer; ACodedBufSize:tBufferIndex; var ADecodedSize:tBufferIndex; var AOutBuffer; AOutBufSize:tBufferIndex; var AOutDataSize:tBufferIndex):boolean; - декодирование буфера ACodedBuffer в AOutBuffer. При декодировании из ACodedBuffer считываются только полные байты, остаток запоминается в промежуточном буфере переноса. Другие функции см. ниже в определении tLZCodec. } {--------------------------------------------------------------------------- (c) Copyright Aleksandrov O.E., 2000 Molecular Physics department, USTU, Ekaterinsburg, K-2, 620002, RUSSIA phone 75-47-15 E-mail: aleks@dpt.ustu.ru (c) Copyright Александров О.Е., 2000 620002, Екатеринбург, К-2, УГТУ, Кафедра молекулярной физики тел. 75-47-15 E-mail: aleks@dpt.ustu.ru ----------------------------------------------------------------------------} {Win-text ╨хрышчрЎш  ъюфхър фы  ёцрЄш  сєЇхЁр т ╬╟╙ ьхЄюфюь ╦хьяхы -╟штр 1) constructor Init(iSizeInNodes:tIndex); - Ёрчьх∙хэшх ёыютрЁ  т iSizeInNodes ёшьтюыют. ╧╨╚╠┼╫└═╚┼. ╠хЄюф ╦хьяхы -╟штр юсЁрсрЄ√трхЄ яюЄюъ фрээ√ї (яюёыхфютрЄхы№эюёЄ№ срщЄ). ═шцх юяшёрэ√ яЁюЎхфєЁ√ юсЁрсюЄъш сєЇхЁр т ╬╟╙, ¤Єш яЁюЎхфєЁ√ яючтюы ■Є єяръют√трЄ№ фрээ√х "яюЁЎш ьш", фы  єяръютъш тёхї фрээ√ї: 1) фрээ√х ёўшЄ√тр■Єё  т яЁюьхцєЄюўэ√щ сєЇхЁ (яюЁЎш ) ш 2) яхЁхфр■Єё  яЁюЎхфєЁрь єяръютъш/Ёрёяръютъш. ═ю эр ёрьюь фхых ¤Єш яЁюЎхфєЁ√: 1) ёўшЄ√тр■Є шч сєЇхЁр яюёыхфютрЄхы№эю срщЄ√ ш яхЁхфр■Є шї т ByteToCodes/CodeToBytes; 2) чряшё√тр■Є Ёхчєы№ЄрЄ т т√їюфэющ сєЇхЁ. ├ыртэр  ЇєэъЎш  ¤Єшї яЁюЎхфєЁ - яыюЄэр  чряшё№ ш эхяЁхЁ√тэюх ёўшЄ√трэшх яюЁЎшщ фрээ√ї (ъюфют) эх ъЁрЄэ√ї 8 сшЄрь (срщЄє), ёь. Єръцх ьюфєы№ LzBitBuf. 2) procedure EncodeReset - эрўрЄ№ эютюх ъюфшЁютрэшх. ╤сЁрё√трхЄ ёыютрЁ№ ш яюыэюёЄ№■ юўш∙рхЄ сєЇхЁ яхЁхэюёр. 3) function Encode(const AInBuffer; - сєЇхЁ ёю шёїюфэ√ьш фрээ√ьш AInBufSize:tBufferIndex; - ЁрчьхЁ сєЇхЁр ё шёїюфэ√ьш фрээ√ьш var AEncodedSize:tBufferIndex; - ЁрчьхЁ чръюфшЁютрээющ ўрёЄш, !!!ьюцхЄ с√Є№ ьхэ№°х AInBufSize, хёыш тёх эх тырчшЄ т AOutBuffer var AOutBuffer; - ъюфшЁютрээ√щ сєЇхЁ AOutBufSize:tBufferIndex; - ЁрчьхЁ ъюфшЁютрээюую сєЇхЁр var AOutDataSize:tBufferIndex - ЁрчьхЁ ъюфшЁютрээ√ї фрээ√ї т сєЇхЁх ):boolean; - ъюфшЁютрэшх сєЇхЁр AInBuffer т AOutBuffer. ╧Ёш ъюфшЁютрэшш т AOutBuffer чряшё√тр■Єё  Єюы№ъю яюыэ√х срщЄ√, эхяюыэ√х юёЄр■Єё  т яЁюьхцєЄюўэюь сєЇхЁх яхЁхэюёр (ьхэхх 1-ую срщЄр). ┬ сєЇхЁх яхЁхэюёр ьюцхЄ юёЄрЄ№ё  сюы№°х фрээ√ї, хёыш чръюэўшыюё№ ьхёЄю т AOutBuffer. ╬ёЄрт°шхё  фрээ√х сєфєЄ чряшёрэ√ т AOutBuffer яЁш ёыхфє■∙хь т√чютх Encode. 4) procedure DecodeReset; - эрўрЄ№ эютюх фхъюфшЁютрэшх. ╤сЁрё√трхЄ ёыютрЁ№ ш яюыэюёЄ№■ юўш∙рхЄ сєЇхЁ яхЁхэюёр. 5) function Decode(const ACodedBuffer; ACodedBufSize:tBufferIndex; var ADecodedSize:tBufferIndex; var AOutBuffer; AOutBufSize:tBufferIndex; var AOutDataSize:tBufferIndex):boolean; - фхъюфшЁютрэшх сєЇхЁр ACodedBuffer т AOutBuffer. ╧Ёш фхъюфшЁютрэшш шч ACodedBuffer ёўшЄ√тр■Єё  Єюы№ъю яюыэ√х срщЄ√, юёЄрЄюъ (ьхэхх 1 срщЄр) чряюьшэрхЄё  т яЁюьхцєЄюўэюь сєЇхЁх яхЁхэюёр ш сєфхЄ фхъюфшЁютрэ яЁш ёыхфє■∙хь т√чютх Decode. ─Ёєушх ЇєэъЎшш ёь. эшцх т юяЁхфхыхэшш tLZCodec. } {--------------------------------------------------------------------------- (c) Copyright Aleksandrov O.E., 2000 Molecular Physics department, USTU, Ekaterinsburg, K-2, 620002, RUSSIA phone 75-47-15 E-mail: aleks@dpt.ustu.ru (c) Copyright └ыхъёрэфЁют ╬.┼., 2000 620002, ┼ърЄхЁшэсєЁу, ╩-2, ╙├╥╙, ╩рЇхфЁр ьюыхъєы Ёэющ Їшчшъш Єхы. 75-47-15 E-mail: aleks@dpt.ustu.ru ----------------------------------------------------------------------------} Unit LZCodec; {$X+} {$B- отключение полного вычисления булевских выражений !!! это критично, включение полного вычисления булевских выражений приведет к ошибке в программе - юЄъы■ўхэшх яюыэюую т√ўшёыхэш  сєыхтёъшї т√Ёрцхэшщ !!! ¤Єю ъЁшЄшўэю, тъы■ўхэшх яюыэюую т√ўшёыхэш  сєыхтёъшї т√Ёрцхэшщ яЁштхфхЄ ъ ю°шсъх т яЁюуЁрььх } {$IfDef NoChecking} {$R-,S-,Q-} {$EndIf Def NoChecking} INTERFACE USES BitBuf, ComTypes, LZTypes, LZBase, LZDic0, LZDic1; type tLZCodec=object(tLZDictionary) private prCodes:tLZCodesArray; { буфер переноса кодов, при декодировке используется только prCodes.Code[0] } { сєЇхЁ яхЁхэюёр ъюфют, яЁш ъюфшЁютрэшш (Encode) шёяюы№чєхЄё  ъръ їЁрэшыш∙х ъюфют, ъюЄюЁ√х эх яюьх∙р■Єё  т т√їюфэющ сєЇхЁ, ёюїЁрэхээ√х ъюф√ сєфєЄ чряшёрэ√ т т√їюфэющ сєЇхЁ яЁш ёыхфє■∙хь т√чютх Encode яЁш фхъюфшЁютрэшш (Decode) шёяюы№чєхЄё  Єюы№ъю prCodes.Code[0], ъръ їЁрэшыш∙х эхфхъюфшЁютрээюую шч-чр юЄёєЄёЄтш  ьхёЄр т√їюфэюь сєЇхЁх ъюфр, ъюф сєфхЄ фхъюфшЁютрэ яЁш ёыхфє■∙хь т√чютх Decode} prCodesCount:tCodesCount; { число кодов в буфере переноса кодов, используется только при кодировке } { ўшёыю ъюфют т сєЇхЁх яхЁхэюёр ъюфют, шёяюы№чєхЄё  Єюы№ъю яЁш ъюфшЁютъх } prCodeNumber:tCodesCount; { номер первого неперенесенного кода в буфере переноса кодов, используется только при кодировке } { эюьхЁ яхЁтюую эхёюїЁрэхээюую ъюфр т сєЇхЁх яхЁхэюёр ъюфют, шёяюы№чєхЄё  Єюы№ъю яЁш ъюфшЁютъх } prBitBuffer:tBitBuffer; { битовый буфер - объект для битовых операций с буфером, см. модуль LzBitBuf } { сшЄют√щ сєЇхЁ - юс·хъЄ фы  сшЄют√ї юяхЁрЎшщ ё сєЇхЁюь, ёь. ьюфєы№ LzBitBuf } public { ---- Инициализация/деинициализация словаря } { ---- ╚эшЎшрышчрЎш /фхшэшЎшрышчрЎш  ёыютрЁ  } constructor Init(iSizeInNodes:tIndex); destructor Done; procedure Reinit; { ---- Кодирование буфера } { ---- ╩юфшЁютрэшх сєЇхЁр } { начать новое кодирование - сбрасывает словарь и полностью очищает буфер переноса } { эрўрЄ№ эютюх ъюфшЁютрэшх - ёсЁрё√трхЄ ёыютрЁ№ ш яюыэюёЄ№■ юўш∙рхЄ сєЇхЁ яхЁхэюёр } procedure EncodeReset; { кодирование буфера AInBuffer в AOutBuffer. При кодировании в AOutBuffer записываются только полные байты, неполные остаются в промежуточном буфере переноса (менее 1-го байта). В буфере переноса может остаться больше данных, если закончилось место в AOutBuffer. Оставшиеся данные будут записаны в AOutBuffer при следующем вызове Encode. } { ъюфшЁютрэшх сєЇхЁр AInBuffer т AOutBuffer. ╧Ёш ъюфшЁютрэшш т AOutBuffer чряшё√тр■Єё  Єюы№ъю яюыэ√х срщЄ√, эхяюыэ√х юёЄр■Єё  т яЁюьхцєЄюўэюь сєЇхЁх яхЁхэюёр (ьхэхх 1-ую срщЄр). ┬ сєЇхЁх яхЁхэюёр ьюцхЄ юёЄрЄ№ё  сюы№°х фрээ√ї (сюыхх 1-ую срщЄр), хёыш чръюэўшыюё№ ьхёЄю т AOutBuffer. ╬ёЄрт°шхё  фрээ√х сєфєЄ чряшёрэ√ т AOutBuffer яЁш ёыхфє■∙хь т√чютх Encode. } function Encode(const AInBuffer; { буфер со исходными данными } { сєЇхЁ ёю шёїюфэ√ьш фрээ√ьш } AInBufSize:tBufferIndex; { размер буфера с исходными данными } { ЁрчьхЁ сєЇхЁр ё шёїюфэ√ьш фрээ√ьш } var AEncodedSize:tBufferIndex; { размер закодированной части, !!!может быть меньше AInBufSize, если все не влазит в AOutBuffer } { ЁрчьхЁ чръюфшЁютрээющ ўрёЄш, !!!ьюцхЄ с√Є№ ьхэ№°х AInBufSize, хёыш тёх эх тырчшЄ т AOutBuffer } var AOutBuffer; { кодированный буфер }{ ъюфшЁютрээ√щ сєЇхЁ } AOutBufSize:tBufferIndex; { размер кодированного буфера } { ЁрчьхЁ ъюфшЁютрээюую сєЇхЁр } var AOutDataSize:tBufferIndex { размер кодированных данных в буфере } { ЁрчьхЁ ъюфшЁютрээ√ї фрээ√ї т сєЇхЁх } ):boolean; function EncodeEx(const AInBuffer; { буфер со исходными данными } { сєЇхЁ ёю шёїюфэ√ьш фрээ√ьш } AInBufSize:tBufferIndex; { размер буфера с исходными данными } { ЁрчьхЁ сєЇхЁр ё шёїюфэ√ьш фрээ√ьш } var AEncodedSize:tBufferIndex; { размер закодированной части, !!!может быть меньше AInBufSize, если все не влазит в AOutBuffer } { ЁрчьхЁ чръюфшЁютрээющ ўрёЄш, !!!ьюцхЄ с√Є№ ьхэ№°х AInBufSize, хёыш тёх эх тырчшЄ т AOutBuffer } var AOutBuffer; { кодированный буфер }{ ъюфшЁютрээ√щ сєЇхЁ } AOutBufSize:tBufferIndex; { размер кодированного буфера } { ЁрчьхЁ ъюфшЁютрээюую сєЇхЁр } var AOutDataSize:tBufferIndex { размер кодированных данных в буфере } { ЁрчьхЁ ъюфшЁютрээ√ї фрээ√ї т сєЇхЁх } ):boolean; { ---- Декодирование буфера } { ---- ─хъюфшЁютрэшх сєЇхЁр } { начать новое декодирование - сбрасывает словарь и полностью очищает буфер переноса. } { эрўрЄ№ эютюх фхъюфшЁютрэшх - ёсЁрё√трхЄ ёыютрЁ№ ш яюыэюёЄ№■ юўш∙рхЄ сєЇхЁ яхЁхэюёр. } procedure DecodeReset; { декодирование буфера ACodedBuffer в AOutBuffer. При декодировании из ACodedBuffer считываются только полные байты, остаток запоминается в промежуточном буфере переноса. } { фхъюфшЁютрэшх сєЇхЁр ACodedBuffer т AOutBuffer. ╧Ёш фхъюфшЁютрэшш шч ACodedBuffer ёўшЄ√тр■Єё  Єюы№ъю яюыэ√х срщЄ√, юёЄрЄюъ чряюьшэрхЄё  т яЁюьхцєЄюўэюь сєЇхЁх яхЁхэюёр. } function Decode(const ACodedBuffer; ACodedBufSize:tBufferIndex; var ADecodedSize:tBufferIndex; var AOutBuffer; AOutBufSize:tBufferIndex; var AOutDataSize:tBufferIndex):boolean; end; IMPLEMENTATION constructor tLZCodec.Init; begin if Inherited ReInit(iSizeInNodes) then begin ReInit; end else begin Fail; end; end; destructor tLZCodec.Done; begin Inherited Done; end; procedure tLZCodec.ReInit; begin prBitBuffer.Init; EncodeReset; end; { начать новое кодирование - сбрасывает словарь и полностью очищает буфер переноса } { эрўрЄ№ эютюх ъюфшЁютрэшх - ёсЁрё√трхЄ ёыютрЁ№ ш яюыэюёЄ№■ юўш∙рхЄ сєЇхЁ яхЁхэюёр } procedure tLZCodec.EncodeReset; begin prCodesCount:=0; prCodeNumber:=0; prBitBuffer.Reset; SetEncodeRegime; end; function tLZCodec.Encode(const AInBuffer; AInBufSize:tBufferIndex; var AEncodedSize:tBufferIndex; var AOutBuffer; AOutBufSize:tBufferIndex; var AOutDataSize:tBufferIndex):boolean; var Codes:tLZCodesArray; lCodesCount:tCodesCount; lCodeNumber:tCodesCount; PBitBuffer:^tBitBuffer; procedure CopyCodesToBuffer(CodesCount, StartFromNumber:tCodesCount); begin while (StartFromNumber0) and (not PBitBuffer^.Full) do begin { пропускаем фрагмент, если он есть в словаре, не забыв изменить длину фрагмента и код текущего фрагмента } { яЁюяєёърхь ЇЁруьхэЄ, хёыш юэ хёЄ№ т ёыютрЁх, эх чрс√т шчьхэшЄ№ фышэє ЇЁруьхэЄр ш ъюф Єхъє∙хую ЇЁруьхэЄр } di:=SkipFragment(tBuffer(AInBuffer)[i],AInBufSize); if di>0 then begin Inc(i, di); Dec(AInBufSize,di); end; { байт tBuffer(AInBuffer)[i] не найден в словаре или буфер AInBuf закончился} { срщЄ tBuffer(AInBuffer)[i] эх эрщфхэ т ёыютрЁх } if (AInBufSize>0) then begin {если буфер AInBuf не закончился} { кодируем очередной байт } { ъюфшЁєхь юўхЁхфэющ срщЄ } { копируем коды в битовый буфер} { ъюяшЁєхь ъюф√ т сшЄют√щ сєЇхЁ} CopyCodesToBuffer( ByteToCodes(tBuffer(AInBuffer)[i], Codes), 0 ); Inc(i); Dec(AInBufSize); end; end; { возвращает размеры обработанных данных } { тючтЁр∙рхь ЁрчьхЁ√ юсЁрсюЄрээ√ї фрээ√ї } AEncodedSize:=i; AOutDataSize:=PBitBuffer^.Size; end; prCodes:=Codes; prCodesCount:=lCodesCount; prCodeNumber:=lCodeNumber; Encode:=(i>0); end; end; (* function tLZCodec.Encode(const AInBuffer; AInBufSize:tBufferIndex; var AEncodedSize:tBufferIndex; var AOutBuffer; AOutBufSize:tBufferIndex; var AOutDataSize:tBufferIndex):boolean; var PCode:^tCodeArray; PLength:^tCodeLengthArray; PBitBuffer:^tBitBuffer; procedure CopyCodesToBuffer(CodesCount, StartFromNumber:tCodesCount); begin while (StartFromNumber0) and (not PBitBuffer^.Full) do begin { пропускаем фрагмент, если он есть в словаре, не забыв изменить длину фрагмента и код текущего фрагмента } { яЁюяєёърхь ЇЁруьхэЄ, хёыш юэ хёЄ№ т ёыютрЁх, эх чрс√т шчьхэшЄ№ фышэє ЇЁруьхэЄр ш ъюф Єхъє∙хую ЇЁруьхэЄр } di:=SkipFragment(tBuffer(AInBuffer)[i],AInBufSize); Inc(i, di); Dec(AInBufSize,di); { байт tBuffer(AInBuffer)[i] не найден в словаре или буфер AInBuf закончился} { срщЄ tBuffer(AInBuffer)[i] эх эрщфхэ т ёыютрЁх } if (AInBufSize>0) then begin {если буфер AInBuf не закончился} { кодируем очередной байт } { ъюфшЁєхь юўхЁхфэющ срщЄ } { копируем коды в битовый буфер} { ъюяшЁєхь ъюф√ т сшЄют√щ сєЇхЁ} CopyCodesToBuffer( ByteToCodes(tBuffer(AInBuffer)[i], PCodes^), 0 ); Inc(i); Dec(AInBufSize); end; end; { возвращает размеры обработанных данных } { тючтЁр∙рхь ЁрчьхЁ√ юсЁрсюЄрээ√ї фрээ√ї } AEncodedSize:=i; AOutDataSize:=PBitBuffer^.Size; end; Encode:=(i>0); end; end; *) { кодирование буфера }{ ъюфшЁютрэшх сєЇхЁр } function tLZCodec.EncodeEx(const AInBuffer; AInBufSize:tBufferIndex; var AEncodedSize:tBufferIndex; var AOutBuffer; AOutBufSize:tBufferIndex; var AOutDataSize:tBufferIndex):boolean; var i,di:tBufferIndex; cn,cc:tCodesCount; PCode:^tCodeArray; PLength:^tCodeLengthArray; PBitBuffer:^tBitBuffer; begin if (AOutBufSize=0) then begin { невозможно кодирование } { эхтючьюцэю ъюфшЁютрэшх } EncodeEx:=False; end else begin { инициализация выходного битового буфера } { шэшЎшрышчрЎш  т√їюфэюую сшЄютюую сєЇхЁр } PBitBuffer:=@prBitBuffer; { это для ускорения обращения }{ ¤Єю фы  єёъюЁхэш  юсЁр∙хэш  } PBitBuffer^.AssignForWrite(AOutBuffer,AOutBufSize); PCode:=@pbCodes.Code; {это для ускорения обращения }{ ¤Єю фы  єёъюЁхэш  юсЁр∙хэш  } PLength:=@pbCodes.Length; { копируем оставшиеся от предыдущего буфера коды } { ъюяшЁєхь юёЄрт°шхё  юЄ яЁхф√фє∙хую сєЇхЁр ъюф√ } cn:=prCodeNumber; cc:=prCodesCount; while (cn0) and (not PBitBuffer^.Full) do begin { пропускаем фрагмент, если он есть в словаре, не забыв изменить длину фрагмента и код текущего фрагмента } { яЁюяєёърхь ЇЁруьхэЄ, хёыш юэ хёЄ№ т ёыютрЁх, эх чрс√т шчьхэшЄ№ фышэє ЇЁруьхэЄр ш ъюф Єхъє∙хую ЇЁруьхэЄр } di:=SkipFragment(tBuffer(AInBuffer)[i],AInBufSize); Inc(i, di); Dec(AInBufSize,di); { байт tBuffer(AInBuffer)[i] не найден в словаре } { срщЄ tBuffer(AInBuffer)[i] эх эрщфхэ т ёыютрЁх } if (AInBufSize>0) then begin { кодируем очередной байт } { ъюфшЁєхь юўхЁхфэющ срщЄ } cc:=ByteToCodesEx(tBuffer(AInBuffer)[i]); Inc(i); Dec(AInBufSize); { копируем коды (cc штук) в битовый буфер} { ъюяшЁєхь ъюф√ (cc °Єєъ) т сшЄют√щ сєЇхЁ} cn:=0; while (cn0); end; end; { начать новое декодирование - сбрасывает словарь и полностью очищает буфер переноса. } { эрўрЄ№ эютюх фхъюфшЁютрэшх - ёсЁрё√трхЄ ёыютрЁ№ ш яюыэюёЄ№■ юўш∙рхЄ сєЇхЁ яхЁхэюёр. } procedure tLZCodec.DecodeReset; begin prCodes.Code[0]:=0; prBitBuffer.Reset; SetDecodeRegime; end; { декодирование буфера }{ фхъюфшЁютрэшх сєЇхЁр } function tLZCodec.Decode(const ACodedBuffer; ACodedBufSize:tBufferIndex; var ADecodedSize:tBufferIndex; var AOutBuffer; AOutBufSize:tBufferIndex; var AOutDataSize:tBufferIndex):boolean; var ACode:BitBuf.tData; {l:longint;} PBitBuffer:^tBitBuffer; i:tBufferIndex; DataSize:tSignedBufferIndex; begin if (AOutBufSize=0) then begin { декодирование невозможно } { фхъюфшЁютрэшх эхтючьюцэю } Decode:=False; end else begin { инициализация входного битового буфера} { шэшЎшрышчрЎш  тїюфэюую сшЄютюую сєЇхЁр} PBitBuffer:=@prBitBuffer; PBitBuffer^.AssignForRead(ACodedBuffer, ACodedBufSize); { оставшийся от предыдущего вызова код }{ юёЄрт°шщё  юЄ яЁхф√фє∙хую т√чютр ъюф } ACode:=prCodes.Code[0]; if ACode>0 then begin { декодируем оставшийся от предыдущего буфера код } { фхъюфшЁєхь юёЄрт°шщё  юЄ яЁхф√фє∙хую сєЇхЁр ъюф } DataSize:=CodeToBytes(ACode,AOutBuffer,AOutBufSize); if DataSize<0 then begin { недостаточно места в буфере - выходим }{ эхфюёЄрЄюўэю ьхёЄр т сєЇхЁх - т√їюфшь } ADecodedSize:=0; AOutDataSize:=0; Decode:=FALSE; Exit; end; { обнуляем код переноса } { юсэєы хь ъюф яхЁхэюёр } prCodes.Code[0]:=0; { номер первого свободного байта в AOutBuffer} { эюьхЁ яхЁтюую ётюсюфэюую срщЄр т AOutBuffer} i:=DataSize; { уменьшаем свободный размер буфера AOutBuffer } { єьхэ№°рхь ётюсюфэ√щ ЁрчьхЁ сєЇхЁр AOutBuffer } Dec(AOutBufSize,i); end else begin { номер первого свободного байта в AOutBuffer} { эюьхЁ яхЁтюую ётюсюфэюую срщЄр т AOutBuffer} i:=0; end; { декодируем буфер ACodedBuffer }{ фхъюфшЁєхь сєЇхЁ ACodedBuffer } Decode:=TRUE; while (AOutBufSize>0) and PBitBuffer^.Get(ACode, NextCodeLength) do begin { декодировать код } { фхъюфшЁютрЄ№ ъюф } DataSize:=CodeToBytes(ACode, tBuffer(AOutBuffer)[i], AOutBufSize); if DataSize<0 then begin { недостаточно места в буфере AOutBuffer - выходим }{ эхфюёЄрЄюўэю ьхёЄр т сєЇхЁх AOutBuffer - т√їюфшь } { ACode извлечен из буфера BitBuffer, но не декодирован. Поместить его обратно в BitBuffer невозможно, поэтому запоминаем код переноса для декодирования при следующем вызове } { ACode шчтыхўхэ шч сєЇхЁр BitBuffer, эю эх фхъюфшЁютрэ. ╧юьхёЄшЄ№ хую юсЁрЄэю т BitBuffer эхтючьюцэю, яю¤Єюьє чряюьшэрхь ъюф яхЁхэюёр фы  фхъюфшЁютрэш  яЁш ёыхфє■∙хь т√чютх } prCodes.Code[0]:=ACode; AOutBufSize:=0; { прерываем цикл while }{ яЁхЁ√трхь Ўшъы while } end else begin { увеличиваем номер свободного байта в AOutBuffer } { єтхышўштрхь эюьхЁ ётюсюфэюую срщЄр т AOutBuffer } Inc(i,DataSize); { уменьшаем свободный размер буфера AOutBuffer } { єьхэ№°рхь ётюсюфэ√щ ЁрчьхЁ сєЇхЁр AOutBuffer } Dec(AOutBufSize,DataSize); end; end; { декодировано }{ фхъюфшЁютрэю } ADecodedSize:=PBitBuffer^.Size; { записано в выходной буфер }{ чряшёрэю т т√їюфэющ сєЇхЁ } AOutDataSize:=i; end; end; END. --------------------------------------------------- ╧Ёхф√фє∙шх тхЁёшш (* { кодирование буфера }{ ъюфшЁютрэшх сєЇхЁр } function tLZCodec.Encode(const AInBuffer; AInBufSize:tBufferIndex; var AEncodedSize:tBufferIndex; var AOutBuffer; AOutBufSize:tBufferIndex; var AOutDataSize:tBufferIndex):boolean; var PCode:^tCodeArray; PLength:^tCodeLengthArray; PBitBuffer:^tBitBuffer; var i,di:tBufferIndex; cn,cc:tCodesCount; PCodes:tPLZCodesArray; begin if (AOutBufSize=0) then begin { невозможно кодирование } { эхтючьюцэю ъюфшЁютрэшх } Encode:=False; end else begin { инициализация выходного битового буфера } { шэшЎшрышчрЎш  т√їюфэюую сшЄютюую сєЇхЁр } PBitBuffer:=@prBitBuffer; { это для ускорения обращения }{ ¤Єю фы  єёъюЁхэш  юсЁр∙хэш  } PBitBuffer^.AssignForWrite(AOutBuffer,AOutBufSize); PCodes:=@prCodes; {это для ускорения обращения }{ ¤Єю фы  єёъюЁхэш  юсЁр∙хэш  } PCode:=@prCodes.Code; PLength:=@prCodes.Length; { копируем оставшиеся от предыдущего буфера коды } { ъюяшЁєхь юёЄрт°шхё  юЄ яЁхф√фє∙хую сєЇхЁр ъюф√ } cn:=prCodeNumber; cc:=prCodesCount; while (cn0) or (i=AInBufSize); { копируем коды в битовый буфер} { ъюяшЁєхь ъюф√ т сшЄют√щ сєЇхЁ} cn:=0; while (cn0); end; end; { декодирование буфера }{ фхъюфшЁютрэшх сєЇхЁр } function tLZCodec.Decode(const ACodedBuffer; ACodedBufSize:tBufferIndex; var ADecodedSize:tBufferIndex; var AOutBuffer; AOutBufSize:tBufferIndex; var AOutDataSize:tBufferIndex):boolean; var i,di:tBufferIndex; ACode:tIndex; {l:longint;} PBitBuffer:^tBitBuffer; begin if (AOutBufSize=0) then begin { декодирование невозможно } { фхъюфшЁютрэшх эхтючьюцэю } Decode:=False; end else begin { инициализация входного битового буфера} { шэшЎшрышчрЎш  тїюфэюую сшЄютюую сєЇхЁр} PBitBuffer:=@prBitBuffer; PBitBuffer^.AssignForRead(ACodedBuffer, ACodedBufSize); { номер первого свободного байта в AOutBuffer} { эюьхЁ яхЁтюую ётюсюфэюую срщЄр т AOutBuffer} i:=0; { оставшийся от предыдущего вызова код }{ юёЄрт°шщё  юЄ яЁхф√фє∙хую т√чютр ъюф } ACode:=prCodes.Code[0]; if ACode>0 then begin { декодируем оставшийся от предыдущего буфера код } { фхъюфшЁєхь юёЄрт°шщё  юЄ яЁхф√фє∙хую сєЇхЁр ъюф } if CodeToBytes(ACode,AOutBuffer,AOutBufSize,i)<>0 then begin { недостаточно места в буфере - выходим }{ эхфюёЄрЄюўэю ьхёЄр т сєЇхЁх - т√їюфшь } ADecodedSize:=0; AOutDataSize:=0; Decode:=FALSE; Exit; end; { обнуляем код переноса } { юсэєы хь ъюф яхЁхэюёр } prCodes.Code[0]:=0; { уменьшаем свободный размер буфера AOutBuffer } { єьхэ№°рхь ётюсюфэ√щ ЁрчьхЁ сєЇхЁр AOutBuffer } Dec(AOutBufSize,i); end; { декодируем буфер ACodedBuffer }{ фхъюфшЁєхь сєЇхЁ ACodedBuffer } Decode:=TRUE; while (AOutBufSize>0) and PBitBuffer^.Get(ACode, NextCodeLength) do begin { декодировать код } { фхъюфшЁютрЄ№ ъюф } if CodeToBytes(ACode,tBuffer(AOutBuffer)[i],AOutBufSize,di)<>0 then begin { недостаточно места в буфере AOutBuffer - выходим } { эхфюёЄрЄюўэю ьхёЄр т сєЇхЁх AOutBuffer - т√їюфшь } { ACode извлечен из буфера BitBuffer, но не декодирован. Поместить его обратно в BitBuffer невозможно, поэтому запоминаем код переноса для декодирования при следующем вызове } { ACode шчтыхўхэ шч сєЇхЁр BitBuffer, эю эх фхъюфшЁютрэ. ╧юьхёЄшЄ№ хую юсЁрЄэю т BitBuffer эхтючьюцэю, яю¤Єюьє чряюьшэрхь ъюф яхЁхэюёр фы  фхъюфшЁютрэш  яЁш ёыхфє■∙хь т√чютх } prCodes.Code[0]:=ACode; AOutBufSize:=0; { прерываем цикл while }{ яЁхЁ√трхь Ўшъы while } end else begin { увеличиваем номер свободного байта в AOutBuffer } { єтхышўштрхь эюьхЁ ётюсюфэюую срщЄр т AOutBuffer } Inc(i,di); { уменьшаем свободный размер буфера AOutBuffer } { єьхэ№°рхь ётюсюфэ√щ ЁрчьхЁ сєЇхЁр AOutBuffer } Dec(AOutBufSize,di); end; end; { декодировано }{ фхъюфшЁютрэю } ADecodedSize:=PBitBuffer^.Size; { записано в выходной буфер }{ чряшёрэю т т√їюфэющ сєЇхЁ } AOutDataSize:=i; end; end;