streams.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************}
  12. {* TStream *}
  13. {****************************************************************************}
  14. {$ifdef seek64bit}
  15. function TStream.GetPosition: Int64;
  16. begin
  17. Result:=Seek(0,soCurrent);
  18. end;
  19. procedure TStream.SetPosition(Pos: Int64);
  20. begin
  21. Seek(pos,soBeginning);
  22. end;
  23. procedure TStream.SetSize64(NewSize: Int64);
  24. begin
  25. // Required because can't use overloaded functions in properties
  26. SetSize(NewSize);
  27. end;
  28. function TStream.GetSize: Int64;
  29. var
  30. p : longint;
  31. begin
  32. p:=GetPosition;
  33. GetSize:=Seek(0,soEnd);
  34. Seek(p,soBeginning);
  35. end;
  36. procedure TStream.SetSize(NewSize: Longint);
  37. begin
  38. // We do nothing. Pipe streams don't support this
  39. // As wel as possible read-ony streams !!
  40. end;
  41. procedure TStream.SetSize(NewSize: Int64);
  42. begin
  43. // Backwards compatibility that calls the longint SetSize
  44. if (NewSize<Low(longint)) or
  45. (NewSize>High(longint)) then
  46. raise ERangeError.Create(SRangeError);
  47. SetSize(longint(NewSize));
  48. end;
  49. function TStream.Seek(Offset: Longint; Origin: Word): Longint;
  50. type
  51. TSeek64 = function(offset:Int64;Origin:TSeekorigin):Int64 of object;
  52. var
  53. CurrSeek,
  54. TStreamSeek : TSeek64;
  55. CurrClass : TClass;
  56. begin
  57. // Redirect calls to 64bit Seek, but we can't call the 64bit Seek
  58. // from TStream, because then we end up in an infinite loop
  59. CurrSeek:=nil;
  60. CurrClass:=Classtype;
  61. while (CurrClass<>nil) and
  62. (CurrClass<>TStream) do
  63. CurrClass:=CurrClass.Classparent;
  64. if CurrClass<>nil then
  65. begin
  66. CurrSeek:[email protected];
  67. TStreamSeek:=@TStream(@CurrClass).Seek;
  68. if TMethod(TStreamSeek).Code=TMethod(CurrSeek).Code then
  69. CurrSeek:=nil;
  70. end;
  71. if CurrSeek<>nil then
  72. Result:=Seek(Int64(offset),TSeekOrigin(origin))
  73. else
  74. raise EStreamError.CreateFmt(SSeekNotImplemented,[ClassName]);
  75. end;
  76. function TStream.Seek(Offset: Int64; Origin: TSeekorigin): Int64;
  77. begin
  78. // Backwards compatibility that calls the longint Seek
  79. if (Offset<Low(longint)) or
  80. (Offset>High(longint)) then
  81. raise ERangeError.Create(SRangeError);
  82. Result:=Seek(longint(Offset),ord(Origin));
  83. end;
  84. {$else seek64bit}
  85. function TStream.GetPosition: Longint;
  86. begin
  87. Result:=Seek(0,soFromCurrent);
  88. end;
  89. procedure TStream.SetPosition(Pos: Longint);
  90. begin
  91. Seek(pos,soFromBeginning);
  92. end;
  93. function TStream.GetSize: Longint;
  94. var
  95. p : longint;
  96. begin
  97. p:=GetPosition;
  98. GetSize:=Seek(0,soFromEnd);
  99. Seek(p,soFromBeginning);
  100. end;
  101. procedure TStream.SetSize(NewSize: Longint);
  102. begin
  103. // We do nothing. Pipe streams don't support this
  104. // As wel as possible read-ony streams !!
  105. end;
  106. {$endif seek64bit}
  107. procedure TStream.ReadBuffer(var Buffer; Count: Longint);
  108. begin
  109. if Read(Buffer,Count)<Count then
  110. Raise EReadError.Create(SReadError);
  111. end;
  112. procedure TStream.WriteBuffer(const Buffer; Count: Longint);
  113. begin
  114. if Write(Buffer,Count)<Count then
  115. Raise EWriteError.Create(SWriteError);
  116. end;
  117. function TStream.CopyFrom(Source: TStream; Count: Int64): Int64;
  118. var
  119. i : Int64;
  120. buffer : array[0..1023] of byte;
  121. begin
  122. CopyFrom:=0;
  123. If (Count=0) then
  124. begin
  125. // This WILL fail for non-seekable streams...
  126. Source.Position:=0;
  127. Count:=Source.Size;
  128. end;
  129. while Count>0 do
  130. begin
  131. if (Count>sizeof(buffer)) then
  132. i:=sizeof(Buffer)
  133. else
  134. i:=Count;
  135. i:=Source.Read(buffer,i);
  136. i:=Write(buffer,i);
  137. dec(count,i);
  138. CopyFrom:=CopyFrom+i;
  139. end;
  140. end;
  141. function TStream.ReadComponent(Instance: TComponent): TComponent;
  142. var
  143. Reader: TReader;
  144. begin
  145. Reader := TReader.Create(Self, 4096);
  146. try
  147. Result := Reader.ReadRootComponent(Instance);
  148. finally
  149. Reader.Free;
  150. end;
  151. end;
  152. function TStream.ReadComponentRes(Instance: TComponent): TComponent;
  153. begin
  154. ReadResHeader;
  155. Result := ReadComponent(Instance);
  156. end;
  157. procedure TStream.WriteComponent(Instance: TComponent);
  158. begin
  159. WriteDescendent(Instance, nil);
  160. end;
  161. procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
  162. begin
  163. WriteDescendentRes(ResName, Instance, nil);
  164. end;
  165. procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);
  166. var
  167. Driver : TAbstractObjectWriter;
  168. Writer : TWriter;
  169. begin
  170. Driver := TBinaryObjectWriter.Create(Self, 4096);
  171. Try
  172. Writer := TWriter.Create(Driver);
  173. Try
  174. Writer.WriteDescendent(Instance, Ancestor);
  175. Finally
  176. Writer.Destroy;
  177. end;
  178. Finally
  179. Driver.Free;
  180. end;
  181. end;
  182. procedure TStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
  183. var
  184. FixupInfo: Integer;
  185. begin
  186. { Write a resource header }
  187. WriteResourceHeader(ResName, FixupInfo);
  188. { Write the instance itself }
  189. WriteDescendent(Instance, Ancestor);
  190. { Insert the correct resource size into the resource header }
  191. FixupResourceHeader(FixupInfo);
  192. end;
  193. procedure TStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Integer);
  194. begin
  195. { Numeric resource type }
  196. WriteByte($ff);
  197. { Application defined data }
  198. WriteWord($0a);
  199. { write the name as asciiz }
  200. WriteBuffer(ResName[1],length(ResName));
  201. WriteByte(0);
  202. { Movable, Pure and Discardable }
  203. WriteWord($1030);
  204. { Placeholder for the resource size }
  205. WriteDWord(0);
  206. { Return current stream position so that the resource size can be
  207. inserted later }
  208. FixupInfo := Position;
  209. end;
  210. procedure TStream.FixupResourceHeader(FixupInfo: Integer);
  211. var
  212. ResSize : Integer;
  213. begin
  214. ResSize := Position - FixupInfo;
  215. { Insert the correct resource size into the placeholder written by
  216. WriteResourceHeader }
  217. Position := FixupInfo - 4;
  218. WriteDWord(ResSize);
  219. { Seek back to the end of the resource }
  220. Position := FixupInfo + ResSize;
  221. end;
  222. procedure TStream.ReadResHeader;
  223. begin
  224. try
  225. { application specific resource ? }
  226. if ReadByte<>$ff then
  227. raise EInvalidImage.Create(SInvalidImage);
  228. if ReadWord<>$000a then
  229. raise EInvalidImage.Create(SInvalidImage);
  230. { read name }
  231. while ReadByte<>0 do
  232. ;
  233. { check the access specifier }
  234. if ReadWord<>$1030 then
  235. raise EInvalidImage.Create(SInvalidImage);
  236. { ignore the size }
  237. ReadDWord;
  238. except
  239. on EInvalidImage do
  240. raise;
  241. else
  242. raise EInvalidImage.create(SInvalidImage);
  243. end;
  244. end;
  245. function TStream.ReadByte : Byte;
  246. var
  247. b : Byte;
  248. begin
  249. ReadBuffer(b,1);
  250. ReadByte:=b;
  251. end;
  252. function TStream.ReadWord : Word;
  253. var
  254. w : Word;
  255. begin
  256. ReadBuffer(w,2);
  257. ReadWord:=w;
  258. end;
  259. function TStream.ReadDWord : Cardinal;
  260. var
  261. d : Cardinal;
  262. begin
  263. ReadBuffer(d,4);
  264. ReadDWord:=d;
  265. end;
  266. Function TStream.ReadAnsiString : String;
  267. Type
  268. PByte = ^Byte;
  269. Var
  270. TheSize : Longint;
  271. P : PByte ;
  272. begin
  273. ReadBuffer (TheSize,SizeOf(TheSize));
  274. SetLength(Result,TheSize);
  275. // Illegal typecast if no AnsiStrings defined.
  276. if TheSize>0 then
  277. begin
  278. ReadBuffer (Pointer(Result)^,TheSize);
  279. P:=Pointer(Result)+TheSize;
  280. p^:=0;
  281. end;
  282. end;
  283. Procedure TStream.WriteAnsiString (S : String);
  284. Var L : Longint;
  285. begin
  286. L:=Length(S);
  287. WriteBuffer (L,SizeOf(L));
  288. WriteBuffer (Pointer(S)^,L);
  289. end;
  290. procedure TStream.WriteByte(b : Byte);
  291. begin
  292. WriteBuffer(b,1);
  293. end;
  294. procedure TStream.WriteWord(w : Word);
  295. begin
  296. WriteBuffer(w,2);
  297. end;
  298. procedure TStream.WriteDWord(d : Cardinal);
  299. begin
  300. WriteBuffer(d,4);
  301. end;
  302. {****************************************************************************}
  303. {* THandleStream *}
  304. {****************************************************************************}
  305. Constructor THandleStream.Create(AHandle: Integer);
  306. begin
  307. FHandle:=AHandle;
  308. end;
  309. function THandleStream.Read(var Buffer; Count: Longint): Longint;
  310. begin
  311. Result:=FileRead(FHandle,Buffer,Count);
  312. If Result=-1 then Result:=0;
  313. end;
  314. function THandleStream.Write(const Buffer; Count: Longint): Longint;
  315. begin
  316. Result:=FileWrite (FHandle,Buffer,Count);
  317. If Result=-1 then Result:=0;
  318. end;
  319. {$ifdef seek64bit}
  320. Procedure THandleStream.SetSize(NewSize: Longint);
  321. begin
  322. SetSize(Int64(NewSize));
  323. end;
  324. Procedure THandleStream.SetSize(NewSize: Int64);
  325. begin
  326. FileTruncate(FHandle,NewSize);
  327. end;
  328. function THandleStream.Seek(Offset: Int64; Origin: TSeekOrigin): Int64;
  329. begin
  330. Result:=FileSeek(FHandle,Offset,ord(Origin));
  331. end;
  332. {$else seek64bit}
  333. Procedure THandleStream.SetSize(NewSize: Longint);
  334. begin
  335. FileTruncate(FHandle,NewSize);
  336. end;
  337. function THandleStream.Seek(Offset: Longint; Origin: Word): Longint;
  338. begin
  339. Result:=FileSeek(FHandle,Offset,Origin);
  340. end;
  341. {$endif seek64bit}
  342. {****************************************************************************}
  343. {* TFileStream *}
  344. {****************************************************************************}
  345. constructor TFileStream.Create(const AFileName: string; Mode: Word);
  346. begin
  347. FFileName:=AFileName;
  348. If Mode=fmcreate then
  349. FHandle:=FileCreate(AFileName)
  350. else
  351. FHAndle:=FileOpen(AFileName,Mode);
  352. If FHandle<0 then
  353. If Mode=fmcreate then
  354. raise EFCreateError.createfmt(SFCreateError,[AFileName])
  355. else
  356. raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
  357. end;
  358. constructor TFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);
  359. begin
  360. FFileName:=AFileName;
  361. If Mode=fmcreate then
  362. FHandle:=FileCreate(AFileName)
  363. else
  364. FHAndle:=FileOpen(AFileName,Mode);
  365. If FHandle<0 then
  366. If Mode=fmcreate then
  367. raise EFCreateError.createfmt(SFCreateError,[AFileName])
  368. else
  369. raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
  370. end;
  371. destructor TFileStream.Destroy;
  372. begin
  373. FileClose(FHandle);
  374. end;
  375. {****************************************************************************}
  376. {* TCustomMemoryStream *}
  377. {****************************************************************************}
  378. procedure TCustomMemoryStream.SetPointer(Ptr: Pointer; ASize: Longint);
  379. begin
  380. FMemory:=Ptr;
  381. FSize:=ASize;
  382. end;
  383. function TCustomMemoryStream.Read(var Buffer; Count: Longint): Longint;
  384. begin
  385. Result:=0;
  386. If (FSize>0) and (FPosition<Fsize) then
  387. begin
  388. Result:=FSize-FPosition;
  389. If Result>Count then Result:=Count;
  390. Move ((FMemory+FPosition)^,Buffer,Result);
  391. FPosition:=Fposition+Result;
  392. end;
  393. end;
  394. function TCustomMemoryStream.Seek(Offset: Longint; Origin: Word): Longint;
  395. begin
  396. Case Origin of
  397. soFromBeginning : FPosition:=Offset;
  398. soFromEnd : FPosition:=FSize+Offset;
  399. soFromCurrent : FpoSition:=FPosition+Offset;
  400. end;
  401. Result:=FPosition;
  402. end;
  403. procedure TCustomMemoryStream.SaveToStream(Stream: TStream);
  404. begin
  405. if FSize>0 then Stream.WriteBuffer (FMemory^,FSize);
  406. end;
  407. procedure TCustomMemoryStream.SaveToFile(const FileName: string);
  408. Var S : TFileStream;
  409. begin
  410. Try
  411. S:=TFileStream.Create (FileName,fmCreate);
  412. SaveToStream(S);
  413. finally
  414. S.free;
  415. end;
  416. end;
  417. {****************************************************************************}
  418. {* TMemoryStream *}
  419. {****************************************************************************}
  420. Const TMSGrow = 4096; { Use 4k blocks. }
  421. procedure TMemoryStream.SetCapacity(NewCapacity: Longint);
  422. begin
  423. SetPointer (Realloc(NewCapacity),Fsize);
  424. FCapacity:=NewCapacity;
  425. end;
  426. function TMemoryStream.Realloc(var NewCapacity: Longint): Pointer;
  427. Var MoveSize : Longint;
  428. begin
  429. If NewCapacity>0 Then // round off to block size.
  430. NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
  431. // Only now check !
  432. If NewCapacity=FCapacity then
  433. Result:=FMemory
  434. else
  435. If NewCapacity=0 then
  436. FreeMem (FMemory,Fcapacity)
  437. else
  438. begin
  439. GetMem (Result,NewCapacity);
  440. If Result=Nil then
  441. Raise EStreamError.Create(SMemoryStreamError);
  442. If FCapacity>0 then
  443. begin
  444. MoveSize:=FSize;
  445. If MoveSize>NewCapacity then MoveSize:=NewCapacity;
  446. Move (Fmemory^,Result^,MoveSize);
  447. FreeMem (FMemory,FCapacity);
  448. end;
  449. end;
  450. end;
  451. destructor TMemoryStream.Destroy;
  452. begin
  453. Clear;
  454. Inherited Destroy;
  455. end;
  456. procedure TMemoryStream.Clear;
  457. begin
  458. FSize:=0;
  459. FPosition:=0;
  460. SetCapacity (0);
  461. end;
  462. procedure TMemoryStream.LoadFromStream(Stream: TStream);
  463. begin
  464. Stream.Position:=0;
  465. SetSize(Stream.Size);
  466. If FSize>0 then Stream.ReadBuffer(FMemory^,FSize);
  467. end;
  468. procedure TMemoryStream.LoadFromFile(const FileName: string);
  469. Var S : TFileStream;
  470. begin
  471. S:=TFileStream.Create (FileName,fmOpenRead);
  472. Try
  473. LoadFromStream(S);
  474. finally
  475. S.free;
  476. end;
  477. end;
  478. procedure TMemoryStream.SetSize(NewSize: Longint);
  479. begin
  480. SetCapacity (NewSize);
  481. FSize:=NewSize;
  482. IF FPosition>FSize then
  483. FPosition:=FSize;
  484. end;
  485. function TMemoryStream.Write(const Buffer; Count: Longint): Longint;
  486. Var NewPos : Longint;
  487. begin
  488. If Count=0 then
  489. exit(0);
  490. NewPos:=FPosition+Count;
  491. If NewPos>Fsize then
  492. begin
  493. IF NewPos>FCapacity then
  494. SetCapacity (NewPos);
  495. FSize:=Newpos;
  496. end;
  497. System.Move (Buffer,(FMemory+FPosition)^,Count);
  498. FPosition:=NewPos;
  499. Result:=Count;
  500. end;
  501. {****************************************************************************}
  502. {* TStringStream *}
  503. {****************************************************************************}
  504. procedure TStringStream.SetSize(NewSize: Longint);
  505. begin
  506. Setlength(FDataString,NewSize);
  507. If FPosition>NewSize then FPosition:=NewSize;
  508. end;
  509. constructor TStringStream.Create(const AString: string);
  510. begin
  511. Inherited create;
  512. FDataString:=AString;
  513. end;
  514. function TStringStream.Read(var Buffer; Count: Longint): Longint;
  515. begin
  516. Result:=Length(FDataString)-FPosition;
  517. If Result>Count then Result:=Count;
  518. // This supposes FDataString to be of type AnsiString !
  519. Move (Pchar(FDataString)[FPosition],Buffer,Result);
  520. FPosition:=FPosition+Result;
  521. end;
  522. function TStringStream.ReadString(Count: Longint): string;
  523. Var NewLen : Longint;
  524. begin
  525. NewLen:=Length(FDataString)-FPosition;
  526. If NewLen>Count then NewLen:=Count;
  527. SetLength(Result,NewLen);
  528. Read (Pointer(Result)^,NewLen);
  529. end;
  530. function TStringStream.Seek(Offset: Longint; Origin: Word): Longint;
  531. begin
  532. Case Origin of
  533. soFromBeginning : FPosition:=Offset;
  534. soFromEnd : FPosition:=Length(FDataString)+Offset;
  535. soFromCurrent : FpoSition:=FPosition+Offset;
  536. end;
  537. If FPosition>Length(FDataString) then FPosition:=Length(FDataString);
  538. If FPosition<0 then FPosition:=0;
  539. Result:=FPosition;
  540. end;
  541. function TStringStream.Write(const Buffer; Count: Longint): Longint;
  542. begin
  543. Result:=Count;
  544. SetSize(FPosition+Count);
  545. // This supposes that FDataString is of type AnsiString)
  546. Move (Buffer,PCHar(FDataString)[Fposition],Count);
  547. FPosition:=FPosition+Count;
  548. end;
  549. procedure TStringStream.WriteString(const AString: string);
  550. begin
  551. Write (PChar(Astring)[0],Length(AString));
  552. end;
  553. {****************************************************************************}
  554. {* TResourceStream *}
  555. {****************************************************************************}
  556. procedure TResourceStream.Initialize(Instance: THandle; Name, ResType: PChar);
  557. begin
  558. end;
  559. constructor TResourceStream.Create(Instance: THandle; const ResName: string; ResType: PChar);
  560. begin
  561. end;
  562. constructor TResourceStream.CreateFromID(Instance: THandle; ResID: Integer; ResType: PChar);
  563. begin
  564. end;
  565. destructor TResourceStream.Destroy;
  566. begin
  567. end;
  568. function TResourceStream.Write(const Buffer; Count: Longint): Longint;
  569. begin
  570. Write:=0;
  571. end;
  572. {
  573. $Log$
  574. Revision 1.2 2003-10-30 16:30:53 peter
  575. * merged copyfrom with 0
  576. Revision 1.3 2003/10/28 22:04:29 michael
  577. + Fixed private seeksupport stuff
  578. Revision 1.2 2003/10/26 14:52:29 michael
  579. + Fixed TStream.CopyFrom with Count=0
  580. Revision 1.13 2003/07/26 16:20:50 michael
  581. + Fixed readstring from TStringStream (
  582. Revision 1.12 2002/04/25 19:14:13 sg
  583. * Fixed TStringStream.ReadString
  584. Revision 1.11 2002/12/18 16:45:33 peter
  585. * set function result in TStream.Seek(int64) found by Mattias Gaertner
  586. Revision 1.10 2002/12/18 16:35:59 peter
  587. * fix crash in Seek()
  588. Revision 1.9 2002/12/18 15:51:52 michael
  589. + Hopefully fixed some issues with int64 seek
  590. Revision 1.8 2002/10/22 09:38:39 michael
  591. + Fixed TmemoryStream.LoadFromStream, reported by Mattias Gaertner
  592. Revision 1.7 2002/09/07 15:15:25 peter
  593. * old logs removed and tabs fixed
  594. }