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
)
89 constructor Create (pMem
: Pointer; pSize
: Integer);
91 function Write (const buffer
; count
: LongInt): LongInt; override;
101 constructor TSFSSDLStream
.Create (aSrc
: PSDL_RWops
; aFreeSource
: Boolean=true);
104 //ASSERT(aSrc <> nil);
106 fFreeSource
:= aFreeSource
;
109 destructor TSFSSDLStream
.Destroy ();
111 if fFreeSource
and (fRW
<> nil) then SDL_FreeRW(fRW
);
115 function TSFSSDLStream
.Read (var buffer
; count
: LongInt): LongInt;
117 if (fRW
= nil) or (count
<= 0) then begin result
:= 0; exit
; end;
118 result
:= SDL_RWread(fRW
, @buffer
, 1, count
);
121 function TSFSSDLStream
.Write (const buffer
; count
: LongInt): LongInt;
123 if (fRW
= nil) or (count
<= 0) then begin result
:= 0; exit
; end;
124 result
:= SDL_RWwrite(fRW
, @buffer
, 1, count
);
127 function TSFSSDLStream
.Seek (const offset
: Int64; origin
: TSeekOrigin
): Int64;
131 if fRW
= nil then begin result
:= 0; exit
; end;
133 soBeginning
: ss
:= RW_SEEK_SET
;
134 soCurrent
: ss
:= RW_SEEK_CUR
;
135 soEnd
: ss
:= RW_SEEK_END
;
136 else raise ESFSError
.Create('invalid Seek() call');
137 // äðóãèõ íå áûâàåò. à ó êîãî áûâàåò, òîìó ÿ íå äîêòîð.
139 result
:= SDL_RWseek(fRW
, offset
, ss
);
140 if result
= -1 then raise ESFSError
.Create('Seek() error');
144 { TSFSPartialStream }
145 constructor TSFSPartialStream
.Create (aSrc
: TStream
; aPos
, aSize
: Int64; aKillSrc
: Boolean; preBuf
: Pointer=nil; bufSz
: Integer=0);
149 if aPos
< 0 then aPos
:= aSrc
.Position
;
150 if aSize
< 0 then aSize
:= 0;
152 fKillSource
:= aKillSrc
;
159 SetLength(fPreBuf
, bufSz
);
160 Move(preBuf
^, fPreBuf
[0], bufSz
);
169 destructor TSFSPartialStream
.Destroy ();
171 if fKillSource
then FreeAndNil(fSource
);
175 procedure TSFSPartialStream
.CheckPos ();
178 if fSource.Position <> fStartPos+fCurrentPos-Length(fPreBuf) then
180 fSource.Position := fStartPos+fCurrentPos-Length(fPreBuf);
183 if fCurrentPos
>= length(fPreBuf
) then
185 //writeln('seeking at ', fCurrentPos, ' (real: ', fStartPos+fCurrentPos-Length(fPreBuf), ')');
186 fSource
.Position
:= fStartPos
+fCurrentPos
-Length(fPreBuf
);
188 fLastReadPos
:= fCurrentPos
;
191 function TSFSPartialStream
.Write (const buffer
; count
: LongInt): LongInt;
194 raise ESFSError
.Create('can''t write to read-only stream');
195 // à íå õîäè, íåõîðîøèé, â íàø ñàäèê ãóëÿòü!
198 function TSFSPartialStream
.Read (var buffer
; count
: LongInt): LongInt;
204 if count
< 0 then raise ESFSError
.Create('invalid Read() call'); // ñêàçî÷íûé äîëáî¸á...
205 if count
= 0 then begin result
:= 0; exit
; end;
208 if (Length(fPreBuf
) > 0) and (fCurrentPos
< Length(fPreBuf
)) then
210 fLastReadPos
:= fCurrentPos
;
211 left
:= Length(fPreBuf
)-fCurrentPos
;
212 if left
> count
then left
:= count
;
215 Move(fPreBuf
[fCurrentPos
], pc
^, left
);
216 Inc(PChar(pc
), left
);
217 Inc(fCurrentPos
, left
);
218 fLastReadPos
:= fCurrentPos
;
221 if count
= 0 then exit
;
225 left
:= fSize
-fCurrentPos
;
226 if left
< count
then count
:= left
; // è òàê ñëó÷àåòñÿ...
229 rd
:= fSource
.Read(pc
^, count
);
231 Inc(fCurrentPos
, rd
);
232 fLastReadPos
:= fCurrentPos
;
240 function TSFSPartialStream
.Seek (const offset
: Int64; origin
: TSeekOrigin
): Int64;
243 soBeginning
: result
:= offset
;
244 soCurrent
: result
:= offset
+fCurrentPos
;
245 soEnd
: result
:= fSize
+offset
;
246 else raise ESFSError
.Create('invalid Seek() call');
247 // äðóãèõ íå áûâàåò. à ó êîãî áûâàåò, òîìó ÿ íå äîêòîð.
249 if result
< 0 then result
:= 0
250 else if result
> fSize
then result
:= fSize
;
251 fCurrentPos
:= result
;
256 constructor TSFSGuardStream
.Create (aSrc
, aGuarded
: TStream
; aKillSrc
, aKillGuarded
: Boolean; aGuardedFirst
: Boolean=true);
259 fSource
:= aSrc
; fGuardedStream
:= aGuarded
;
260 fKillSource
:= aKillSrc
; fKillGuarded
:= aKillGuarded
;
261 fGuardedFirst
:= aGuardedFirst
;
264 destructor TSFSGuardStream
.Destroy ();
266 if fKillGuarded
and fGuardedFirst
then FreeAndNil(fGuardedStream
);
267 if fKillSource
then FreeAndNil(fSource
);
268 if fKillGuarded
and not fGuardedFirst
then FreeAndNil(fGuardedStream
);
272 function TSFSGuardStream
.Read (var buffer
; count
: LongInt): LongInt;
274 result
:= fSource
.Read(buffer
, count
);
277 function TSFSGuardStream
.Write (const buffer
; count
: LongInt): LongInt;
279 result
:= fSource
.Write(buffer
, count
);
282 function TSFSGuardStream
.Seek (const offset
: Int64; origin
: TSeekOrigin
): Int64;
284 result
:= fSource
.Seek(offset
, origin
);
288 { TSFSMemoryStreamRO }
289 constructor TSFSMemoryStreamRO
.Create (pMem
: Pointer; pSize
: Integer);
292 SetPointer(pMem
, pSize
);
296 function TSFSMemoryStreamRO
.Write (const buffer
; count
: LongInt): LongInt;
299 raise ESFSError
.Create('can''t write to read-only stream');
300 // ñîâñåì ñáðåíäèë...