xtool/contrib/CoreCipher/Source/MemoryStream64.pas

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.