Форум по Delphi программированию

 



Вернуться   Форум по Delphi программированию > Разное > Исходники и статьи
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 05.09.2013, 10:20
CynicRus CynicRus вне форума
Прохожий
 
Регистрация: 26.02.2013
Сообщения: 30
Версия Delphi: Lazarus, XE 3.
Репутация: 10
По умолчанию Декомпрессия алгоритма snappy от Google

Не так давно потребовалось распаковать на Delphi файлик сжатый snappy, в связи с чем и была написана данная функция. Работает как в Delphi так и в Lazarus.

Сжатие мне было не нужно, поэтому я его особо не ковырял.
Код:
procedure SnappyDecompress(Input: TByteArray; Offset,
  Length: integer; var Output: TByteArray);
var
  i, l, o, c,targetIndex,SourceIndex,targetLength: integer;

function incPP(var AVal: integer): integer;
begin
  result := AVal;
  inc(AVal);
end;

begin
  sourceIndex:=offset;
  targetIndex:=0;
  targetLength:=0;
  i:=0;
  repeat
     targetLength := targetLength + (input[sourceIndex] and $7f) shl (incPP(i) * 7);
   until ((input[incPP(sourceIndex)] and $80) <> $80);
   SetLength(Output,targetLength);
   while (sourceIndex < offset + length) do
    begin
      if(targetIndex >= targetLength) then
       raise Exception.Create('Superfluous input data encountered on offset '+IntToStr(sourceIndex));
        case (input[sourceIndex] and 3) of
         0: begin
            l := (input[incPP(sourceIndex)] shr 2) and $3f;
                  case l of
                   60: begin
                       l := input[incPP(sourceIndex)] and $ff;
                       inc(l);
                       end;
                   61:
                       begin
                       l := input[incPP(sourceIndex)] and $ff;
                       l := l or ((input[incPP(sourceIndex)]) and $ff);
                       inc(l);
                       end;
                   62:
                       begin
                       l := input[incPP(sourceIndex)] and $ff;
                       l :=l or ((input[IncPP(sourceIndex)] and $ff) shl 8);
                       l :=l or ((input[IncPP(sourceIndex)] and $ff) shl 16);
                       inc(l);
                       end;
                   63:
                       begin
                       l := input[IncPP(sourceIndex)] and $ff;
                       l := l or ((input[IncPP(sourceIndex)] and $ff) shl 8);
                       l := l or ((input[IncPP(sourceIndex)] and $ff) shl 16);
                       l := l or ((input[IncPP(sourceIndex)] and $ff) shl 24);
                       inc(l);
                       end
                   else
                       inc(l);
                   end;
                   Move(Input[sourceIndex],Output[targetIndex],l);
                   sourceIndex := sourceIndex + l;
                   targetIndex :=targetIndex + l;
               end;
          1:
             begin
               l := 4 + ((input[sourceIndex] shr 2) and 7);
               o := (input[IncPP(sourceIndex)] and $e0) shl 3;
               o := o or (input[incPP(sourceIndex)] and $ff);
               if (l < o) then
                begin
                  move(output[targetIndex - o],output[targetIndex],l);
                  targetIndex:=targetIndex + l;
                end
                 else
                begin
                  if (o = 1) then
                    begin
                     FillChar(Output[targetIndex],l,output[targetIndex-l]);
                     targetIndex:= targetIndex + l;
                    end
                    else
                    begin
                        while (l > 0) do
                          begin
                            c:= ifthen( L > o, o, l);
                              Move(output[targetIndex-o],output[targetIndex],c);
                              targetIndex:= targetIndex + c;
                              l:= l - c;
                          end;
                    end;
                end;
               end;
             2:
              begin
              l := ((input[IncPP(sourceIndex)] shr 2) and $3f) + 1;
              o := input[IncPP(sourceIndex)] and $ff;
              o := o or ((input[IncPP(sourceIndex)] and $ff) shl 8);
               if (l < o) then
                begin
                  move(output[abs(targetIndex - o)],output[targetIndex],l);
                  targetIndex:=targetIndex + l;
                end
                 else
                begin
                  if (o = 1) then
                    begin
                     FillChar(Output[targetIndex],l,output[targetIndex-l]);
                     targetIndex:= targetIndex + l;
                    end
                    else
                    begin
                        while (l > 0) do
                          begin
                            c:= ifthen( L > o, o, l);
                              Move(output[targetIndex-o],output[targetIndex],c);
                              targetIndex:= targetIndex + c;
                              l:= l - c;
                          end;
                    end;
                end;
               end;
              3:
               begin
              l := ((input[IncPP(sourceIndex)] shr 2) and $3f) + 1;
              o := input[IncPP(sourceIndex)] and $ff;
              o := o or ((input[IncPP(sourceIndex)] and $ff) shl 8);
              o := o or ((input[IncPP(sourceIndex)] and $ff) shl 16);
              o := o or ((input[IncPP(sourceIndex)] and $ff) shl 24);
               if (l < o) then
                begin
                  move(output[targetIndex - o],output[targetIndex],l);
                  targetIndex:=targetIndex + l;
                end
                 else
                begin
                  if (o = 1) then
                    begin
                     FillChar(Output[targetIndex],l,output[targetIndex-l]);
                     targetIndex:= targetIndex + l;
                    end
                    else
                    begin
                        while (l > 0) do
                          begin
                              c:= ifthen( L > o, o, l);
                              Move(output[targetIndex-o],output[targetIndex],c);
                              targetIndex:= targetIndex + c;
                              l:= l - c;
                          end;
                    end;
                end;
               end;

         end;

     end;
end;
Ответить с цитированием
Ответ



Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 07:56.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources", 2004-2020

ВКонтакте   Facebook   Twitter