1 // special stream classes
9 SysUtils
, Classes
, SDL2
;
13 // ïîòîê-îá¸ðòêà äëÿ SDL_RWops
14 TSFSSDLStream
= class(TStream
)
16 fRW
: PSDL_RWops
; // SDL-íàÿ ïðîêëàäêà
17 fFreeSource
: Boolean; // óáèâàòü èñõîäíèê ïðè ïîìèðàíèè?
20 constructor Create (aSrc
: PSDL_RWops
; aFreeSource
: Boolean=true);
21 destructor Destroy (); override;
23 function Read (var buffer
; count
: LongInt): LongInt; override;
24 function Write (const buffer
; count
: LongInt): LongInt; override;
25 function Seek (const offset
: Int64; origin
: TSeekOrigin
): Int64; override;
28 // read-only ïîòîê äëÿ èçâëå÷åíèÿ èç èñõîäíîãî òîëüêî êóñî÷êà
29 TSFSPartialStream
= class(TStream
)
31 fSource
: TStream
; // èñõîäíûé ïîòîê
32 fKillSource
: Boolean; // óáèâàòü èñõîäíèê ïðè ïîìèðàíèè?
33 fLastReadPos
: Int64; // ïîñëåäíèé Read() îñòàíîâèëñÿ çäåñü (îòíîñ. fStartPos)
34 fCurrentPos
: Int64; // ïîñëåäíèé Seek() îñòàíîâèëñÿ çäåñü (îòíîñ. fStartPos)
35 fStartPos
: Int64; // íà÷àëî êóñî÷êà
36 fSize
: Int64; // äëèíà êóñî÷êà
37 fPreBuf
: packed array of Byte; // ýòîò áóôåð áóäåò ïåðåä ôàéëîì
39 procedure CheckPos ();
42 // aSrc: ïîòîê-èñõîäíèê.
43 // aPos: íà÷àëüíàÿ ïîçèöèÿ â ïîòîêå. -1 -- ñ òåêóùåé.
44 // åñëè aPos < òåêóùåé ïîçèöèè, òî èñõîäíûé ïîòîê äîëæåí
45 // íîðìàëüíî ïîääåðæèâàòü Seek()!
46 // aSize: êîëè÷åñòâî áàéòèêîâ, êîòîðîå ìîæíî ïðî÷åñòü èç ïîòîêà.
47 // åñëè ìåíüøå íóëÿ -- òî äî êîíöà.
48 // aKillSrc: óáèâàòü ëè èñõîäíûé ïîòîê, êîãäà ñàìè óìèðàåì?
49 // òàêæå ìîæåò ïðèøïàíäîðèòü ê íà÷àëó ôàéëà áóôåð. bufSz áóäåò äîáàâëåíî ê
51 constructor Create (aSrc
: TStream
; aPos
, aSize
: Int64; aKillSrc
: Boolean; preBuf
: Pointer=nil; bufSz
: Integer=0);
52 destructor Destroy (); override;
54 // íîðìàëèçóåò count è ÷èòàåò.
55 function Read (var buffer
; count
: LongInt): LongInt; override;
56 // Write() ïðîñòî ãðîìêî ïàäàåò.
57 function Write (const buffer
; count
: LongInt): LongInt; override;
58 // Seek() ðåàëèçîâàíî, ÷òîáû ìîãëà ðàáîòàòü ïðîïåðòÿ Size.
59 // âîîáùå-òî ìîæíî ïåðåêðûòü ìåòîä GetSize(), íî âäðóã êàêîé
60 // áîëüíîé íà ãîëîâó êîäåð áóäåò ïîëó÷àòü ðàçìåð ïðè ïîìîùè
62 function Seek (const offset
: Int64; origin
: TSeekOrigin
): Int64; override;
65 TSFSGuardStream
= class(TStream
)
67 fSource
: TStream
; // èñõîäíûé ïîòîê
68 fGuardedStream
: TStream
; // ïîòîê, êîòîðûé çàâàëèì ïðè ïîìèðàíèè
69 fKillSource
: Boolean; // óáèâàòü èñõîäíèê ïðè ïîìèðàíèè?
70 fKillGuarded
: Boolean; // óáèâàòü îõðàíÿåìûé ïðè ïîìèðàíèè?
71 fGuardedFirst
: Boolean; // ïðè ñìåðòè ïåðâûì ïðèøèáàåì îõðàíÿåìîãî?
74 // aSrc: ïîòîê-èñõîäíèê (íà êîòîðûé çàìàïåíû îïåðàöèè ÷òåíèÿ/çàïèñè).
75 // aKillSrc: óáèâàòü ëè èñõîäíûé ïîòîê, êîãäà ñàìè óìèðàåì?
76 // aKillGuarded: óáèâàòü ëè îõðàíÿåìûé ïîòîê, êîãäà ñàìè óìèðàåì?
77 // aGuardedFirst: true: ïðè ñìåðòè ïåðâûì ïðèøèáàåì îõðàíÿåìîãî.
78 constructor Create (aSrc
, aGuarded
: TStream
; aKillSrc
, aKillGuarded
: Boolean; aGuardedFirst
: Boolean=true);
79 destructor Destroy (); override;
81 // íèæåñëåäóþùåå çàìàïëåíî íà fSource
82 function Read (var buffer
; count
: LongInt): LongInt; override;
83 function Write (const buffer
; count
: LongInt): LongInt; override;
84 function Seek (const offset
: Int64; origin
: TSeekOrigin
): Int64; override;
87 TSFSMemoryStreamRO
= class(TCustomMemoryStream
)
93 constructor Create (pMem
: Pointer; pSize
: Integer; aFreeMem
: Boolean=false);
94 destructor Destroy (); override;
96 function Write (const buffer
; count
: LongInt): LongInt; override;
103 sfs
; // for ESFSError
106 constructor TSFSSDLStream
.Create (aSrc
: PSDL_RWops
; aFreeSource
: Boolean=true);
109 //ASSERT(aSrc <> nil);
111 fFreeSource
:= aFreeSource
;
114 destructor TSFSSDLStream
.Destroy ();
116 if fFreeSource
and (fRW
<> nil) then SDL_FreeRW(fRW
);
120 function TSFSSDLStream
.Read (var buffer
; count
: LongInt): LongInt;
122 if (fRW
= nil) or (count
<= 0) then begin result
:= 0; exit
; end;
123 result
:= SDL_RWread(fRW
, @buffer
, 1, count
);
126 function TSFSSDLStream
.Write (const buffer
; count
: LongInt): LongInt;
128 if (fRW
= nil) or (count
<= 0) then begin result
:= 0; exit
; end;
129 result
:= SDL_RWwrite(fRW
, @buffer
, 1, count
);
132 function TSFSSDLStream
.Seek (const offset
: Int64; origin
: TSeekOrigin
): Int64;
136 if fRW
= nil then begin result
:= 0; exit
; end;
138 soBeginning
: ss
:= RW_SEEK_SET
;
139 soCurrent
: ss
:= RW_SEEK_CUR
;
140 soEnd
: ss
:= RW_SEEK_END
;
141 else raise ESFSError
.Create('invalid Seek() call');
142 // äðóãèõ íå áûâàåò. à ó êîãî áûâàåò, òîìó ÿ íå äîêòîð.
144 result
:= SDL_RWseek(fRW
, offset
, ss
);
145 if result
= -1 then raise ESFSError
.Create('Seek() error');
149 { TSFSPartialStream }
150 constructor TSFSPartialStream
.Create (aSrc
: TStream
; aPos
, aSize
: Int64; aKillSrc
: Boolean; preBuf
: Pointer=nil; bufSz
: Integer=0);
154 if aPos
< 0 then aPos
:= aSrc
.Position
;
155 if aSize
< 0 then aSize
:= 0;
157 fKillSource
:= aKillSrc
;
164 SetLength(fPreBuf
, bufSz
);
165 Move(preBuf
^, fPreBuf
[0], bufSz
);
174 destructor TSFSPartialStream
.Destroy ();
176 if fKillSource
then FreeAndNil(fSource
);
180 procedure TSFSPartialStream
.CheckPos ();
183 if fSource.Position <> fStartPos+fCurrentPos-Length(fPreBuf) then
185 fSource.Position := fStartPos+fCurrentPos-Length(fPreBuf);
188 if fCurrentPos
>= length(fPreBuf
) then
190 //writeln('seeking at ', fCurrentPos, ' (real: ', fStartPos+fCurrentPos-Length(fPreBuf), ')');
191 fSource
.Position
:= fStartPos
+fCurrentPos
-Length(fPreBuf
);
193 fLastReadPos
:= fCurrentPos
;
196 function TSFSPartialStream
.Write (const buffer
; count
: LongInt): LongInt;
199 raise ESFSError
.Create('can''t write to read-only stream');
200 // à íå õîäè, íåõîðîøèé, â íàø ñàäèê ãóëÿòü!
203 function TSFSPartialStream
.Read (var buffer
; count
: LongInt): LongInt;
209 if count
< 0 then raise ESFSError
.Create('invalid Read() call'); // ñêàçî÷íûé äîëáî¸á...
210 if count
= 0 then begin result
:= 0; exit
; end;
213 if (Length(fPreBuf
) > 0) and (fCurrentPos
< Length(fPreBuf
)) then
215 fLastReadPos
:= fCurrentPos
;
216 left
:= Length(fPreBuf
)-fCurrentPos
;
217 if left
> count
then left
:= count
;
220 Move(fPreBuf
[fCurrentPos
], pc
^, left
);
221 Inc(PChar(pc
), left
);
222 Inc(fCurrentPos
, left
);
223 fLastReadPos
:= fCurrentPos
;
226 if count
= 0 then exit
;
230 left
:= fSize
-fCurrentPos
;
231 if left
< count
then count
:= left
; // è òàê ñëó÷àåòñÿ...
234 rd
:= fSource
.Read(pc
^, count
);
236 Inc(fCurrentPos
, rd
);
237 fLastReadPos
:= fCurrentPos
;
245 function TSFSPartialStream
.Seek (const offset
: Int64; origin
: TSeekOrigin
): Int64;
248 soBeginning
: result
:= offset
;
249 soCurrent
: result
:= offset
+fCurrentPos
;
250 soEnd
: result
:= fSize
+offset
;
251 else raise ESFSError
.Create('invalid Seek() call');
252 // äðóãèõ íå áûâàåò. à ó êîãî áûâàåò, òîìó ÿ íå äîêòîð.
254 if result
< 0 then result
:= 0
255 else if result
> fSize
then result
:= fSize
;
256 fCurrentPos
:= result
;
261 constructor TSFSGuardStream
.Create (aSrc
, aGuarded
: TStream
; aKillSrc
, aKillGuarded
: Boolean; aGuardedFirst
: Boolean=true);
264 fSource
:= aSrc
; fGuardedStream
:= aGuarded
;
265 fKillSource
:= aKillSrc
; fKillGuarded
:= aKillGuarded
;
266 fGuardedFirst
:= aGuardedFirst
;
269 destructor TSFSGuardStream
.Destroy ();
271 if fKillGuarded
and fGuardedFirst
then FreeAndNil(fGuardedStream
);
272 if fKillSource
then FreeAndNil(fSource
);
273 if fKillGuarded
and not fGuardedFirst
then FreeAndNil(fGuardedStream
);
277 function TSFSGuardStream
.Read (var buffer
; count
: LongInt): LongInt;
279 result
:= fSource
.Read(buffer
, count
);
282 function TSFSGuardStream
.Write (const buffer
; count
: LongInt): LongInt;
284 result
:= fSource
.Write(buffer
, count
);
287 function TSFSGuardStream
.Seek (const offset
: Int64; origin
: TSeekOrigin
): Int64;
289 result
:= fSource
.Seek(offset
, origin
);
293 { TSFSMemoryStreamRO }
294 constructor TSFSMemoryStreamRO
.Create (pMem
: Pointer; pSize
: Integer; aFreeMem
: Boolean=false);
296 fFreeMem
:= aFreeMem
;
299 SetPointer(pMem
, pSize
);
303 destructor TSFSMemoryStreamRO
.Destroy ();
305 if fFreeMem
and (fMem
<> nil) then FreeMem(fMem
);
308 function TSFSMemoryStreamRO
.Write (const buffer
; count
: LongInt): LongInt;
311 raise ESFSError
.Create('can''t write to read-only stream');
312 // ñîâñåì ñáðåíäèë...