1461 lines
36 KiB
ObjectPascal
1461 lines
36 KiB
ObjectPascal
{ ****************************************************************************** }
|
|
{ * support > 2G TMemoryStream64, writen by QQ 600585@qq.com * }
|
|
{ * https://zpascal.net * }
|
|
{ * https://github.com/PassByYou888/zAI * }
|
|
{ * https://github.com/PassByYou888/ZServer4D * }
|
|
{ * https://github.com/PassByYou888/PascalString * }
|
|
{ * https://github.com/PassByYou888/zRasterization * }
|
|
{ * https://github.com/PassByYou888/CoreCipher * }
|
|
{ * https://github.com/PassByYou888/zSound * }
|
|
{ * https://github.com/PassByYou888/zChinese * }
|
|
{ * https://github.com/PassByYou888/zExpression * }
|
|
{ * https://github.com/PassByYou888/zGameWare * }
|
|
{ * https://github.com/PassByYou888/zAnalysis * }
|
|
{ * https://github.com/PassByYou888/FFMPEG-Header * }
|
|
{ * https://github.com/PassByYou888/zTranslate * }
|
|
{ * https://github.com/PassByYou888/InfiniteIoT * }
|
|
{ * https://github.com/PassByYou888/FastMD5 * }
|
|
{ ****************************************************************************** }
|
|
|
|
unit MemoryStream64;
|
|
|
|
{$INCLUDE zDefine.inc}
|
|
|
|
{
|
|
create by passbyyou
|
|
first 2011-10
|
|
|
|
last 2017-11-2 added x64 memory interface
|
|
2017-12-29 added newCompressor
|
|
}
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils,
|
|
{$IFDEF FPC}
|
|
zstream,
|
|
FPCGenericStructlist,
|
|
{$ELSE FPC}
|
|
ZLib,
|
|
{$ENDIF}
|
|
CoreClasses, PascalStrings, UnicodeMixedLib;
|
|
|
|
type
|
|
TMemoryStream64 = class(TCoreClassStream)
|
|
private
|
|
FDelta: NativeInt;
|
|
FMemory: Pointer;
|
|
FSize: NativeUInt;
|
|
FPosition: NativeUInt;
|
|
FCapacity: NativeUInt;
|
|
FProtectedMode: Boolean;
|
|
protected
|
|
procedure SetPointer(buffPtr: Pointer; const BuffSize: NativeUInt);
|
|
procedure SetCapacity(NewCapacity: NativeUInt);
|
|
function Realloc(var NewCapacity: NativeUInt): Pointer; virtual;
|
|
property Capacity: NativeUInt read FCapacity write SetCapacity;
|
|
public
|
|
constructor Create;
|
|
constructor CustomCreate(const customDelta: NativeInt);
|
|
destructor Destroy; override;
|
|
|
|
procedure DiscardMemory;
|
|
procedure Clear;
|
|
procedure NewParam(source: TMemoryStream64);
|
|
|
|
property Delta: NativeInt read FDelta write FDelta;
|
|
procedure SetPointerWithProtectedMode(buffPtr: Pointer; const BuffSize: NativeUInt);
|
|
function PositionAsPtr(const APosition: Int64): Pointer; overload;
|
|
function PositionAsPtr: Pointer; overload;
|
|
|
|
procedure LoadFromStream(stream: TCoreClassStream); virtual;
|
|
procedure LoadFromFile(FileName: SystemString);
|
|
procedure SaveToStream(stream: TCoreClassStream); virtual;
|
|
procedure SaveToFile(FileName: SystemString);
|
|
|
|
procedure SetSize(const NewSize: Int64); overload; override;
|
|
procedure SetSize(NewSize: longint); overload; override;
|
|
|
|
function Write64(const buffer; Count: Int64): Int64; virtual;
|
|
function WritePtr(const p: Pointer; Count: Int64): Int64;
|
|
function write(const buffer; Count: longint): longint; overload; override;
|
|
{$IFNDEF FPC} function write(const buffer: TBytes; Offset, Count: longint): longint; overload; override; {$ENDIF}
|
|
procedure WriteBytes(const buff: TBytes);
|
|
|
|
function Read64(var buffer; Count: Int64): Int64; virtual;
|
|
function ReadPtr(const p: Pointer; Count: Int64): Int64;
|
|
function read(var buffer; Count: longint): longint; overload; override;
|
|
{$IFNDEF FPC} function read(buffer: TBytes; Offset, Count: longint): longint; overload; override; {$ENDIF}
|
|
//
|
|
function Seek(const Offset: Int64; origin: TSeekOrigin): Int64; override;
|
|
property Memory: Pointer read FMemory;
|
|
|
|
function CopyFrom(const source: TCoreClassStream; CCount: Int64): Int64; virtual;
|
|
|
|
// Serialized writer
|
|
procedure WriteBool(const buff: Boolean);
|
|
procedure WriteInt8(const buff: ShortInt);
|
|
procedure WriteInt16(const buff: SmallInt);
|
|
procedure WriteInt32(const buff: Integer);
|
|
procedure WriteInt64(const buff: Int64);
|
|
procedure WriteUInt8(const buff: Byte);
|
|
procedure WriteUInt16(const buff: Word);
|
|
procedure WriteUInt32(const buff: Cardinal);
|
|
procedure WriteUInt64(const buff: UInt64);
|
|
procedure WriteSingle(const buff: Single);
|
|
procedure WriteDouble(const buff: Double);
|
|
procedure WriteCurrency(const buff: Currency);
|
|
procedure WriteString(const buff: TPascalString);
|
|
procedure WriteANSI(const buff: TPascalString); overload;
|
|
procedure WriteANSI(const buff: TPascalString; const L: Integer); overload;
|
|
procedure WriteMD5(const buff: TMD5);
|
|
|
|
// Serialized reader
|
|
function ReadBool: Boolean;
|
|
function ReadInt8: ShortInt;
|
|
function ReadInt16: SmallInt;
|
|
function ReadInt32: Integer;
|
|
function ReadInt64: Int64;
|
|
function ReadUInt8: Byte;
|
|
function ReadUInt16: Word;
|
|
function ReadUInt32: Cardinal;
|
|
function ReadUInt64: UInt64;
|
|
function ReadSingle: Single;
|
|
function ReadDouble: Double;
|
|
function ReadCurrency: Currency;
|
|
function PrepareReadString: Boolean;
|
|
function ReadString: TPascalString;
|
|
function ReadANSI(L: Integer): TPascalString;
|
|
function ReadMD5: TMD5;
|
|
end;
|
|
|
|
TMemoryStream64List_Decl = {$IFDEF FPC}specialize {$ENDIF FPC} TGenericsList<TMemoryStream64>;
|
|
|
|
TMemoryStream64List = class(TMemoryStream64List_Decl)
|
|
end;
|
|
|
|
TStream64List = TMemoryStream64List;
|
|
|
|
IMemoryStream64WriteTrigger = interface
|
|
procedure TriggerWrite64(Count: Int64);
|
|
end;
|
|
|
|
TMemoryStream64OfWriteTrigger = class(TMemoryStream64)
|
|
public
|
|
Trigger: IMemoryStream64WriteTrigger;
|
|
constructor Create(ATrigger: IMemoryStream64WriteTrigger);
|
|
function Write64(const buffer; Count: Int64): Int64; override;
|
|
end;
|
|
|
|
IMemoryStream64ReadTrigger = interface
|
|
procedure TriggerRead64(Count: Int64);
|
|
end;
|
|
|
|
TMemoryStream64OfReadTrigger = class(TMemoryStream64)
|
|
public
|
|
Trigger: IMemoryStream64ReadTrigger;
|
|
constructor Create(ATrigger: IMemoryStream64ReadTrigger);
|
|
function Read64(var buffer; Count: Int64): Int64; override;
|
|
end;
|
|
|
|
IMemoryStream64ReadWriteTrigger = interface
|
|
procedure TriggerWrite64(Count: Int64);
|
|
procedure TriggerRead64(Count: Int64);
|
|
end;
|
|
|
|
TMemoryStream64OfReadWriteTrigger = class(TMemoryStream64)
|
|
public
|
|
Trigger: IMemoryStream64ReadWriteTrigger;
|
|
constructor Create(ATrigger: IMemoryStream64ReadWriteTrigger);
|
|
function Read64(var buffer; Count: Int64): Int64; override;
|
|
function Write64(const buffer; Count: Int64): Int64; override;
|
|
end;
|
|
|
|
{$IFDEF FPC}
|
|
|
|
TDecompressionStream = class(zstream.TDecompressionStream)
|
|
public
|
|
end;
|
|
|
|
{ TCompressionStream }
|
|
|
|
TCompressionStream = class(zstream.TCompressionStream)
|
|
public
|
|
constructor Create(stream: TCoreClassStream); overload;
|
|
constructor Create(level: Tcompressionlevel; stream: TCoreClassStream); overload;
|
|
end;
|
|
{$ELSE}
|
|
|
|
TDecompressionStream = ZLib.TZDecompressionStream;
|
|
TCompressionStream = ZLib.TZCompressionStream;
|
|
{$ENDIF}
|
|
TSelectCompressionMethod = (scmNone, scmZLIB, scmZLIB_Fast, scmZLIB_Max, scmDeflate, scmBRRC);
|
|
|
|
function MaxCompressStream(sour, dest: TCoreClassStream): Boolean;
|
|
function FastCompressStream(sour, dest: TCoreClassStream): Boolean;
|
|
function CompressStream(sour, dest: TCoreClassStream): Boolean; overload;
|
|
function DecompressStream(DataPtr: Pointer; siz: NativeInt; dest: TCoreClassStream): Boolean; overload;
|
|
function DecompressStream(sour: TCoreClassStream; dest: TCoreClassStream): Boolean; overload;
|
|
function DecompressStreamToPtr(sour: TCoreClassStream; var dest: Pointer): Boolean; overload;
|
|
function CompressFile(sour, dest: SystemString): Boolean;
|
|
function DecompressFile(sour, dest: SystemString): Boolean;
|
|
|
|
function SelectCompressStream(const scm: TSelectCompressionMethod; const sour, dest: TCoreClassStream): Boolean;
|
|
function SelectDecompressStream(const sour, dest: TCoreClassStream): Boolean;
|
|
|
|
procedure ParallelCompressStream(const scm: TSelectCompressionMethod; const StripNum_: Integer; const sour: TMemoryStream64; const dest: TCoreClassStream); overload;
|
|
procedure ParallelCompressStream(const scm: TSelectCompressionMethod; const sour: TMemoryStream64; const dest: TCoreClassStream); overload;
|
|
procedure ParallelCompressStream(const sour: TMemoryStream64; const dest: TCoreClassStream); overload;
|
|
|
|
procedure ParallelDecompressStream(const sour_, dest_: TCoreClassStream);
|
|
|
|
procedure ParallelCompressFile(const sour, dest: SystemString);
|
|
procedure ParallelDecompressFile(const sour, dest: SystemString);
|
|
|
|
function CompressUTF8(const sour_: TBytes): TBytes;
|
|
function DecompressUTF8(const sour_: TBytes): TBytes;
|
|
|
|
procedure DoStatus(const v: TMemoryStream64); overload;
|
|
|
|
implementation
|
|
|
|
uses DoStatusIO, CoreCompress;
|
|
|
|
procedure TMemoryStream64.SetPointer(buffPtr: Pointer; const BuffSize: NativeUInt);
|
|
begin
|
|
FMemory := buffPtr;
|
|
FSize := BuffSize;
|
|
end;
|
|
|
|
procedure TMemoryStream64.SetCapacity(NewCapacity: NativeUInt);
|
|
begin
|
|
if FProtectedMode then
|
|
Exit;
|
|
SetPointer(Realloc(NewCapacity), FSize);
|
|
FCapacity := NewCapacity;
|
|
end;
|
|
|
|
function TMemoryStream64.Realloc(var NewCapacity: NativeUInt): Pointer;
|
|
begin
|
|
if FProtectedMode then
|
|
Exit(nil);
|
|
|
|
if (NewCapacity > 0) and (NewCapacity <> FSize) then
|
|
NewCapacity := DeltaStep(NewCapacity, FDelta);
|
|
Result := Memory;
|
|
if NewCapacity <> FCapacity then
|
|
begin
|
|
if NewCapacity = 0 then
|
|
begin
|
|
System.FreeMemory(Memory);
|
|
Result := nil;
|
|
end
|
|
else
|
|
begin
|
|
if Capacity = 0 then
|
|
Result := System.GetMemory(NewCapacity)
|
|
else
|
|
Result := System.ReallocMemory(Result, NewCapacity);
|
|
if Result = nil then
|
|
RaiseInfo('Out of memory while expanding memory stream');
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
constructor TMemoryStream64.Create;
|
|
begin
|
|
CustomCreate(256);
|
|
end;
|
|
|
|
constructor TMemoryStream64.CustomCreate(const customDelta: NativeInt);
|
|
begin
|
|
inherited Create;
|
|
FDelta := customDelta;
|
|
FMemory := nil;
|
|
FSize := 0;
|
|
FPosition := 0;
|
|
FCapacity := 0;
|
|
FProtectedMode := False;
|
|
end;
|
|
|
|
destructor TMemoryStream64.Destroy;
|
|
begin
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TMemoryStream64.DiscardMemory;
|
|
begin
|
|
if FProtectedMode then
|
|
Exit;
|
|
FMemory := nil;
|
|
FSize := 0;
|
|
FPosition := 0;
|
|
FCapacity := 0;
|
|
end;
|
|
|
|
procedure TMemoryStream64.Clear;
|
|
begin
|
|
if FProtectedMode then
|
|
Exit;
|
|
SetCapacity(0);
|
|
FSize := 0;
|
|
FPosition := 0;
|
|
end;
|
|
|
|
procedure TMemoryStream64.NewParam(source: TMemoryStream64);
|
|
begin
|
|
Clear;
|
|
FDelta := source.FDelta;
|
|
FMemory := source.FMemory;
|
|
FSize := source.FSize;
|
|
FPosition := source.FPosition;
|
|
FCapacity := source.FCapacity;
|
|
FProtectedMode := source.FProtectedMode;
|
|
end;
|
|
|
|
procedure TMemoryStream64.SetPointerWithProtectedMode(buffPtr: Pointer; const BuffSize: NativeUInt);
|
|
begin
|
|
Clear;
|
|
FMemory := buffPtr;
|
|
FSize := BuffSize;
|
|
FPosition := 0;
|
|
FProtectedMode := True;
|
|
end;
|
|
|
|
function TMemoryStream64.PositionAsPtr(const APosition: Int64): Pointer;
|
|
begin
|
|
Result := Pointer(NativeUInt(FMemory) + APosition);
|
|
end;
|
|
|
|
function TMemoryStream64.PositionAsPtr: Pointer;
|
|
begin
|
|
Result := Pointer(NativeUInt(FMemory) + FPosition);
|
|
end;
|
|
|
|
procedure TMemoryStream64.LoadFromStream(stream: TCoreClassStream);
|
|
const
|
|
ChunkSize = 64 * 1024 * 1024;
|
|
var
|
|
p: Pointer;
|
|
j: NativeInt;
|
|
Num: NativeInt;
|
|
Rest: NativeInt;
|
|
begin
|
|
if FProtectedMode then
|
|
Exit;
|
|
|
|
stream.Position := 0;
|
|
SetSize(stream.Size);
|
|
if stream.Size > 0 then
|
|
begin
|
|
p := FMemory;
|
|
if stream.Size > ChunkSize then
|
|
begin
|
|
{ Calculate number of full chunks that will fit into the buffer }
|
|
Num := stream.Size div ChunkSize;
|
|
{ Calculate remaining bytes }
|
|
Rest := stream.Size mod ChunkSize;
|
|
|
|
{ Process full chunks }
|
|
for j := 0 to Num - 1 do
|
|
begin
|
|
stream.ReadBuffer(p^, ChunkSize);
|
|
p := Pointer(NativeUInt(p) + ChunkSize);
|
|
end;
|
|
|
|
{ Process remaining bytes }
|
|
if Rest > 0 then
|
|
begin
|
|
stream.ReadBuffer(p^, Rest);
|
|
p := Pointer(NativeUInt(p) + Rest);
|
|
end;
|
|
end
|
|
else
|
|
stream.ReadBuffer(p^, stream.Size);
|
|
end;
|
|
end;
|
|
|
|
procedure TMemoryStream64.LoadFromFile(FileName: SystemString);
|
|
var
|
|
stream: TCoreClassStream;
|
|
begin
|
|
stream := TCoreClassFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
|
|
try
|
|
LoadFromStream(stream);
|
|
finally
|
|
DisposeObject(stream);
|
|
end;
|
|
end;
|
|
|
|
procedure TMemoryStream64.SaveToStream(stream: TCoreClassStream);
|
|
const
|
|
ChunkSize = 64 * 1024 * 1024;
|
|
var
|
|
p: Pointer;
|
|
j: NativeInt;
|
|
Num: NativeInt;
|
|
Rest: NativeInt;
|
|
begin
|
|
if Size > 0 then
|
|
begin
|
|
p := FMemory;
|
|
if Size > ChunkSize then
|
|
begin
|
|
{ Calculate number of full chunks that will fit into the buffer }
|
|
Num := Size div ChunkSize;
|
|
{ Calculate remaining bytes }
|
|
Rest := Size mod ChunkSize;
|
|
|
|
{ Process full chunks }
|
|
for j := 0 to Num - 1 do
|
|
begin
|
|
stream.WriteBuffer(p^, ChunkSize);
|
|
p := Pointer(NativeUInt(p) + ChunkSize);
|
|
end;
|
|
|
|
{ Process remaining bytes }
|
|
if Rest > 0 then
|
|
begin
|
|
stream.WriteBuffer(p^, Rest);
|
|
p := Pointer(NativeUInt(p) + Rest);
|
|
end;
|
|
end
|
|
else
|
|
stream.WriteBuffer(p^, Size);
|
|
end;
|
|
end;
|
|
|
|
procedure TMemoryStream64.SaveToFile(FileName: SystemString);
|
|
var
|
|
stream: TCoreClassStream;
|
|
begin
|
|
stream := TCoreClassFileStream.Create(FileName, fmCreate);
|
|
try
|
|
SaveToStream(stream);
|
|
finally
|
|
DisposeObject(stream);
|
|
end;
|
|
end;
|
|
|
|
procedure TMemoryStream64.SetSize(const NewSize: Int64);
|
|
var
|
|
OldPosition: Int64;
|
|
begin
|
|
if FProtectedMode then
|
|
Exit;
|
|
|
|
OldPosition := FPosition;
|
|
SetCapacity(NewSize);
|
|
FSize := NewSize;
|
|
if OldPosition > NewSize then
|
|
Seek(0, TSeekOrigin.soEnd);
|
|
end;
|
|
|
|
procedure TMemoryStream64.SetSize(NewSize: longint);
|
|
begin
|
|
SetSize(Int64(NewSize));
|
|
end;
|
|
|
|
function TMemoryStream64.Write64(const buffer; Count: Int64): Int64;
|
|
var
|
|
p: Int64;
|
|
begin
|
|
if FProtectedMode then
|
|
begin
|
|
Result := 0;
|
|
Exit;
|
|
end;
|
|
|
|
if (Count > 0) then
|
|
begin
|
|
p := FPosition;
|
|
p := p + Count;
|
|
if p > 0 then
|
|
begin
|
|
if p > FSize then
|
|
begin
|
|
if p > FCapacity then
|
|
SetCapacity(p);
|
|
FSize := p;
|
|
end;
|
|
CopyPtr(@buffer, PByte(NativeUInt(FMemory) + FPosition), Count);
|
|
FPosition := p;
|
|
Result := Count;
|
|
Exit;
|
|
end;
|
|
end;
|
|
Result := 0;
|
|
end;
|
|
|
|
function TMemoryStream64.WritePtr(const p: Pointer; Count: Int64): Int64;
|
|
begin
|
|
Result := Write64(p^, Count);
|
|
end;
|
|
|
|
function TMemoryStream64.write(const buffer; Count: longint): longint;
|
|
begin
|
|
Result := Write64(buffer, Count);
|
|
end;
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
|
|
function TMemoryStream64.write(const buffer: TBytes; Offset, Count: longint): longint;
|
|
var
|
|
p: Int64;
|
|
begin
|
|
if Count > 0 then
|
|
begin
|
|
p := FPosition;
|
|
p := p + Count;
|
|
if p > 0 then
|
|
begin
|
|
if p > FSize then
|
|
begin
|
|
if p > FCapacity then
|
|
SetCapacity(p);
|
|
FSize := p;
|
|
end;
|
|
CopyPtr(@buffer[Offset], PByte(NativeUInt(FMemory) + FPosition), Count);
|
|
FPosition := p;
|
|
Result := Count;
|
|
Exit;
|
|
end;
|
|
end;
|
|
Result := 0;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
|
|
procedure TMemoryStream64.WriteBytes(const buff: TBytes);
|
|
begin
|
|
if Length(buff) > 0 then
|
|
WritePtr(@buff[0], Length(buff));
|
|
end;
|
|
|
|
function TMemoryStream64.Read64(var buffer; Count: Int64): Int64;
|
|
begin
|
|
if Count > 0 then
|
|
begin
|
|
Result := FSize;
|
|
Result := Result - FPosition;
|
|
if Result > 0 then
|
|
begin
|
|
if Result > Count then
|
|
Result := Count;
|
|
CopyPtr(PByte(NativeUInt(FMemory) + FPosition), @buffer, Result);
|
|
inc(FPosition, Result);
|
|
Exit;
|
|
end;
|
|
end;
|
|
Result := 0;
|
|
end;
|
|
|
|
function TMemoryStream64.ReadPtr(const p: Pointer; Count: Int64): Int64;
|
|
begin
|
|
Result := Read64(p^, Count);
|
|
end;
|
|
|
|
function TMemoryStream64.read(var buffer; Count: longint): longint;
|
|
begin
|
|
Result := Read64(buffer, Count);
|
|
end;
|
|
|
|
{$IFNDEF FPC}
|
|
|
|
|
|
function TMemoryStream64.read(buffer: TBytes; Offset, Count: longint): longint;
|
|
var
|
|
p: Int64;
|
|
begin
|
|
if Count > 0 then
|
|
begin
|
|
p := FSize;
|
|
p := p - FPosition;
|
|
if p > 0 then
|
|
begin
|
|
if p > Count then
|
|
p := Count;
|
|
|
|
CopyPtr(PByte(NativeUInt(FMemory) + FPosition), @buffer[Offset], p);
|
|
inc(FPosition, p);
|
|
Result := p;
|
|
Exit;
|
|
end;
|
|
end;
|
|
Result := 0;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
|
|
function TMemoryStream64.Seek(const Offset: Int64; origin: TSeekOrigin): Int64;
|
|
begin
|
|
case origin of
|
|
TSeekOrigin.soBeginning: FPosition := Offset;
|
|
TSeekOrigin.soCurrent: inc(FPosition, Offset);
|
|
TSeekOrigin.soEnd: FPosition := FSize + Offset;
|
|
end;
|
|
Result := FPosition;
|
|
end;
|
|
|
|
function TMemoryStream64.CopyFrom(const source: TCoreClassStream; CCount: Int64): Int64;
|
|
const
|
|
MaxBufSize = $F000;
|
|
var
|
|
BufSize, n: Int64;
|
|
buffer: PByte;
|
|
begin
|
|
if FProtectedMode then
|
|
RaiseInfo('protected mode');
|
|
|
|
if source is TMemoryStream64 then
|
|
begin
|
|
WritePtr(TMemoryStream64(source).PositionAsPtr, CCount);
|
|
TMemoryStream64(source).Position := TMemoryStream64(source).FPosition + CCount;
|
|
Result := CCount;
|
|
Exit;
|
|
end;
|
|
|
|
if CCount <= 0 then
|
|
begin
|
|
source.Position := 0;
|
|
CCount := source.Size;
|
|
end;
|
|
|
|
Result := CCount;
|
|
if CCount > MaxBufSize then
|
|
BufSize := MaxBufSize
|
|
else
|
|
BufSize := CCount;
|
|
|
|
buffer := System.GetMemory(BufSize);
|
|
try
|
|
while CCount <> 0 do
|
|
begin
|
|
if CCount > BufSize then
|
|
n := BufSize
|
|
else
|
|
n := CCount;
|
|
source.read(buffer^, n);
|
|
WritePtr(buffer, n);
|
|
dec(CCount, n);
|
|
end;
|
|
finally
|
|
System.FreeMem(buffer);
|
|
end;
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteBool(const buff: Boolean);
|
|
begin
|
|
WritePtr(@buff, 1);
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteInt8(const buff: ShortInt);
|
|
begin
|
|
WritePtr(@buff, 1);
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteInt16(const buff: SmallInt);
|
|
begin
|
|
WritePtr(@buff, 2);
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteInt32(const buff: Integer);
|
|
begin
|
|
WritePtr(@buff, 4);
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteInt64(const buff: Int64);
|
|
begin
|
|
WritePtr(@buff, 8);
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteUInt8(const buff: Byte);
|
|
begin
|
|
WritePtr(@buff, 1);
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteUInt16(const buff: Word);
|
|
begin
|
|
WritePtr(@buff, 2);
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteUInt32(const buff: Cardinal);
|
|
begin
|
|
WritePtr(@buff, 4);
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteUInt64(const buff: UInt64);
|
|
begin
|
|
WritePtr(@buff, 8);
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteSingle(const buff: Single);
|
|
begin
|
|
WritePtr(@buff, 4);
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteDouble(const buff: Double);
|
|
begin
|
|
WritePtr(@buff, 8);
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteCurrency(const buff: Currency);
|
|
begin
|
|
WriteDouble(buff);
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteString(const buff: TPascalString);
|
|
var
|
|
b: TBytes;
|
|
begin
|
|
b := buff.Bytes;
|
|
WriteUInt32(Length(b));
|
|
if Length(b) > 0 then
|
|
begin
|
|
WritePtr(@b[0], Length(b));
|
|
SetLength(b, 0);
|
|
end;
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteANSI(const buff: TPascalString);
|
|
var
|
|
b: TBytes;
|
|
begin
|
|
b := buff.ANSI;
|
|
if Length(b) > 0 then
|
|
begin
|
|
WritePtr(@b[0], Length(b));
|
|
SetLength(b, 0);
|
|
end;
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteANSI(const buff: TPascalString; const L: Integer);
|
|
var
|
|
b: TBytes;
|
|
begin
|
|
b := buff.ANSI;
|
|
if L > 0 then
|
|
begin
|
|
WritePtr(@b[0], L);
|
|
SetLength(b, 0);
|
|
end;
|
|
end;
|
|
|
|
procedure TMemoryStream64.WriteMD5(const buff: TMD5);
|
|
begin
|
|
WritePtr(@buff, 16);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadBool: Boolean;
|
|
begin
|
|
ReadPtr(@Result, 1);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadInt8: ShortInt;
|
|
begin
|
|
ReadPtr(@Result, 1);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadInt16: SmallInt;
|
|
begin
|
|
ReadPtr(@Result, 2);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadInt32: Integer;
|
|
begin
|
|
ReadPtr(@Result, 4);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadInt64: Int64;
|
|
begin
|
|
ReadPtr(@Result, 8);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadUInt8: Byte;
|
|
begin
|
|
ReadPtr(@Result, 1);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadUInt16: Word;
|
|
begin
|
|
ReadPtr(@Result, 2);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadUInt32: Cardinal;
|
|
begin
|
|
ReadPtr(@Result, 4);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadUInt64: UInt64;
|
|
begin
|
|
ReadPtr(@Result, 8);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadSingle: Single;
|
|
begin
|
|
ReadPtr(@Result, 4);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadDouble: Double;
|
|
begin
|
|
ReadPtr(@Result, 8);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadCurrency: Currency;
|
|
begin
|
|
Result := ReadDouble();
|
|
end;
|
|
|
|
function TMemoryStream64.PrepareReadString: Boolean;
|
|
begin
|
|
Result := (Position + 4 <= Size) and (Position + 4 + PCardinal(PositionAsPtr())^ <= Size);
|
|
end;
|
|
|
|
function TMemoryStream64.ReadString: TPascalString;
|
|
var
|
|
L: Cardinal;
|
|
b: TBytes;
|
|
begin
|
|
L := ReadUInt32;
|
|
if L > 0 then
|
|
begin
|
|
SetLength(b, L);
|
|
ReadPtr(@b[0], L);
|
|
Result.Bytes := b;
|
|
SetLength(b, 0);
|
|
end;
|
|
end;
|
|
|
|
function TMemoryStream64.ReadANSI(L: Integer): TPascalString;
|
|
var
|
|
b: TBytes;
|
|
begin
|
|
if L > 0 then
|
|
begin
|
|
SetLength(b, L);
|
|
ReadPtr(@b[0], L);
|
|
Result.ANSI := b;
|
|
SetLength(b, 0);
|
|
end;
|
|
end;
|
|
|
|
function TMemoryStream64.ReadMD5: TMD5;
|
|
begin
|
|
ReadPtr(@Result, 16);
|
|
end;
|
|
|
|
constructor TMemoryStream64OfWriteTrigger.Create(ATrigger: IMemoryStream64WriteTrigger);
|
|
begin
|
|
inherited Create;
|
|
Trigger := ATrigger;
|
|
end;
|
|
|
|
function TMemoryStream64OfWriteTrigger.Write64(const buffer; Count: Int64): Int64;
|
|
begin
|
|
Result := inherited Write64(buffer, Count);
|
|
if Assigned(Trigger) then
|
|
Trigger.TriggerWrite64(Count);
|
|
end;
|
|
|
|
constructor TMemoryStream64OfReadTrigger.Create(ATrigger: IMemoryStream64ReadTrigger);
|
|
begin
|
|
inherited Create;
|
|
Trigger := ATrigger;
|
|
end;
|
|
|
|
function TMemoryStream64OfReadTrigger.Read64(var buffer; Count: Int64): Int64;
|
|
begin
|
|
Result := inherited Read64(buffer, Count);
|
|
if Assigned(Trigger) then
|
|
Trigger.TriggerRead64(Count);
|
|
end;
|
|
|
|
constructor TMemoryStream64OfReadWriteTrigger.Create(ATrigger: IMemoryStream64ReadWriteTrigger);
|
|
begin
|
|
inherited Create;
|
|
Trigger := ATrigger;
|
|
end;
|
|
|
|
function TMemoryStream64OfReadWriteTrigger.Read64(var buffer; Count: Int64): Int64;
|
|
begin
|
|
Result := inherited Read64(buffer, Count);
|
|
if Assigned(Trigger) then
|
|
Trigger.TriggerRead64(Count);
|
|
end;
|
|
|
|
function TMemoryStream64OfReadWriteTrigger.Write64(const buffer; Count: Int64): Int64;
|
|
begin
|
|
Result := inherited Write64(buffer, Count);
|
|
if Assigned(Trigger) then
|
|
Trigger.TriggerWrite64(Count);
|
|
end;
|
|
|
|
{$IFDEF FPC}
|
|
|
|
|
|
constructor TCompressionStream.Create(stream: TCoreClassStream);
|
|
begin
|
|
inherited Create(clFastest, stream);
|
|
end;
|
|
|
|
constructor TCompressionStream.Create(level: Tcompressionlevel; stream: TCoreClassStream);
|
|
begin
|
|
inherited Create(level, stream);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
|
|
function MaxCompressStream(sour, dest: TCoreClassStream): Boolean;
|
|
var
|
|
cStream: TCompressionStream;
|
|
siz_: Int64;
|
|
begin
|
|
Result := False;
|
|
try
|
|
siz_ := sour.Size;
|
|
dest.WriteBuffer(siz_, 8);
|
|
if sour.Size > 0 then
|
|
begin
|
|
sour.Position := 0;
|
|
cStream := TCompressionStream.Create(clMax, dest);
|
|
Result := cStream.CopyFrom(sour, siz_) = siz_;
|
|
DisposeObject(cStream);
|
|
end;
|
|
except
|
|
end;
|
|
end;
|
|
|
|
function FastCompressStream(sour, dest: TCoreClassStream): Boolean;
|
|
var
|
|
cStream: TCompressionStream;
|
|
siz_: Int64;
|
|
begin
|
|
Result := False;
|
|
try
|
|
siz_ := sour.Size;
|
|
dest.WriteBuffer(siz_, 8);
|
|
if sour.Size > 0 then
|
|
begin
|
|
sour.Position := 0;
|
|
cStream := TCompressionStream.Create(clFastest, dest);
|
|
Result := cStream.CopyFrom(sour, siz_) = siz_;
|
|
DisposeObject(cStream);
|
|
end;
|
|
except
|
|
end;
|
|
end;
|
|
|
|
function CompressStream(sour, dest: TCoreClassStream): Boolean;
|
|
var
|
|
cStream: TCompressionStream;
|
|
siz_: Int64;
|
|
begin
|
|
Result := False;
|
|
try
|
|
siz_ := sour.Size;
|
|
dest.WriteBuffer(siz_, 8);
|
|
if sour.Size > 0 then
|
|
begin
|
|
sour.Position := 0;
|
|
cStream := TCompressionStream.Create(clDefault, dest);
|
|
Result := cStream.CopyFrom(sour, siz_) = siz_;
|
|
DisposeObject(cStream);
|
|
end;
|
|
except
|
|
end;
|
|
end;
|
|
|
|
function DecompressStream(DataPtr: Pointer; siz: NativeInt; dest: TCoreClassStream): Boolean;
|
|
var
|
|
m64: TMemoryStream64;
|
|
begin
|
|
m64 := TMemoryStream64.Create;
|
|
m64.SetPointer(DataPtr, siz);
|
|
Result := DecompressStream(m64, dest);
|
|
DisposeObject(m64);
|
|
end;
|
|
|
|
function DecompressStream(sour: TCoreClassStream; dest: TCoreClassStream): Boolean;
|
|
var
|
|
dcStream: TDecompressionStream;
|
|
dSiz: Int64;
|
|
iPos: Int64;
|
|
begin
|
|
Result := False;
|
|
sour.ReadBuffer(dSiz, 8);
|
|
if dSiz > 0 then
|
|
begin
|
|
iPos := dest.Position;
|
|
dest.Size := iPos + dSiz;
|
|
dest.Position := iPos;
|
|
try
|
|
dcStream := TDecompressionStream.Create(sour);
|
|
Result := dest.CopyFrom(dcStream, dSiz) = dSiz;
|
|
DisposeObject(dcStream);
|
|
except
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function DecompressStreamToPtr(sour: TCoreClassStream; var dest: Pointer): Boolean;
|
|
var
|
|
dcStream: TDecompressionStream;
|
|
dSiz: Int64;
|
|
begin
|
|
Result := False;
|
|
try
|
|
sour.ReadBuffer(dSiz, 8);
|
|
if dSiz > 0 then
|
|
begin
|
|
dcStream := TDecompressionStream.Create(sour);
|
|
dest := System.GetMemory(dSiz);
|
|
Result := dcStream.read(dest^, dSiz) = dSiz;
|
|
DisposeObject(dcStream);
|
|
end;
|
|
except
|
|
end;
|
|
end;
|
|
|
|
function CompressFile(sour, dest: SystemString): Boolean;
|
|
var
|
|
s_fs, d_fs: TCoreClassFileStream;
|
|
begin
|
|
s_fs := TCoreClassFileStream.Create(sour, fmOpenRead or fmShareDenyNone);
|
|
d_fs := TCoreClassFileStream.Create(dest, fmCreate);
|
|
Result := CompressStream(s_fs, d_fs);
|
|
DisposeObject(s_fs);
|
|
DisposeObject(d_fs);
|
|
end;
|
|
|
|
function DecompressFile(sour, dest: SystemString): Boolean;
|
|
var
|
|
s_fs, d_fs: TCoreClassFileStream;
|
|
begin
|
|
s_fs := TCoreClassFileStream.Create(sour, fmOpenRead or fmShareDenyNone);
|
|
d_fs := TCoreClassFileStream.Create(dest, fmCreate);
|
|
Result := DecompressStream(s_fs, d_fs);
|
|
DisposeObject(s_fs);
|
|
DisposeObject(d_fs);
|
|
end;
|
|
|
|
function SelectCompressStream(const scm: TSelectCompressionMethod; const sour, dest: TCoreClassStream): Boolean;
|
|
var
|
|
scm_b: Byte;
|
|
siz_: Int64;
|
|
begin
|
|
Result := False;
|
|
scm_b := Byte(scm);
|
|
if dest.write(scm_b, 1) <> 1 then
|
|
Exit;
|
|
sour.Position := 0;
|
|
|
|
try
|
|
case scm of
|
|
scmNone:
|
|
begin
|
|
siz_ := sour.Size;
|
|
dest.write(siz_, 8);
|
|
Result := dest.CopyFrom(sour, siz_) = siz_;
|
|
end;
|
|
scmZLIB: Result := CompressStream(sour, dest);
|
|
scmZLIB_Fast: Result := FastCompressStream(sour, dest);
|
|
scmZLIB_Max: Result := MaxCompressStream(sour, dest);
|
|
scmDeflate: Result := DeflateCompressStream(sour, dest);
|
|
scmBRRC: Result := BRRCCompressStream(sour, dest);
|
|
end;
|
|
except
|
|
end;
|
|
end;
|
|
|
|
function SelectDecompressStream(const sour, dest: TCoreClassStream): Boolean;
|
|
var
|
|
scm: Byte;
|
|
siz_: Int64;
|
|
begin
|
|
Result := False;
|
|
if sour.read(scm, 1) <> 1 then
|
|
Exit;
|
|
|
|
try
|
|
case TSelectCompressionMethod(scm) of
|
|
scmNone:
|
|
begin
|
|
if sour.read(siz_, 8) <> 8 then
|
|
Exit;
|
|
Result := dest.CopyFrom(sour, siz_) = siz_;
|
|
end;
|
|
scmZLIB, scmZLIB_Fast, scmZLIB_Max: Result := DecompressStream(sour, dest);
|
|
scmDeflate: Result := DeflateDecompressStream(sour, dest);
|
|
scmBRRC: Result := BRRCDecompressStream(sour, dest);
|
|
end;
|
|
except
|
|
end;
|
|
end;
|
|
|
|
procedure ParallelCompressStream(const scm: TSelectCompressionMethod; const StripNum_: Integer; const sour: TMemoryStream64; const dest: TCoreClassStream);
|
|
var
|
|
StripNum: Integer;
|
|
sourStrips: TStream64List;
|
|
StripArry: array of TMemoryStream64;
|
|
|
|
{$IFDEF Parallel}
|
|
{$IFDEF FPC}
|
|
procedure Nested_ParallelFor(pass: Integer);
|
|
begin
|
|
SelectCompressStream(scm, sourStrips[pass], StripArry[pass]);
|
|
end;
|
|
{$ENDIF FPC}
|
|
{$ELSE Parallel}
|
|
procedure DoFor;
|
|
var
|
|
pass: Integer;
|
|
begin
|
|
for pass := 0 to Length(StripArry) - 1 do
|
|
begin
|
|
SelectCompressStream(scm, sourStrips[pass], StripArry[pass]);
|
|
end;
|
|
end;
|
|
{$ENDIF Parallel}
|
|
procedure BuildBuff;
|
|
var
|
|
strip_siz, strip_m: Int64;
|
|
p: Int64;
|
|
m64: TMemoryStream64;
|
|
i: Integer;
|
|
begin
|
|
sourStrips := TStream64List.Create;
|
|
strip_siz := sour.Size div StripNum;
|
|
p := 0;
|
|
while True do
|
|
begin
|
|
if p + strip_siz < sour.Size then
|
|
begin
|
|
m64 := TMemoryStream64.Create;
|
|
m64.SetPointerWithProtectedMode(sour.PositionAsPtr(p), strip_siz);
|
|
sourStrips.Add(m64);
|
|
inc(p, strip_siz);
|
|
end
|
|
else
|
|
begin
|
|
if sour.Size - p > 0 then
|
|
begin
|
|
m64 := TMemoryStream64.Create;
|
|
m64.SetPointerWithProtectedMode(sour.PositionAsPtr(p), sour.Size - p);
|
|
sourStrips.Add(m64);
|
|
end;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
SetLength(StripArry, sourStrips.Count);
|
|
for i := 0 to sourStrips.Count - 1 do
|
|
StripArry[i] := TMemoryStream64.CustomCreate(1024);
|
|
end;
|
|
|
|
procedure BuildOutput;
|
|
var
|
|
L: Integer;
|
|
siz_: Int64;
|
|
i: Integer;
|
|
begin
|
|
L := Length(StripArry);
|
|
dest.write(L, 4);
|
|
for i := 0 to L - 1 do
|
|
begin
|
|
siz_ := StripArry[i].Size;
|
|
dest.write(siz_, 8);
|
|
dest.write(StripArry[i].Memory^, StripArry[i].Size);
|
|
|
|
DisposeObject(sourStrips[i]);
|
|
DisposeObject(StripArry[i]);
|
|
end;
|
|
end;
|
|
|
|
procedure FreeBuff;
|
|
begin
|
|
DisposeObject(sourStrips);
|
|
SetLength(StripArry, 0);
|
|
end;
|
|
|
|
begin
|
|
if StripNum_ <= 0 then
|
|
StripNum := 1
|
|
else
|
|
StripNum := StripNum_;
|
|
BuildBuff;
|
|
|
|
{$IFDEF Parallel}
|
|
{$IFDEF FPC}
|
|
FPCParallelFor(@Nested_ParallelFor, 0, Length(StripArry) - 1);
|
|
{$ELSE FPC}
|
|
DelphiParallelFor(0, Length(StripArry) - 1, procedure(pass: Integer)
|
|
begin
|
|
SelectCompressStream(scm, sourStrips[pass], StripArry[pass]);
|
|
end);
|
|
{$ENDIF FPC}
|
|
{$ELSE Parallel}
|
|
DoFor;
|
|
{$ENDIF Parallel}
|
|
BuildOutput;
|
|
FreeBuff;
|
|
end;
|
|
|
|
procedure ParallelCompressStream(const scm: TSelectCompressionMethod; const sour: TMemoryStream64; const dest: TCoreClassStream);
|
|
begin
|
|
ParallelCompressStream(scm, sour.Size div 8192, sour, dest);
|
|
end;
|
|
|
|
procedure ParallelCompressStream(const sour: TMemoryStream64; const dest: TCoreClassStream);
|
|
begin
|
|
ParallelCompressStream(scmZLIB, sour, dest);
|
|
end;
|
|
|
|
procedure ParallelDecompressStream(const sour_, dest_: TCoreClassStream);
|
|
type
|
|
TPara_strip_ = record
|
|
sour, dest: TMemoryStream64;
|
|
end;
|
|
|
|
PPara_strip_ = ^TPara_strip_;
|
|
var
|
|
StripArry: array of TPara_strip_;
|
|
|
|
{$IFDEF Parallel}
|
|
{$IFDEF FPC}
|
|
procedure Nested_ParallelFor(pass: Integer);
|
|
begin
|
|
SelectDecompressStream(StripArry[pass].sour, StripArry[pass].dest);
|
|
end;
|
|
{$ENDIF FPC}
|
|
{$ELSE Parallel}
|
|
procedure DoFor;
|
|
var
|
|
pass: Integer;
|
|
begin
|
|
for pass := 0 to Length(StripArry) - 1 do
|
|
begin
|
|
SelectDecompressStream(StripArry[pass].sour, StripArry[pass].dest);
|
|
end;
|
|
end;
|
|
{$ENDIF Parallel}
|
|
function BuildBuff_Stream64(stream: TMemoryStream64): Boolean;
|
|
var
|
|
strip_num: Integer;
|
|
i: Integer;
|
|
p, siz_, ss: Int64;
|
|
begin
|
|
Result := False;
|
|
ss := stream.Size;
|
|
p := stream.Position;
|
|
if p + 4 > ss then
|
|
Exit;
|
|
strip_num := PInteger(stream.PositionAsPtr(p))^;
|
|
inc(p, 4);
|
|
|
|
SetLength(StripArry, strip_num);
|
|
for i := 0 to strip_num - 1 do
|
|
begin
|
|
StripArry[i].sour := TMemoryStream64.Create;
|
|
if p + 4 > ss then
|
|
Exit;
|
|
siz_ := PInt64(stream.PositionAsPtr(p))^;
|
|
inc(p, 8);
|
|
if p + siz_ > ss then
|
|
Exit;
|
|
StripArry[i].sour.SetPointerWithProtectedMode(stream.PositionAsPtr(p), siz_);
|
|
inc(p, siz_);
|
|
StripArry[i].sour.Position := 0;
|
|
StripArry[i].dest := TMemoryStream64.CustomCreate(1024);
|
|
end;
|
|
stream.Position := p;
|
|
Result := True;
|
|
end;
|
|
|
|
function BuildBuff_Stream(stream: TCoreClassStream): Boolean;
|
|
var
|
|
strip_num: Integer;
|
|
i: Integer;
|
|
siz_: Int64;
|
|
begin
|
|
Result := False;
|
|
if stream.read(strip_num, 4) <> 4 then
|
|
Exit;
|
|
|
|
SetLength(StripArry, strip_num);
|
|
for i := 0 to strip_num - 1 do
|
|
begin
|
|
StripArry[i].sour := TMemoryStream64.CustomCreate(1024);
|
|
StripArry[i].dest := TMemoryStream64.CustomCreate(1024);
|
|
end;
|
|
|
|
for i := 0 to strip_num - 1 do
|
|
begin
|
|
if stream.read(siz_, 8) <> 8 then
|
|
Exit;
|
|
if StripArry[i].sour.CopyFrom(stream, siz_) <> siz_ then
|
|
Exit;
|
|
StripArry[i].sour.Position := 0;
|
|
end;
|
|
Result := True;
|
|
end;
|
|
|
|
procedure BuildOutput;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to Length(StripArry) - 1 do
|
|
begin
|
|
dest_.write(StripArry[i].dest.Memory^, StripArry[i].dest.Size);
|
|
DisposeObject(StripArry[i].sour);
|
|
DisposeObject(StripArry[i].dest);
|
|
end;
|
|
end;
|
|
|
|
procedure FreeBuff;
|
|
begin
|
|
SetLength(StripArry, 0);
|
|
end;
|
|
|
|
var
|
|
preDone: Boolean;
|
|
begin
|
|
if sour_ is TMemoryStream64 then
|
|
preDone := BuildBuff_Stream64(TMemoryStream64(sour_))
|
|
else
|
|
preDone := BuildBuff_Stream(sour_);
|
|
|
|
if not preDone then
|
|
begin
|
|
FreeBuff;
|
|
Exit;
|
|
end;
|
|
|
|
{$IFDEF Parallel}
|
|
{$IFDEF FPC}
|
|
FPCParallelFor(@Nested_ParallelFor, 0, Length(StripArry) - 1);
|
|
{$ELSE FPC}
|
|
DelphiParallelFor(0, Length(StripArry) - 1, procedure(pass: Integer)
|
|
begin
|
|
SelectDecompressStream(StripArry[pass].sour, StripArry[pass].dest);
|
|
end);
|
|
{$ENDIF FPC}
|
|
{$ELSE Parallel}
|
|
DoFor;
|
|
{$ENDIF Parallel}
|
|
BuildOutput;
|
|
FreeBuff;
|
|
end;
|
|
|
|
procedure ParallelCompressFile(const sour, dest: SystemString);
|
|
var
|
|
s_fs: TMemoryStream64;
|
|
d_fs: TCoreClassFileStream;
|
|
begin
|
|
s_fs := TMemoryStream64.Create;
|
|
s_fs.LoadFromFile(sour);
|
|
d_fs := TCoreClassFileStream.Create(dest, fmCreate);
|
|
ParallelCompressStream(s_fs, d_fs);
|
|
DisposeObject(s_fs);
|
|
DisposeObject(d_fs);
|
|
end;
|
|
|
|
procedure ParallelDecompressFile(const sour, dest: SystemString);
|
|
var
|
|
s_fs: TMemoryStream64;
|
|
d_fs: TCoreClassFileStream;
|
|
begin
|
|
s_fs := TMemoryStream64.Create;
|
|
s_fs.LoadFromFile(sour);
|
|
d_fs := TCoreClassFileStream.Create(dest, fmCreate);
|
|
ParallelDecompressStream(s_fs, d_fs);
|
|
DisposeObject(s_fs);
|
|
DisposeObject(d_fs);
|
|
end;
|
|
|
|
function CompressUTF8(const sour_: TBytes): TBytes;
|
|
var
|
|
cStream: TCompressionStream;
|
|
dest: TMemoryStream64;
|
|
begin
|
|
if Length(sour_) > 10 then
|
|
begin
|
|
dest := TMemoryStream64.Create;
|
|
cStream := TCompressionStream.Create(clMax, dest);
|
|
cStream.write(sour_[0], Length(sour_));
|
|
DisposeObject(cStream);
|
|
if dest.Size + 6 < Length(sour_) then
|
|
begin
|
|
SetLength(Result, dest.Size + 6);
|
|
Result[0] := $FF;
|
|
Result[1] := $FF;
|
|
PInteger(@Result[2])^ := Length(sour_);
|
|
CopyPtr(dest.Memory, @Result[6], dest.Size);
|
|
end
|
|
else
|
|
Result := sour_;
|
|
DisposeObject(dest);
|
|
end
|
|
else
|
|
Result := sour_;
|
|
end;
|
|
|
|
function DecompressUTF8(const sour_: TBytes): TBytes;
|
|
var
|
|
dcStream: TDecompressionStream;
|
|
sour: TMemoryStream64;
|
|
siz: Integer;
|
|
begin
|
|
if Length(sour_) > 6 then
|
|
begin
|
|
if (sour_[0] = $FF) and (sour_[1] = $FF) then
|
|
begin
|
|
siz := PInteger(@sour_[2])^;
|
|
sour := TMemoryStream64.Create();
|
|
sour.SetPointer(@sour_[6], Length(sour_) - 6);
|
|
dcStream := TDecompressionStream.Create(sour);
|
|
SetLength(Result, siz);
|
|
dcStream.read(Result[0], siz);
|
|
DisposeObject(sour);
|
|
DisposeObject(dcStream);
|
|
end
|
|
else
|
|
Result := sour_;
|
|
end
|
|
else
|
|
Result := sour_;
|
|
end;
|
|
|
|
procedure test_utf8;
|
|
var
|
|
buff: TBytes;
|
|
s: TPascalString;
|
|
begin
|
|
buff := CompressUTF8(TPascalString('123456789abcdefg1111111111111111111111111111111111111').Bytes);
|
|
s.Bytes := DecompressUTF8(buff);
|
|
end;
|
|
|
|
procedure DoStatus(const v: TMemoryStream64);
|
|
var
|
|
p: PByte;
|
|
i: Integer;
|
|
n: SystemString;
|
|
begin
|
|
p := v.Memory;
|
|
for i := 0 to v.Size - 1 do
|
|
begin
|
|
if n <> '' then
|
|
n := n + ',' + IntToStr(p^)
|
|
else
|
|
n := IntToStr(p^);
|
|
inc(p);
|
|
end;
|
|
DoStatus(IntToHex(NativeInt(v), SizeOf(Pointer)) + ':' + n);
|
|
end;
|
|
|
|
initialization
|
|
|
|
end.
|