CompressionStreamUnit.pas
上传用户:hndmjx
上传日期:2014-09-16
资源大小:3369k
文件大小:21k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {
  2.   ZLIB Compression Streams for Delphi by Aphex
  3.   http://www.iamaphex.cjb.net
  4.   unremote@knology.net
  5.   Originally based on delphi fast zlib
  6.   http://www.dellapasqua.com/delphizlib
  7. }
  8. unit CompressionStreamUnit;
  9. interface
  10. {$WARNINGS OFF}
  11. uses
  12.   Windows;
  13. const
  14.   ZLIB_VERSION = '1.1.4';
  15.   WM_USER = $0400;
  16.   MaxListSize = Maxint div 16;
  17.   soFromBeginning = 0;
  18.   soFromCurrent = 1;
  19.   soFromEnd = 2;
  20. type
  21.   TNotifyEvent = procedure(Sender: TObject) of object;
  22.   TSeekOrigin = (soBeginning, soCurrent, soEnd);
  23.   TStream = class(TObject)
  24.   private
  25.     function GetPosition: Int64;
  26.     procedure SetPosition(const Pos: Int64);
  27.     function GetSize: Int64;
  28.     procedure SetSize64(const NewSize: Int64);
  29.   protected
  30.     procedure SetSize(NewSize: Longint); overload; virtual;
  31.     procedure SetSize(const NewSize: Int64); overload; virtual;
  32.   public
  33.     function Read(var Buffer; Count: Longint): Longint; virtual; abstract;
  34.     function Write(const Buffer; Count: Longint): Longint; virtual; abstract;
  35.     function Seek(Offset: Longint; Origin: Word): Longint; overload; virtual;
  36.     function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; overload; virtual;
  37.     procedure ReadBuffer(var Buffer; Count: Longint);
  38.     procedure WriteBuffer(const Buffer; Count: Longint);
  39.     function CopyFrom(Source: TStream; Count: Int64): Int64;
  40.     property Position: Int64 read GetPosition write SetPosition;
  41.     property Size: Int64 read GetSize write SetSize64;
  42.   end;
  43.   TCustomMemoryStream = class(TStream)
  44.   private
  45.     FMemory: Pointer;
  46.     FData: Pointer;
  47.     FSize, FPosition: Longint;
  48.   protected
  49.     procedure SetPointer(Ptr: Pointer; Size: Longint);
  50.   public
  51.     function Read(var Buffer; Count: Longint): Longint; override;
  52.     function Seek(Offset: Longint; Origin: Word): Longint; override;
  53.     procedure SaveToStream(Stream: TStream);
  54.     procedure SaveToFile(const FileName: string);
  55.     property Memory: Pointer read FMemory;
  56.     property Data: Pointer read FData write FData;
  57.   end;
  58.   TMemoryStream = class(TCustomMemoryStream)
  59.   private
  60.     FCapacity: Longint;
  61.     procedure SetCapacity(NewCapacity: Longint);
  62.   protected
  63.     function Realloc(var NewCapacity: Longint): Pointer; virtual;
  64.     property Capacity: Longint read FCapacity write SetCapacity;
  65.   public
  66.     destructor Destroy; override;
  67.     procedure Clear;
  68.     procedure LoadFromStream(Stream: TStream);
  69.     procedure LoadFromFile(const FileName: string);
  70.     procedure SetSize(NewSize: Longint); override;
  71.     function Write(const Buffer; Count: Longint): Longint; override;
  72.   end;
  73.   THandleStream = class(TStream)
  74.   protected
  75.     FHandle: Integer;
  76.     procedure SetSize(NewSize: Longint); override;
  77.     procedure SetSize(const NewSize: Int64); override;
  78.   public
  79.     constructor Create(AHandle: Integer);
  80.     function Read(var Buffer; Count: Longint): Longint; override;
  81.     function Write(const Buffer; Count: Longint): Longint; override;
  82.     function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
  83.     property Handle: Integer read FHandle;
  84.   end;
  85.   TFileStream = class(THandleStream)
  86.   public
  87.     constructor Create(const FileName: string; Mode: Word); overload;
  88.     constructor Create(const FileName: string; Mode: Word; Rights: Cardinal); overload;
  89.     destructor Destroy; override;
  90.   end;
  91.   TAlloc = function(Opaque: Pointer; Items, Size: Integer): Pointer;
  92.   TFree = procedure(Opaque, Block: Pointer);
  93.   TCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax);
  94.   TCompressionStreamRecord = packed record
  95.     NextIn: PChar;
  96.     AvailableIn: dword;
  97.     TotalIn: dword;
  98.     NextOut: PChar;
  99.     AvailableOut: dword;
  100.     TotalOut: dword;
  101.     Msg: PChar;
  102.     State: Pointer;
  103.     AllocProc: TAlloc;
  104.     FreeProc: TFree;
  105.     Opaque: Pointer;
  106.     DataType: dword;
  107.     Adler: dword;
  108.     Reserved: dword;
  109.   end;
  110.   TCustomCompressionStream = class(TStream)
  111.   private
  112.     FStream: TStream;
  113.     FStreamPos: Integer;
  114.     FOnProgress: TNotifyEvent;
  115.     FStreamRecord: TCompressionStreamRecord;
  116.     FBuffer: array [Word] of Char;
  117.   protected
  118.     constructor Create(stream: TStream);
  119.     procedure DoProgress; dynamic;
  120.     property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
  121.   end;
  122.   TCompressionStream = class(TCustomCompressionStream)
  123.   private
  124.     function GetCompressionRate: Single;
  125.   public
  126.     constructor Create(dest: TStream; CompressionLevel: TCompressionLevel = zcDefault);
  127.     destructor Destroy; override;
  128.     function Read(var Buffer; Count: longint): longint; override;
  129.     function Write(const Buffer; Count: longint): longint; override;
  130.     function Seek(Offset: longint; Origin: Word): longint; override;
  131.     property CompressionRate: Single read GetCompressionRate;
  132.     property OnProgress;
  133.   end;
  134.   TDecompressionStream = class(TCustomCompressionStream)
  135.   public
  136.     constructor Create(source: TStream);
  137.     destructor Destroy; override;
  138.     function Read(var Buffer; Count: longint): longint; override;
  139.     function Write(const Buffer; Count: longint): longint; override;
  140.     function Seek(Offset: longint; Origin: Word): longint; override;
  141.     property OnProgress;
  142.   end;
  143. function adler32(adler: LongInt; const buf: PChar; len: Integer): LongInt;
  144. function crc32(crc: LongInt; const buf: PChar; len: Integer): LongInt;
  145. function compressBound(sourceLen: LongInt): LongInt;
  146. implementation
  147. {$L adler32.obj}
  148. {$L compress.obj}
  149. {$L crc32.obj}
  150. {$L deflate.obj}
  151. {$L infback.obj}
  152. {$L inffast.obj}
  153. {$L inflate.obj}
  154. {$L inftrees.obj}
  155. {$L trees.obj}
  156. {$L uncompr.obj}
  157. const
  158.   Levels: array[TCompressionLevel] of Shortint = (0, 1, (-1), 9);
  159.   _z_errmsg: array[0..9] of PChar = ('', '', '', '', '', '', '', '', '', '');
  160.   fmCreate = $FFFF;
  161.   fmOpenRead = $0000;
  162.   fmOpenWrite = $0001;
  163.   fmOpenReadWrite = $0002;
  164.   fmShareCompat = $0000;
  165.   fmShareExclusive = $0010;
  166.   fmShareDenyWrite = $0020;
  167.   fmShareDenyRead = $0030;
  168.   fmShareDenyNone = $0040;
  169. function deflateInit_(var strm: TCompressionStreamRecord; level: Integer; version: PChar; recsize: Integer): Integer; external;
  170. function DeflateInit2_(var strm: TCompressionStreamRecord; level: integer; method: integer; windowBits: integer; memLevel: integer; strategy: integer; version: PChar; recsize: integer): integer; external;
  171. function deflate(var strm: TCompressionStreamRecord; flush: Integer): Integer; external;
  172. function deflateEnd(var strm: TCompressionStreamRecord): Integer; external;
  173. function inflateInit_(var strm: TCompressionStreamRecord; version: PChar; recsize: Integer): Integer; external;
  174. function inflateInit2_(var strm: TCompressionStreamRecord; windowBits: integer; version: PChar; recsize: integer): integer; external;
  175. function inflate(var strm: TCompressionStreamRecord; flush: Integer): Integer; external;
  176. function inflateEnd(var strm: TCompressionStreamRecord): Integer; external;
  177. function inflateReset(var strm: TCompressionStreamRecord): Integer; external;
  178. function adler32; external;
  179. function crc32; external;
  180. function compressBound; external;
  181. function FileOpen(const FileName: string; Mode: LongWord): Integer;
  182. const
  183.   AccessMode: array[0..2] of LongWord = (
  184.     GENERIC_READ,
  185.     GENERIC_WRITE,
  186.     GENERIC_READ or GENERIC_WRITE);
  187.   ShareMode: array[0..4] of LongWord = (
  188.     0,
  189.     0,
  190.     FILE_SHARE_READ,
  191.     FILE_SHARE_WRITE,
  192.     FILE_SHARE_READ or FILE_SHARE_WRITE);
  193. begin
  194.   Result := -1;
  195.   if ((Mode and 3) <= $0002) and
  196.     (((Mode and $F0) shr 4) <= $0040) then
  197.     Result := Integer(CreateFile(PChar(FileName), AccessMode[Mode and 3],
  198.       ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING,
  199.       FILE_ATTRIBUTE_NORMAL, 0));
  200. end;
  201. procedure FileClose(Handle: Integer);
  202. begin
  203.   CloseHandle(THandle(Handle));
  204. end;
  205. function FileCreate(const FileName: string): Integer;
  206. begin
  207.   Result := Integer(CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE,
  208.     0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0));
  209. end;
  210. function FileRead(Handle: Integer; var Buffer; Count: LongWord): Integer;
  211. begin
  212.   if not ReadFile(THandle(Handle), Buffer, Count, LongWord(Result), nil) then
  213.     Result := -1;
  214. end;
  215. function FileWrite(Handle: Integer; const Buffer; Count: LongWord): Integer;
  216. begin
  217.   if not WriteFile(THandle(Handle), Buffer, Count, LongWord(Result), nil) then
  218.     Result := -1;
  219. end;
  220. function FileSeek(Handle, Offset, Origin: Integer): Integer;
  221. begin
  222.   Result := SetFilePointer(THandle(Handle), Offset, nil, Origin);
  223. end;
  224. function zcalloc(opaque: Pointer; items, size: Integer): Pointer;
  225. begin
  226.   GetMem(Result, items * size);
  227. end;
  228. procedure zcfree(opaque, block: Pointer);
  229. begin
  230.   FreeMem(block);
  231. end;
  232. procedure _memset(p: Pointer; b: Byte; Count: Integer); cdecl;
  233. begin
  234.   FillChar(p^, Count, b);
  235. end;
  236. procedure _memcpy(dest, source: Pointer; Count: Integer); cdecl;
  237. begin
  238.   move(source^, dest^, Count);
  239. end;
  240. function DeflateInit(var stream: TCompressionStreamRecord; level: Integer): Integer;
  241. begin
  242.   Result := DeflateInit_(stream, level, ZLIB_VERSION, SizeOf(TCompressionStreamRecord));
  243. end;
  244. function DeflateInit2(var stream: TCompressionStreamRecord; level, method, windowBits,
  245.   memLevel, strategy: Integer): Integer;
  246. begin
  247.   Result := DeflateInit2_(stream, level, method, windowBits, memLevel, strategy, ZLIB_VERSION, SizeOf(TCompressionStreamRecord));
  248. end;
  249. function InflateInit(var stream: TCompressionStreamRecord): Integer;
  250. begin
  251.   Result := InflateInit_(stream, ZLIB_VERSION, SizeOf(TCompressionStreamRecord));
  252. end;
  253. function InflateInit2(var stream: TCompressionStreamRecord; windowBits: Integer): Integer;
  254. begin
  255.   Result := InflateInit2_(stream, windowBits, ZLIB_VERSION, SizeOf(TCompressionStreamRecord));
  256. end;
  257. function TStream.GetPosition: Int64;
  258. begin
  259.   Result := Seek(0, soCurrent);
  260. end;
  261. procedure TStream.SetPosition(const Pos: Int64);
  262. begin
  263.   Seek(Pos, soBeginning);
  264. end;
  265. function TStream.GetSize: Int64;
  266. var
  267.   Pos: Int64;
  268. begin
  269.   Pos := Seek(0, soCurrent);
  270.   Result := Seek(0, soEnd);
  271.   Seek(Pos, soBeginning);
  272. end;
  273. procedure TStream.SetSize(NewSize: Longint);
  274. begin
  275.   SetSize(NewSize);
  276. end;
  277. procedure TStream.SetSize64(const NewSize: Int64);
  278. begin
  279.   SetSize(NewSize);
  280. end;
  281. procedure TStream.SetSize(const NewSize: Int64);
  282. begin
  283.   if (NewSize < Low(Longint)) or (NewSize > High(Longint)) then
  284.     Exit;
  285.   SetSize(Longint(NewSize));
  286. end;
  287. function TStream.Seek(Offset: Longint; Origin: Word): Longint;
  288. type
  289.   TSeek64 = function (const Offset: Int64; Origin: TSeekOrigin): Int64 of object;
  290. var
  291.   Impl: TSeek64;
  292.   Base: TSeek64;
  293.   ClassTStream: TClass;
  294. begin
  295.   Impl := Seek;
  296.   ClassTStream := Self.ClassType;
  297.   while (ClassTStream <> nil) and (ClassTStream <> TStream) do
  298.     ClassTStream := ClassTStream.ClassParent;
  299.   Base := TStream(@ClassTStream).Seek;
  300.   Result := Seek(Int64(Offset), TSeekOrigin(Origin));
  301. end;
  302. function TStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
  303. begin
  304.   Result := 0;
  305.   if (Offset < Low(Longint)) or (Offset > High(Longint)) then
  306.     Exit;
  307.   Result := Seek(Longint(Offset), Ord(Origin));
  308. end;
  309. procedure TStream.ReadBuffer(var Buffer; Count: Longint);
  310. begin
  311.   if (Count <> 0) and (Read(Buffer, Count) <> Count) then
  312.     Exit;
  313. end;
  314. procedure TStream.WriteBuffer(const Buffer; Count: Longint);
  315. begin
  316.   if (Count <> 0) and (Write(Buffer, Count) <> Count) then
  317.     Exit;
  318. end;
  319. function TStream.CopyFrom(Source: TStream; Count: Int64): Int64;
  320. const
  321.   MaxBufSize = $F000;
  322. var
  323.   BufSize, N: Integer;
  324.   Buffer: PChar;
  325. begin
  326.   if Count = 0 then
  327.   begin
  328.     Source.Position := 0;
  329.     Count := Source.Size;
  330.   end;
  331.   Result := Count;
  332.   if Count > MaxBufSize then BufSize := MaxBufSize else BufSize := Count;
  333.   GetMem(Buffer, BufSize);
  334.   try
  335.     while Count <> 0 do
  336.     begin
  337.       if Count > BufSize then N := BufSize else N := Count;
  338.       Source.ReadBuffer(Buffer^, N);
  339.       WriteBuffer(Buffer^, N);
  340.       Dec(Count, N);
  341.     end;
  342.   finally
  343.     FreeMem(Buffer, BufSize);
  344.   end;
  345. end;
  346. constructor THandleStream.Create(AHandle: Integer);
  347. begin
  348.   inherited Create;
  349.   FHandle := AHandle;
  350. end;
  351. function THandleStream.Read(var Buffer; Count: Longint): Longint;
  352. begin
  353.   Result := FileRead(FHandle, Buffer, Count);
  354.   if Result = -1 then Result := 0;
  355. end;
  356. function THandleStream.Write(const Buffer; Count: Longint): Longint;
  357. begin
  358.   Result := FileWrite(FHandle, Buffer, Count);
  359.   if Result = -1 then Result := 0;
  360. end;
  361. function THandleStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
  362. begin
  363.   Result := FileSeek(FHandle, Offset, Ord(Origin));
  364. end;
  365. procedure THandleStream.SetSize(NewSize: Longint);
  366. begin
  367.   SetSize(Int64(NewSize));
  368. end;
  369. procedure THandleStream.SetSize(const NewSize: Int64);
  370. begin
  371.   Seek(NewSize, soBeginning);
  372. end;
  373. constructor TFileStream.Create(const FileName: string; Mode: Word);
  374. begin
  375.   Create(Filename, Mode, 0);
  376. end;
  377. constructor TFileStream.Create(const FileName: string; Mode: Word; Rights: Cardinal);
  378. begin
  379.   if Mode = $FFFF then
  380.   begin
  381.     inherited Create(FileCreate(FileName));
  382.   end
  383.   else
  384.   begin
  385.     inherited Create(FileOpen(FileName, Mode));
  386.   end;
  387. end;
  388. destructor TFileStream.Destroy;
  389. begin
  390.   if FHandle >= 0 then FileClose(FHandle);
  391.   inherited Destroy;
  392. end;
  393. constructor TCustomCompressionStream.Create(Stream: TStream);
  394. begin
  395.   inherited Create;
  396.   FStream := Stream;
  397.   FStreamPos := Stream.Position;
  398. end;
  399. procedure TCustomCompressionStream.DoProgress;
  400. begin
  401.   if Assigned(FOnProgress) then FOnProgress(Self);
  402. end;
  403. constructor TCompressionStream.Create(Dest: TStream; CompressionLevel: TCompressionLevel);
  404. begin
  405.   inherited Create(dest);
  406.   FStreamRecord.NextOut := FBuffer;
  407.   FStreamRecord.AvailableOut := SizeOf(FBuffer);
  408.   DeflateInit(FStreamRecord, Levels[CompressionLevel]);
  409. end;
  410. destructor TCompressionStream.Destroy;
  411. begin
  412.   FStreamRecord.NextIn := nil;
  413.   FStreamRecord.AvailableIn := 0;
  414.   try
  415.     if FStream.Position <> FStreamPos then FStream.Position := FStreamPos;
  416.     while deflate(FStreamRecord, 4) <> 1 do
  417.     begin
  418.       FStream.WriteBuffer(FBuffer, SizeOf(FBuffer) - FStreamRecord.AvailableOut);
  419.       FStreamRecord.NextOut := FBuffer;
  420.       FStreamRecord.AvailableOut := SizeOf(FBuffer);
  421.     end;
  422.     if FStreamRecord.AvailableOut < SizeOf(FBuffer) then
  423.     begin
  424.       FStream.WriteBuffer(FBuffer, SizeOf(FBuffer) - FStreamRecord.AvailableOut);
  425.     end;
  426.   finally
  427.     deflateEnd(FStreamRecord);
  428.   end;
  429.   inherited Destroy;
  430. end;
  431. function TCompressionStream.Read(var Buffer; Count: longint): longint;
  432. begin
  433. end;
  434. function TCompressionStream.Write(const Buffer; Count: longint): longint;
  435. begin
  436.   FStreamRecord.NextIn := @Buffer;
  437.   FStreamRecord.AvailableIn := Count;
  438.   if FStream.Position <> FStreamPos then FStream.Position := FStreamPos;
  439.   while FStreamRecord.AvailableIn > 0 do
  440.   begin
  441.     deflate(FStreamRecord, 0);
  442.     if FStreamRecord.AvailableOut = 0 then
  443.     begin
  444.       FStream.WriteBuffer(FBuffer, SizeOf(FBuffer));
  445.       FStreamRecord.NextOut := FBuffer;
  446.       FStreamRecord.AvailableOut := SizeOf(FBuffer);
  447.       FStreamPos := FStream.Position;
  448.       DoProgress;
  449.     end;
  450.   end;
  451.   Result := Count;
  452. end;
  453. function TCompressionStream.Seek(offset: Longint; origin: Word): Longint;
  454. begin
  455.   if (offset = 0) and (origin = soFromCurrent) then
  456.   begin
  457.     Result := FStreamRecord.TotalIn;
  458.   end;
  459. end;
  460. function TCompressionStream.GetCompressionRate: Single;
  461. begin
  462.   if FStreamRecord.TotalIn = 0 then Result := 0
  463.   else Result := (1.0 - (FStreamRecord.TotalOut / FStreamRecord.TotalIn)) * 100.0;
  464. end;
  465. constructor TDecompressionStream.Create(source: TStream);
  466. begin
  467.   inherited Create(source);
  468.   FStreamRecord.NextIn := FBuffer;
  469.   FStreamRecord.AvailableIn := 0;
  470.   InflateInit(FStreamRecord);
  471. end;
  472. destructor TDecompressionStream.Destroy;
  473. begin
  474.   inflateEnd(FStreamRecord);
  475.   inherited Destroy;
  476. end;
  477. function TDecompressionStream.Read(var Buffer; Count: longint): longint;
  478. var
  479.   ReturnValue: longint;
  480. begin
  481.   FStreamRecord.NextOut := @Buffer;
  482.   FStreamRecord.AvailableOut := Count;
  483.   if FStream.Position <> FStreamPos then FStream.Position := FStreamPos;
  484.   ReturnValue := 0;
  485.   while ((FStreamRecord.AvailableOut > 0) and (ReturnValue <> 1)) do
  486.   begin
  487.     if FStreamRecord.AvailableIn = 0 then
  488.     begin
  489.       FStreamRecord.AvailableIn := FStream.Read(FBuffer, SizeOf(FBuffer));
  490.       if FStreamRecord.AvailableIn = 0 then
  491.       begin
  492.         Result := Count - FStreamRecord.AvailableOut;
  493.         Exit;
  494.       end;
  495.       FStreamRecord.NextIn := FBuffer;
  496.       FStreamPos := FStream.Position;
  497.       DoProgress;
  498.     end;
  499.     ReturnValue := inflate(FStreamRecord, 0);
  500.   end;
  501.   if ((ReturnValue = 1) and (FStreamRecord.AvailableIn > 0)) then
  502.   begin
  503.     FStream.Position := FStream.Position - FStreamRecord.AvailableIn;
  504.     FStreamPos := FStream.Position;
  505.     FStreamRecord.AvailableIn := 0;
  506.   end;
  507.   Result := Count - FStreamRecord.AvailableOut;
  508. end;
  509. function TDecompressionStream.Write(const Buffer; Count: longint): longint;
  510. begin
  511. end;
  512. function TDecompressionStream.Seek(Offset: longint; Origin: Word): longint;
  513. var
  514.   Buffer: array [0..8191] of Char;
  515.   Count: Integer;
  516. begin
  517.   if ((Offset = 0) and (Origin = soFromBeginning)) then
  518.   begin
  519.     inflateReset(FStreamRecord);
  520.     FStreamRecord.NextIn := FBuffer;
  521.     FStreamRecord.AvailableIn := 0;
  522.     FStream.Position := 0;
  523.     FStreamPos := 0;
  524.   end
  525.   else if ((Offset >= 0) and (Origin = soFromCurrent)) or (((Offset - FStreamRecord.TotalOut) > 0) and (Origin = soFromBeginning)) then
  526.   begin
  527.     if Origin = soFromBeginning then Dec(Offset, FStreamRecord.TotalOut);
  528.     if Offset > 0 then
  529.     begin
  530.       for Count := 1 to Offset div SizeOf(Buffer) do ReadBuffer(Buffer, SizeOf(Buffer));
  531.       ReadBuffer(Buffer, Offset mod SizeOf(Buffer));
  532.     end;
  533.   end
  534.   else if (Offset = 0) and (Origin = soFromEnd) then
  535.   begin
  536.     while Read(Buffer, SizeOf(Buffer)) > 0 do;
  537.   end;
  538.   Result := FStreamRecord.TotalOut;
  539. end;
  540. procedure TCustomMemoryStream.SetPointer(Ptr: Pointer; Size: Longint);
  541. begin
  542.   FMemory := Ptr;
  543.   FSize := Size;
  544. end;
  545. function TCustomMemoryStream.Read(var Buffer; Count: Longint): Longint;
  546. begin
  547.   if (FPosition >= 0) and (Count >= 0) then
  548.   begin
  549.     Result := FSize - FPosition;
  550.     if Result > 0 then
  551.     begin
  552.       if Result > Count then Result := Count;
  553.       Move(Pointer(Longint(FMemory) + FPosition)^, Buffer, Result);
  554.       Inc(FPosition, Result);
  555.       Exit;
  556.     end;
  557.   end;
  558.   Result := 0;
  559. end;
  560. function TCustomMemoryStream.Seek(Offset: Longint; Origin: Word): Longint;
  561. begin
  562.   case Origin of
  563.     soFromBeginning: FPosition := Offset;
  564.     soFromCurrent: Inc(FPosition, Offset);
  565.     soFromEnd: FPosition := FSize + Offset;
  566.   end;
  567.   Result := FPosition;
  568. end;
  569. procedure TCustomMemoryStream.SaveToStream(Stream: TStream);
  570. begin
  571.   if FSize <> 0 then Stream.WriteBuffer(FMemory^, FSize);
  572. end;
  573. procedure TCustomMemoryStream.SaveToFile(const FileName: string);
  574. var
  575.   Stream: TStream;
  576. begin
  577.   Stream := TFileStream.Create(FileName, fmCreate);
  578.   try
  579.     SaveToStream(Stream);
  580.   finally
  581.     Stream.Free;
  582.   end;
  583. end;
  584. const
  585.   MemoryDelta = $2000;
  586. destructor TMemoryStream.Destroy;
  587. begin
  588.   Clear;
  589.   inherited Destroy;
  590. end;
  591. procedure TMemoryStream.Clear;
  592. begin
  593.   SetCapacity(0);
  594.   FSize := 0;
  595.   FPosition := 0;
  596. end;
  597. procedure TMemoryStream.LoadFromStream(Stream: TStream);
  598. var
  599.   Count: Longint;
  600. begin
  601.   Stream.Position := 0;
  602.   Count := Stream.Size;
  603.   SetSize(Count);
  604.   if Count <> 0 then Stream.ReadBuffer(FMemory^, Count);
  605. end;
  606. procedure TMemoryStream.LoadFromFile(const FileName: string);
  607. var
  608.   Stream: TStream;
  609. begin
  610.   Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  611.   try
  612.     LoadFromStream(Stream);
  613.   finally
  614.     Stream.Free;
  615.   end;
  616. end;
  617. procedure TMemoryStream.SetCapacity(NewCapacity: Longint);
  618. begin
  619.   SetPointer(Realloc(NewCapacity), FSize);
  620.   FCapacity := NewCapacity;
  621. end;
  622. procedure TMemoryStream.SetSize(NewSize: Longint);
  623. var
  624.   OldPosition: Longint;
  625. begin
  626.   OldPosition := FPosition;
  627.   SetCapacity(NewSize);
  628.   FSize := NewSize;
  629.   if OldPosition > NewSize then Seek(0, soFromEnd);
  630. end;
  631. function TMemoryStream.Realloc(var NewCapacity: Longint): Pointer;
  632. begin
  633.   if (NewCapacity > 0) and (NewCapacity <> FSize) then
  634.     NewCapacity := (NewCapacity + (MemoryDelta - 1)) and not (MemoryDelta - 1);
  635.   Result := Memory;
  636.   if NewCapacity <> FCapacity then
  637.   begin
  638.     if NewCapacity = 0 then
  639.     begin
  640.       GlobalFreePtr(Memory);
  641.       Result := nil;
  642.     end else
  643.     begin
  644.       if Capacity = 0 then
  645.         Result := GlobalAllocPtr(HeapAllocFlags, NewCapacity)
  646.       else
  647.         Result := GlobalReallocPtr(Memory, NewCapacity, HeapAllocFlags);
  648.     end;
  649.   end;
  650. end;
  651. function TMemoryStream.Write(const Buffer; Count: Longint): Longint;
  652. var
  653.   Pos: Longint;
  654. begin
  655.   if (FPosition >= 0) and (Count >= 0) then
  656.   begin
  657.     Pos := FPosition + Count;
  658.     if Pos > 0 then
  659.     begin
  660.       if Pos > FSize then
  661.       begin
  662.         if Pos > FCapacity then
  663.           SetCapacity(Pos);
  664.         FSize := Pos;
  665.       end;
  666.       System.Move(Buffer, Pointer(Longint(FMemory) + FPosition)^, Count);
  667.       FPosition := Pos;
  668.       Result := Count;
  669.       Exit;
  670.     end;
  671.   end;
  672.   Result := 0;
  673. end;
  674. end.