X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fshared%2Fxstreams.pas;h=36e73f96e45d24dd09afed6127c864b4a3a05b61;hb=987c4a835a103345b59937e8e1be8524a6228712;hp=81a104cc9e33be77409318c25766fcdc5b0382b3;hpb=dd0d8ac4cc2a0aa774f25c8a1a774f7358acfae7;p=d2df-sdl.git diff --git a/src/shared/xstreams.pas b/src/shared/xstreams.pas index 81a104c..36e73f9 100644 --- a/src/shared/xstreams.pas +++ b/src/shared/xstreams.pas @@ -1,9 +1,8 @@ -(* Copyright (C) DooM 2D:Forever Developers +(* Copyright (C) Doom 2D: Forever Developers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * the Free Software Foundation, version 3 of the License ONLY. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -126,6 +125,29 @@ type function seek (const offset: Int64; origin: TSeekOrigin): Int64; override; end; + // fixed memory chunk + TSFSMemoryChunkStream = class(TStream) + private + fFreeMem: Boolean; + fMemBuf: PByte; + fMemSize: Integer; + fCurPos: Integer; + + public + // if `pMem` is `nil`, stream will allocate it + constructor Create (pMem: Pointer; pSize: Integer; aFreeMem: Boolean=false); + destructor Destroy (); override; + + procedure setup (pMem: Pointer; pSize: Integer; aFreeMem: Boolean=false); + + function Seek (const offset: Int64; origin: TSeekOrigin): Int64; override; + function Read (var buffer; count: LongInt): LongInt; override; + function Write (const buffer; count: LongInt): LongInt; override; + + property chunkSize: Integer read fMemSize; + property chunkData: PByte read fMemBuf; + end; + implementation @@ -454,4 +476,91 @@ begin end; +// ////////////////////////////////////////////////////////////////////////// // +constructor TSFSMemoryChunkStream.Create (pMem: Pointer; pSize: Integer; aFreeMem: Boolean=false); +begin + fMemBuf := nil; + fFreeMem := false; + fMemSize := 0; + fCurPos := 0; + setup(pMem, pSize, aFreeMem); +end; + + +procedure TSFSMemoryChunkStream.setup (pMem: Pointer; pSize: Integer; aFreeMem: Boolean=false); +begin + if fFreeMem then FreeMem(fMemBuf); + fMemBuf := nil; + fFreeMem := false; + fMemSize := 0; + fCurPos := 0; + if (pSize < 0) then raise XStreamError.Create('invalid chunk size'); + if (pMem = nil) then + begin + if (pSize > 0) then + begin + GetMem(pMem, pSize); + if (pMem = nil) then raise XStreamError.Create('out of memory for chunk'); + aFreeMem := true; + end + else + begin + aFreeMem := false; + end; + end; + fFreeMem := aFreeMem; + fMemBuf := PByte(pMem); + fMemSize := pSize; +end; + + +destructor TSFSMemoryChunkStream.Destroy (); +begin + if fFreeMem then FreeMem(fMemBuf); + inherited; +end; + + +function TSFSMemoryChunkStream.Seek (const offset: Int64; origin: TSeekOrigin): Int64; +begin + case origin of + soBeginning: result := offset; + soCurrent: result := offset+fCurPos; + soEnd: result := fMemSize+offset; + else raise XStreamError.Create('invalid Seek() call'); + end; + if (result < 0) then raise XStreamError.Create('invalid Seek() call'); + if (result > fMemSize) then result := fMemSize; + fCurPos := result; +end; + + +function TSFSMemoryChunkStream.Read (var buffer; count: LongInt): LongInt; +var + left: Integer; +begin + if (count < 0) then raise XStreamError.Create('negative read'); + left := fMemSize-fCurPos; + if (left < 0) then raise XStreamError.Create('internal error in TSFSMemoryChunkStream (read)'); + if (count > left) then count := left; + if (count > 0) then Move((fMemBuf+fCurPos)^, buffer, count); + Inc(fCurPos, count); + result := count; +end; + + +function TSFSMemoryChunkStream.Write (const buffer; count: LongInt): LongInt; +var + left: Integer; +begin + if (count < 0) then raise XStreamError.Create('negative write'); + left := fMemSize-fCurPos; + if (left < 0) then raise XStreamError.Create('internal error in TSFSMemoryChunkStream (write)'); + if (count > left) then count := left; + if (count > 0) then Move(buffer, (fMemBuf+fCurPos)^, count); + Inc(fCurPos, count); + result := count; +end; + + end.