index c34f2e820989016fe9ec6e0f02fa6b690f9fde02..e27f73ad0eb9c94c8f964649e0d969a22b0e78e6 100644 (file)
--- a/src/shared/xstreams.pas
+++ b/src/shared/xstreams.pas
+(* 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *)
// special stream classes
-{$MODE DELPHI}
-{$R+}
+{$INCLUDE a_modes.inc}
+{.$R+}
unit xstreams;
interface
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
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.