cstreams.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
  4. This module provides stream classes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cstreams;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cutils;
  23. {****************************************************************************
  24. TCStream
  25. ****************************************************************************}
  26. {
  27. TCStream is copied directly from classesh.inc from the FCL so
  28. it's compatible with the normal Classes.TStream.
  29. TCFileStream is a merge of THandleStream and TFileStream and updated
  30. to have a 'file' type instead of Handle.
  31. TCCustomMemoryStream and TCMemoryStream are direct copies.
  32. }
  33. const
  34. { TCStream seek origins }
  35. soFromBeginning = 0;
  36. soFromCurrent = 1;
  37. soFromEnd = 2;
  38. { TCFileStream create mode }
  39. fmCreate = $FFFF;
  40. fmOpenRead = 0;
  41. fmOpenWrite = 1;
  42. fmOpenReadWrite = 2;
  43. var
  44. { Used for Error reporting instead of exceptions }
  45. CStreamError : longint;
  46. type
  47. { Fake TComponent class, it isn't used any futher }
  48. TCComponent = class(TObject)
  49. end;
  50. { TCStream abstract class }
  51. TCStream = class(TObject)
  52. private
  53. function GetPosition: Longint;
  54. procedure SetPosition(Pos: Longint);
  55. function GetSize: Longint;
  56. protected
  57. procedure SetSize(NewSize: Longint); virtual;
  58. public
  59. function Read(var Buffer; Count: Longint): Longint; virtual; abstract;
  60. function Write(const Buffer; Count: Longint): Longint; virtual; abstract;
  61. function Seek(Offset: Longint; Origin: Word): Longint; virtual; abstract;
  62. procedure ReadBuffer(var Buffer; Count: Longint);
  63. procedure WriteBuffer(const Buffer; Count: Longint);
  64. function CopyFrom(Source: TCStream; Count: Longint): Longint;
  65. function ReadComponent(Instance: TCComponent): TCComponent;
  66. function ReadComponentRes(Instance: TCComponent): TCComponent;
  67. procedure WriteComponent(Instance: TCComponent);
  68. procedure WriteComponentRes(const ResName: string; Instance: TCComponent);
  69. procedure WriteDescendent(Instance, Ancestor: TCComponent);
  70. procedure WriteDescendentRes(const ResName: string; Instance, Ancestor: TCComponent);
  71. procedure WriteResourceHeader(const ResName: string; {!!!:out} var FixupInfo: Integer);
  72. procedure FixupResourceHeader(FixupInfo: Integer);
  73. procedure ReadResHeader;
  74. function ReadByte : Byte;
  75. function ReadWord : Word;
  76. function ReadDWord : Cardinal;
  77. function ReadAnsiString : AnsiString;
  78. procedure WriteByte(b : Byte);
  79. procedure WriteWord(w : Word);
  80. procedure WriteDWord(d : Cardinal);
  81. Procedure WriteAnsiString (S : AnsiString);
  82. property Position: Longint read GetPosition write SetPosition;
  83. property Size: Longint read GetSize write SetSize;
  84. end;
  85. { TFileStream class }
  86. TCFileStream = class(TCStream)
  87. Private
  88. FFileName : String;
  89. FHandle: File;
  90. protected
  91. procedure SetSize(NewSize: Longint); override;
  92. public
  93. constructor Create(const AFileName: string; Mode: Word);
  94. destructor Destroy; override;
  95. function Read(var Buffer; Count: Longint): Longint; override;
  96. function Write(const Buffer; Count: Longint): Longint; override;
  97. function Seek(Offset: Longint; Origin: Word): Longint; override;
  98. property FileName : String Read FFilename;
  99. end;
  100. { TCustomMemoryStream abstract class }
  101. TCCustomMemoryStream = class(TCStream)
  102. private
  103. FMemory: Pointer;
  104. FSize, FPosition: Longint;
  105. protected
  106. procedure SetPointer(Ptr: Pointer; ASize: Longint);
  107. public
  108. function Read(var Buffer; Count: Longint): Longint; override;
  109. function Seek(Offset: Longint; Origin: Word): Longint; override;
  110. procedure SaveToStream(Stream: TCStream);
  111. procedure SaveToFile(const FileName: string);
  112. property Memory: Pointer read FMemory;
  113. end;
  114. { TCMemoryStream }
  115. TCMemoryStream = class(TCCustomMemoryStream)
  116. private
  117. FCapacity: Longint;
  118. procedure SetCapacity(NewCapacity: Longint);
  119. protected
  120. function Realloc(var NewCapacity: Longint): Pointer; virtual;
  121. property Capacity: Longint read FCapacity write SetCapacity;
  122. public
  123. destructor Destroy; override;
  124. procedure Clear;
  125. procedure LoadFromStream(Stream: TCStream);
  126. procedure LoadFromFile(const FileName: string);
  127. procedure SetSize(NewSize: Longint); override;
  128. function Write(const Buffer; Count: Longint): Longint; override;
  129. end;
  130. implementation
  131. Type
  132. PByte = ^Byte;
  133. {*****************************************************************************
  134. TCStream
  135. *****************************************************************************}
  136. function TCStream.GetPosition: Longint;
  137. begin
  138. Result:=Seek(0,soFromCurrent);
  139. end;
  140. procedure TCStream.SetPosition(Pos: Longint);
  141. begin
  142. Seek(pos,soFromBeginning);
  143. end;
  144. function TCStream.GetSize: Longint;
  145. var
  146. p : longint;
  147. begin
  148. p:=GetPosition;
  149. GetSize:=Seek(0,soFromEnd);
  150. Seek(p,soFromBeginning);
  151. end;
  152. procedure TCStream.SetSize(NewSize: Longint);
  153. begin
  154. // We do nothing. Pipe streams don't support this
  155. // As wel as possible read-ony streams !!
  156. end;
  157. procedure TCStream.ReadBuffer(var Buffer; Count: Longint);
  158. begin
  159. CStreamError:=0;
  160. if Read(Buffer,Count)<Count then
  161. CStreamError:=102;
  162. end;
  163. procedure TCStream.WriteBuffer(const Buffer; Count: Longint);
  164. begin
  165. CStreamError:=0;
  166. if Write(Buffer,Count)<Count then
  167. CStreamError:=103;
  168. end;
  169. function TCStream.CopyFrom(Source: TCStream; Count: Longint): Longint;
  170. var
  171. i : longint;
  172. buffer : array[0..1023] of byte;
  173. begin
  174. CStreamError:=0;
  175. Result:=0;
  176. while Count>0 do
  177. begin
  178. if (Count>sizeof(buffer)) then
  179. i:=sizeof(Buffer)
  180. else
  181. i:=Count;
  182. i:=Source.Read(buffer,i);
  183. i:=Write(buffer,i);
  184. dec(count,i);
  185. inc(Result,i);
  186. if i=0 then
  187. exit;
  188. end;
  189. end;
  190. function TCStream.ReadComponent(Instance: TCComponent): TCComponent;
  191. begin
  192. Result:=nil;
  193. end;
  194. function TCStream.ReadComponentRes(Instance: TCComponent): TCComponent;
  195. begin
  196. Result:=nil;
  197. end;
  198. procedure TCStream.WriteComponent(Instance: TCComponent);
  199. begin
  200. end;
  201. procedure TCStream.WriteComponentRes(const ResName: string; Instance: TCComponent);
  202. begin
  203. end;
  204. procedure TCStream.WriteDescendent(Instance, Ancestor: TCComponent);
  205. begin
  206. end;
  207. procedure TCStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TCComponent);
  208. begin
  209. end;
  210. procedure TCStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Integer);
  211. begin
  212. end;
  213. procedure TCStream.FixupResourceHeader(FixupInfo: Integer);
  214. begin
  215. end;
  216. procedure TCStream.ReadResHeader;
  217. begin
  218. end;
  219. function TCStream.ReadByte : Byte;
  220. var
  221. b : Byte;
  222. begin
  223. ReadBuffer(b,1);
  224. ReadByte:=b;
  225. end;
  226. function TCStream.ReadWord : Word;
  227. var
  228. w : Word;
  229. begin
  230. ReadBuffer(w,2);
  231. ReadWord:=w;
  232. end;
  233. function TCStream.ReadDWord : Cardinal;
  234. var
  235. d : Cardinal;
  236. begin
  237. ReadBuffer(d,4);
  238. ReadDWord:=d;
  239. end;
  240. Function TCStream.ReadAnsiString : AnsiString;
  241. Var
  242. TheSize : Longint;
  243. P : PByte ;
  244. begin
  245. ReadBuffer (TheSize,SizeOf(TheSize));
  246. SetLength(Result,TheSize);
  247. // Illegal typecast if no AnsiStrings defined.
  248. if TheSize>0 then
  249. begin
  250. ReadBuffer (Pointer(Result)^,TheSize);
  251. P:=PByte(PtrInt(Result)+TheSize);
  252. p^:=0;
  253. end;
  254. end;
  255. Procedure TCStream.WriteAnsiString (S : AnsiString);
  256. Var L : Longint;
  257. begin
  258. L:=Length(S);
  259. WriteBuffer (L,SizeOf(L));
  260. WriteBuffer (Pointer(S)^,L);
  261. end;
  262. procedure TCStream.WriteByte(b : Byte);
  263. begin
  264. WriteBuffer(b,1);
  265. end;
  266. procedure TCStream.WriteWord(w : Word);
  267. begin
  268. WriteBuffer(w,2);
  269. end;
  270. procedure TCStream.WriteDWord(d : Cardinal);
  271. begin
  272. WriteBuffer(d,4);
  273. end;
  274. {****************************************************************************}
  275. {* TCFileStream *}
  276. {****************************************************************************}
  277. constructor TCFileStream.Create(const AFileName: string; Mode: Word);
  278. begin
  279. FFileName:=AFileName;
  280. If Mode=fmcreate then
  281. begin
  282. system.assign(FHandle,AFileName);
  283. {$I-}
  284. system.rewrite(FHandle,1);
  285. {$I+}
  286. CStreamError:=IOResult;
  287. end
  288. else
  289. begin
  290. system.assign(FHandle,AFileName);
  291. {$I-}
  292. system.reset(FHandle,1);
  293. {$I+}
  294. CStreamError:=IOResult;
  295. end;
  296. end;
  297. destructor TCFileStream.Destroy;
  298. begin
  299. {$I-}
  300. System.Close(FHandle);
  301. {$I+}
  302. CStreamError:=IOResult;
  303. end;
  304. function TCFileStream.Read(var Buffer; Count: Longint): Longint;
  305. begin
  306. CStreamError:=0;
  307. BlockRead(FHandle,Buffer,Count,Result);
  308. If Result=-1 then Result:=0;
  309. end;
  310. function TCFileStream.Write(const Buffer; Count: Longint): Longint;
  311. begin
  312. CStreamError:=0;
  313. BlockWrite (FHandle,(@Buffer)^,Count,Result);
  314. If Result=-1 then Result:=0;
  315. end;
  316. Procedure TCFileStream.SetSize(NewSize: Longint);
  317. begin
  318. {$I-}
  319. System.Seek(FHandle,NewSize);
  320. System.Truncate(FHandle);
  321. {$I+}
  322. CStreamError:=IOResult;
  323. end;
  324. function TCFileStream.Seek(Offset: Longint; Origin: Word): Longint;
  325. var
  326. l : longint;
  327. begin
  328. {$I-}
  329. case Origin of
  330. soFromBeginning :
  331. System.Seek(FHandle,Offset);
  332. soFromCurrent :
  333. begin
  334. l:=System.FilePos(FHandle);
  335. inc(l,Offset);
  336. System.Seek(FHandle,l);
  337. end;
  338. soFromEnd :
  339. begin
  340. l:=System.FileSize(FHandle);
  341. dec(l,Offset);
  342. if l<0 then
  343. l:=0;
  344. System.Seek(FHandle,l);
  345. end;
  346. end;
  347. {$I+}
  348. CStreamError:=IOResult;
  349. Result:=CStreamError;
  350. end;
  351. {****************************************************************************}
  352. {* TCustomMemoryStream *}
  353. {****************************************************************************}
  354. procedure TCCustomMemoryStream.SetPointer(Ptr: Pointer; ASize: Longint);
  355. begin
  356. FMemory:=Ptr;
  357. FSize:=ASize;
  358. end;
  359. function TCCustomMemoryStream.Read(var Buffer; Count: Longint): Longint;
  360. begin
  361. Result:=0;
  362. If (FSize>0) and (FPosition<Fsize) then
  363. begin
  364. Result:=FSize-FPosition;
  365. If Result>Count then Result:=Count;
  366. Move (Pointer(PtrInt(FMemory)+FPosition)^,Buffer,Result);
  367. FPosition:=Fposition+Result;
  368. end;
  369. end;
  370. function TCCustomMemoryStream.Seek(Offset: Longint; Origin: Word): Longint;
  371. begin
  372. Case Origin of
  373. soFromBeginning : FPosition:=Offset;
  374. soFromEnd : FPosition:=FSize+Offset;
  375. soFromCurrent : FpoSition:=FPosition+Offset;
  376. end;
  377. Result:=FPosition;
  378. end;
  379. procedure TCCustomMemoryStream.SaveToStream(Stream: TCStream);
  380. begin
  381. if FSize>0 then Stream.WriteBuffer (FMemory^,FSize);
  382. end;
  383. procedure TCCustomMemoryStream.SaveToFile(const FileName: string);
  384. Var S : TCFileStream;
  385. begin
  386. Try
  387. S:=TCFileStream.Create (FileName,fmCreate);
  388. SaveToStream(S);
  389. finally
  390. S.free;
  391. end;
  392. end;
  393. {****************************************************************************}
  394. {* TCMemoryStream *}
  395. {****************************************************************************}
  396. Const TMSGrow = 4096; { Use 4k blocks. }
  397. procedure TCMemoryStream.SetCapacity(NewCapacity: Longint);
  398. begin
  399. SetPointer (Realloc(NewCapacity),Fsize);
  400. FCapacity:=NewCapacity;
  401. end;
  402. function TCMemoryStream.Realloc(var NewCapacity: Longint): Pointer;
  403. Var MoveSize : Longint;
  404. begin
  405. CStreamError:=0;
  406. If NewCapacity>0 Then // round off to block size.
  407. NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
  408. // Only now check !
  409. If NewCapacity=FCapacity then
  410. Result:=FMemory
  411. else
  412. If NewCapacity=0 then
  413. FreeMem (FMemory,Fcapacity)
  414. else
  415. begin
  416. GetMem (Result,NewCapacity);
  417. If Result=Nil then
  418. CStreamError:=204;
  419. If FCapacity>0 then
  420. begin
  421. MoveSize:=FSize;
  422. If MoveSize>NewCapacity then MoveSize:=NewCapacity;
  423. Move (Fmemory^,Result^,MoveSize);
  424. FreeMem (FMemory,FCapacity);
  425. end;
  426. end;
  427. end;
  428. destructor TCMemoryStream.Destroy;
  429. begin
  430. Clear;
  431. Inherited Destroy;
  432. end;
  433. procedure TCMemoryStream.Clear;
  434. begin
  435. FSize:=0;
  436. FPosition:=0;
  437. SetCapacity (0);
  438. end;
  439. procedure TCMemoryStream.LoadFromStream(Stream: TCStream);
  440. begin
  441. Stream.Position:=0;
  442. SetSize(Stream.Size);
  443. If FSize>0 then Stream.ReadBuffer(FMemory^,FSize);
  444. end;
  445. procedure TCMemoryStream.LoadFromFile(const FileName: string);
  446. Var S : TCFileStream;
  447. begin
  448. Try
  449. S:=TCFileStream.Create (FileName,fmOpenRead);
  450. LoadFromStream(S);
  451. finally
  452. S.free;
  453. end;
  454. end;
  455. procedure TCMemoryStream.SetSize(NewSize: Longint);
  456. begin
  457. SetCapacity (NewSize);
  458. FSize:=NewSize;
  459. IF FPosition>FSize then
  460. FPosition:=FSize;
  461. end;
  462. function TCMemoryStream.Write(const Buffer; Count: Longint): Longint;
  463. Var NewPos : Longint;
  464. begin
  465. If Count=0 then
  466. begin
  467. Result:=0;
  468. exit;
  469. end;
  470. NewPos:=FPosition+Count;
  471. If NewPos>Fsize then
  472. begin
  473. IF NewPos>FCapacity then
  474. SetCapacity (NewPos);
  475. FSize:=Newpos;
  476. end;
  477. System.Move (Buffer,Pointer(Ptrint(FMemory)+FPosition)^,Count);
  478. FPosition:=NewPos;
  479. Result:=Count;
  480. end;
  481. end.
  482. {
  483. $Log$
  484. Revision 1.8 2004-06-20 08:55:29 florian
  485. * logs truncated
  486. Revision 1.7 2004/06/16 20:07:07 florian
  487. * dwarf branch merged
  488. Revision 1.6.2.2 2004/04/29 19:07:22 peter
  489. * compile fixes
  490. Revision 1.6.2.1 2004/04/28 21:46:56 peter
  491. * compile fixes for x86-64
  492. }