DEADSOFTWARE

sfs: removed unused archive support
[d2df-sdl.git] / src / sfs / xstreams.pas
1 // special stream classes
2 {$MODE DELPHI}
3 {.$R-}
4 unit xstreams;
6 interface
8 uses
9 SysUtils, Classes, SDL2;
12 type
13 // ïîòîê-îá¸ðòêà äëÿ SDL_RWops
14 TSFSSDLStream = class(TStream)
15 protected
16 fRW: PSDL_RWops; // SDL-íàÿ ïðîêëàäêà
17 fFreeSource: Boolean; // óáèâàòü èñõîäíèê ïðè ïîìèðàíèè?
19 public
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;
26 end;
28 // read-only ïîòîê äëÿ èçâëå÷åíèÿ èç èñõîäíîãî òîëüêî êóñî÷êà
29 TSFSPartialStream = class(TStream)
30 protected
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 ();
41 public
42 // aSrc: ïîòîê-èñõîäíèê.
43 // aPos: íà÷àëüíàÿ ïîçèöèÿ â ïîòîêå. -1 -- ñ òåêóùåé.
44 // åñëè aPos < òåêóùåé ïîçèöèè, òî èñõîäíûé ïîòîê äîëæåí
45 // íîðìàëüíî ïîääåðæèâàòü Seek()!
46 // aSize: êîëè÷åñòâî áàéòèêîâ, êîòîðîå ìîæíî ïðî÷åñòü èç ïîòîêà.
47 // åñëè ìåíüøå íóëÿ -- òî äî êîíöà.
48 // aKillSrc: óáèâàòü ëè èñõîäíûé ïîòîê, êîãäà ñàìè óìèðàåì?
49 // òàêæå ìîæåò ïðèøïàíäîðèòü ê íà÷àëó ôàéëà áóôåð. bufSz áóäåò äîáàâëåíî ê
50 // äëèíå ôàéëà.
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 // áîëüíîé íà ãîëîâó êîäåð áóäåò ïîëó÷àòü ðàçìåð ïðè ïîìîùè
61 // Seek()'à?
62 function Seek (const offset: Int64; origin: TSeekOrigin): Int64; override;
63 end;
65 TSFSGuardStream = class(TStream)
66 protected
67 fSource: TStream; // èñõîäíûé ïîòîê
68 fGuardedStream: TStream; // ïîòîê, êîòîðûé çàâàëèì ïðè ïîìèðàíèè
69 fKillSource: Boolean; // óáèâàòü èñõîäíèê ïðè ïîìèðàíèè?
70 fKillGuarded: Boolean; // óáèâàòü îõðàíÿåìûé ïðè ïîìèðàíèè?
71 fGuardedFirst: Boolean; // ïðè ñìåðòè ïåðâûì ïðèøèáàåì îõðàíÿåìîãî?
73 public
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;
85 end;
87 TSFSMemoryStreamRO = class(TCustomMemoryStream)
88 public
89 constructor Create (pMem: Pointer; pSize: Integer);
91 function Write (const buffer; count: LongInt): LongInt; override;
92 end;
95 implementation
97 uses
98 sfs; // for ESFSError
100 { TSFSSDLStream }
101 constructor TSFSSDLStream.Create (aSrc: PSDL_RWops; aFreeSource: Boolean=true);
102 begin
103 inherited Create();
104 //ASSERT(aSrc <> nil);
105 fRW := aSrc;
106 fFreeSource := aFreeSource;
107 end;
109 destructor TSFSSDLStream.Destroy ();
110 begin
111 if fFreeSource and (fRW <> nil) then SDL_FreeRW(fRW);
112 inherited Destroy();
113 end;
115 function TSFSSDLStream.Read (var buffer; count: LongInt): LongInt;
116 begin
117 if (fRW = nil) or (count <= 0) then begin result := 0; exit; end;
118 result := SDL_RWread(fRW, @buffer, 1, count);
119 end;
121 function TSFSSDLStream.Write (const buffer; count: LongInt): LongInt;
122 begin
123 if (fRW = nil) or (count <= 0) then begin result := 0; exit; end;
124 result := SDL_RWwrite(fRW, @buffer, 1, count);
125 end;
127 function TSFSSDLStream.Seek (const offset: Int64; origin: TSeekOrigin): Int64;
128 var
129 ss: Integer;
130 begin
131 if fRW = nil then begin result := 0; exit; end;
132 case origin of
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 // äðóãèõ íå áûâàåò. à ó êîãî áûâàåò, òîìó ÿ íå äîêòîð.
138 end;
139 result := SDL_RWseek(fRW, offset, ss);
140 if result = -1 then raise ESFSError.Create('Seek() error');
141 end;
144 { TSFSPartialStream }
145 constructor TSFSPartialStream.Create (aSrc: TStream; aPos, aSize: Int64; aKillSrc: Boolean; preBuf: Pointer=nil; bufSz: Integer=0);
146 begin
147 inherited Create();
148 ASSERT(aSrc <> nil);
149 if aPos < 0 then aPos := aSrc.Position;
150 if aSize < 0 then aSize := 0;
151 fSource := aSrc;
152 fKillSource := aKillSrc;
153 fLastReadPos := 0;
154 fCurrentPos := 0;
155 fStartPos := aPos;
156 fSize := aSize;
157 if bufSz > 0 then
158 begin
159 SetLength(fPreBuf, bufSz);
160 Move(preBuf^, fPreBuf[0], bufSz);
161 Inc(fSize, bufSz);
162 end
163 else
164 begin
165 fPreBuf := nil;
166 end;
167 end;
169 destructor TSFSPartialStream.Destroy ();
170 begin
171 if fKillSource then FreeAndNil(fSource);
172 inherited Destroy();
173 end;
175 procedure TSFSPartialStream.CheckPos ();
176 begin
177 if fSource.Position <> fStartPos+fCurrentPos-Length(fPreBuf) then
178 begin
179 fSource.Position := fStartPos+fCurrentPos-Length(fPreBuf);
180 end;
181 fLastReadPos := fCurrentPos;
182 end;
184 function TSFSPartialStream.Write (const buffer; count: LongInt): LongInt;
185 begin
186 result := 0;
187 raise ESFSError.Create('can''t write to read-only stream');
188 // à íå õîäè, íåõîðîøèé, â íàø ñàäèê ãóëÿòü!
189 end;
191 function TSFSPartialStream.Read (var buffer; count: LongInt): LongInt;
192 var
193 left: Int64;
194 pc: Pointer;
195 rd: LongInt;
196 begin
197 if count < 0 then raise ESFSError.Create('invalid Read() call'); // ñêàçî÷íûé äîëáî¸á...
198 if count = 0 then begin result := 0; exit; end;
199 pc := @buffer;
200 result := 0;
201 if (Length(fPreBuf) > 0) and (fCurrentPos < Length(fPreBuf)) then
202 begin
203 fLastReadPos := fCurrentPos;
204 left := Length(fPreBuf)-fCurrentPos;
205 if left > count then left := count;
206 if left > 0 then
207 begin
208 Move(fPreBuf[fCurrentPos], pc^, left);
209 Inc(PChar(pc), left);
210 Inc(fCurrentPos, left);
211 fLastReadPos := fCurrentPos;
212 Dec(count, left);
213 result := left;
214 if count = 0 then exit;
215 end;
216 end;
217 CheckPos();
218 left := fSize-fCurrentPos;
219 if left < count then count := left; // è òàê ñëó÷àåòñÿ...
220 if count > 0 then
221 begin
222 rd := fSource.Read(pc^, count);
223 Inc(result, rd);
224 Inc(fCurrentPos, rd);
225 fLastReadPos := fCurrentPos;
226 end
227 else
228 begin
229 result := 0;
230 end;
231 end;
233 function TSFSPartialStream.Seek (const offset: Int64; origin: TSeekOrigin): Int64;
234 begin
235 case origin of
236 soBeginning: result := offset;
237 soCurrent: result := offset+fCurrentPos;
238 soEnd: result := fSize+offset;
239 else raise ESFSError.Create('invalid Seek() call');
240 // äðóãèõ íå áûâàåò. à ó êîãî áûâàåò, òîìó ÿ íå äîêòîð.
241 end;
242 if result < 0 then result := 0
243 else if result > fSize then result := fSize;
244 fCurrentPos := result;
245 end;
248 { TSFSGuardStream }
249 constructor TSFSGuardStream.Create (aSrc, aGuarded: TStream; aKillSrc, aKillGuarded: Boolean; aGuardedFirst: Boolean=true);
250 begin
251 inherited Create();
252 fSource := aSrc; fGuardedStream := aGuarded;
253 fKillSource := aKillSrc; fKillGuarded := aKillGuarded;
254 fGuardedFirst := aGuardedFirst;
255 end;
257 destructor TSFSGuardStream.Destroy ();
258 begin
259 if fKillGuarded and fGuardedFirst then FreeAndNil(fGuardedStream);
260 if fKillSource then FreeAndNil(fSource);
261 if fKillGuarded and not fGuardedFirst then FreeAndNil(fGuardedStream);
262 inherited Destroy();
263 end;
265 function TSFSGuardStream.Read (var buffer; count: LongInt): LongInt;
266 begin
267 result := fSource.Read(buffer, count);
268 end;
270 function TSFSGuardStream.Write (const buffer; count: LongInt): LongInt;
271 begin
272 result := fSource.Write(buffer, count);
273 end;
275 function TSFSGuardStream.Seek (const offset: Int64; origin: TSeekOrigin): Int64;
276 begin
277 result := fSource.Seek(offset, origin);
278 end;
281 { TSFSMemoryStreamRO }
282 constructor TSFSMemoryStreamRO.Create (pMem: Pointer; pSize: Integer);
283 begin
284 inherited Create();
285 SetPointer(pMem, pSize);
286 Position := 0;
287 end;
289 function TSFSMemoryStreamRO.Write (const buffer; count: LongInt): LongInt;
290 begin
291 result := 0;
292 raise ESFSError.Create('can''t write to read-only stream');
293 // ñîâñåì ñáðåíäèë...
294 end;
297 end.