Распаковать поток LZ4 неизвестного размера

Я хочу распаковать необработанный поток LZ4 внутри двоичных данных. Я прочитал документацию и придумал следующую функцию. Согласно коду, он должен продолжать распаковывать до тех пор, пока не закончатся сжатые данные, но этого не происходит. Что я делаю неправильно? Кроме того, я хочу добавить запись для сжатого размера.

function Try(inStream: TMemorySTream): Boolean;
var
  i, j, k: int64;
  orig_buff: Pansichar;
  compressed_buff: Pansichar;
  lz4StreamDecode: PLZ4_streamDecode_t;
begin
  result := false;
  lz4StreamDecode := LZ4_createStreamDecode();
  k := 0;   
  while True do
  begin
    orig_buff := allocmem(100);
    compressed_buff := allocmem(4064);
    j := inStream.Read(orig_buff^, 100);
    i := lz4.LZ4_decompress_safe_continue(lz4StreamDecode, orig_buff,
      compressed_buff, j, 4064);
    Freemem(orig_buff);
    Freemem(compressed_buff);
    if i <= 0 then
      break;
    inc(k);
  end;
  if k <> 0 then
    result := True;
  LZ4_freeStreamDecode(lz4StreamDecode);    
end;

РЕДАКТИРОВАТЬ 1: Удалена часть, где освобождается выходной буфер (временный буфер), но проблема остается, вместо распаковки всего потока и последующего выхода, он просто заранее выходит из цикла.

function Try(inStream: TMemorySTream): Boolean;
var
  i, j, k: int64;
  orig_buff: Pansichar;
  compressed_buff: Pansichar;
  lz4StreamDecode: PLZ4_streamDecode_t;
begin
  result := false;
  lz4StreamDecode := LZ4_createStreamDecode();
  compressed_buff := allocmem(64 * 1024 * 1024);
  k := 0;   
  while True do
  begin
    orig_buff := allocmem(100);
    j := inStream.Read(orig_buff^, 100);
    i := lz4.LZ4_decompress_safe_continue(lz4StreamDecode, orig_buff,
      compressed_buff, j, (64 * 1024 * 1024));
    Freemem(orig_buff);
    if i <= 0 then
      break;
    inc(k);
  end;
  if k <> 0 then
    result := True;
  Freemem(compressed_buff);
  LZ4_freeStreamDecode(lz4StreamDecode);    
end; 

person Dremora    schedule 08.03.2017    source источник
comment
Не лучше ли знать длину? Разве это не намерение.   -  person David Heffernan    schedule 08.03.2017
comment
Точно, сэр, вы получили то, чего я пытаюсь добиться :D   -  person Dremora    schedule 09.03.2017
comment
Вы идете об этом неправильно. Сожмите данные и сохраните сжатый размер и данные.   -  person David Heffernan    schedule 09.03.2017
comment
Это было бы так, если бы я сжимал данные, это нужно для распаковки любого потока LZ4, встроенного в дамп, поэтому я запускаю это практически при каждом смещении.   -  person Dremora    schedule 09.03.2017
comment
Зачем ты это делаешь?   -  person David Heffernan    schedule 09.03.2017
comment
Чтобы получить длины потоков внутри него и их смещения   -  person Dremora    schedule 09.03.2017
comment
Почему вы создали файл без этой информации? Если бы вы правильно наметили файл, вам не нужно было бы так взламывать.   -  person David Heffernan    schedule 09.03.2017


Ответы (1)


LZ4_Decompress_safe_continue использует «предыдущий блок памяти», потому что сжатие также зависело от него. Вы разрушаете этот блок памяти. Вы не должны этого делать. Вместо этого вы должны использовать два буфера и переключаться между ними. Вы должны создать буферы перед началом и уничтожить их только после завершения декомпрессии. Вы говорите, что читали инструкцию. Я не думаю, что у вас есть. Это дает явный пример для этого, а также объясняет, как это работает.

Редактировать

Вот как я бы изменил вашу функцию. Извините - не удалось проверить

Примечание. Я использую 2 буфера и переключаюсь между ними. Это одна из вещей, которые вам не хватает

Также я бы не стал использовать Try в качестве имени функции, это зарезервированное слово!

function XTry(inStream: TMemorySTream): Boolean;
var
  i, j, k: int64;
  orig_buff: Pansichar;
  compressed_buff1, compressed_buff2: Pansichar;
  lz4StreamDecode: PLZ4_streamDecode_t;
begin
  result := false;
  lz4StreamDecode := LZ4_createStreamDecode();
  orig_buff := allocMem( 128 *1024 );
  compressed_buff1 := allocmem(1024 * 1024);
  compressed_buff2 := allocmem(1024 * 1024);
  k := 0;   
  while True do
  begin
    j := inStream.Read(orig_buff^, 128*1024);
    i := lz4.LZ4_decompress_safe_continue(lz4StreamDecode, orig_buff,
      compressed_buff1, j, 4096);  // <<<< Note 1st buffer
    if i <= 0 then
      break;
    inc(k);
    j := inStream.Read(orig_buff^, 128*1024);
    i := lz4.LZ4_decompress_safe_continue(lz4StreamDecode, orig_buff,
      compressed_buff2, j, 4096);   // Note 2nd buffer
    if i <= 0 then
      break;
    inc(k);
  end;
  if k <> 0 then
    result := True;
  LZ4_freeStreamDecode(lz4StreamDecode);    
  Freemem(compressed_buff1);
  Freemem(compressed_buff2);
  Freemem(orig_buff);

end; 

Очевидно, это можно многое исправить - я просто хотел максимально приблизиться к исходному коду.

person Dsm    schedule 08.03.2017
comment
Во-первых, спасибо за ответ. Тогда это не сжатие, так как нам нужен «предыдущий блок памяти» в качестве словаря для поиска совпадений, хотя он может понадобиться зависимым блокам. То есть, по сути, вы говорите, что я не должен освобождать сжатый_бафф? - person Dremora; 08.03.2017
comment
Глядя на руководство, это распакованный буфер, который вы специально не должны освобождать. Вместо этого используйте два таких буфера и переключайтесь между ними. Но лично я бы тоже не стал освобождать - это только замедляет работу. - person Dsm; 08.03.2017
comment
Отредактировано, как вы сказали, все равно то же самое :( - person Dremora; 08.03.2017
comment
Вы сжимали оригинал? Были ли исходные блоки длиной всего 100 байт? (или вы не знаете?) 100 байт кажутся немного маленькими... - person Dsm; 08.03.2017
comment
Нет.. Еще не распаковывал его... Написание функции для его распаковки - person Dremora; 08.03.2017
comment
Я имел в виду, вы распаковываете что-то вы сжатое или просто случайный zip-файл? - person Dsm; 08.03.2017
comment
На самом деле это бинарный файл со встроенными в него потоками lz4. - person Dremora; 08.03.2017