streams.inc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  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,soFromCurrent);
  18. end;
  19. procedure TStream.SetPosition(Pos: Int64);
  20. begin
  21. Seek(pos,soFromBeginning);
  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,soFromEnd);
  34. Seek(p,soFromBeginning);
  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. 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. while Count>0 do
  124. begin
  125. if (Count>sizeof(buffer)) then
  126. i:=sizeof(Buffer)
  127. else
  128. i:=Count;
  129. i:=Source.Read(buffer,i);
  130. i:=Write(buffer,i);
  131. dec(count,i);
  132. CopyFrom:=CopyFrom+i;
  133. if i=0 then
  134. exit;
  135. end;
  136. end;
  137. function TStream.ReadComponent(Instance: TComponent): TComponent;
  138. var
  139. Reader: TReader;
  140. begin
  141. Reader := TReader.Create(Self, 4096);
  142. try
  143. Result := Reader.ReadRootComponent(Instance);
  144. finally
  145. Reader.Free;
  146. end;
  147. end;
  148. function TStream.ReadComponentRes(Instance: TComponent): TComponent;
  149. begin
  150. ReadResHeader;
  151. Result := ReadComponent(Instance);
  152. end;
  153. procedure TStream.WriteComponent(Instance: TComponent);
  154. begin
  155. WriteDescendent(Instance, nil);
  156. end;
  157. procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
  158. begin
  159. WriteDescendentRes(ResName, Instance, nil);
  160. end;
  161. procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);
  162. var
  163. Driver : TAbstractObjectWriter;
  164. Writer : TWriter;
  165. begin
  166. Driver := TBinaryObjectWriter.Create(Self, 4096);
  167. Try
  168. Writer := TWriter.Create(Driver);
  169. Try
  170. Writer.WriteDescendent(Instance, Ancestor);
  171. Finally
  172. Writer.Destroy;
  173. end;
  174. Finally
  175. Driver.Free;
  176. end;
  177. end;
  178. procedure TStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
  179. var
  180. FixupInfo: Integer;
  181. begin
  182. { Write a resource header }
  183. WriteResourceHeader(ResName, FixupInfo);
  184. { Write the instance itself }
  185. WriteDescendent(Instance, Ancestor);
  186. { Insert the correct resource size into the resource header }
  187. FixupResourceHeader(FixupInfo);
  188. end;
  189. procedure TStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Integer);
  190. begin
  191. { Numeric resource type }
  192. WriteByte($ff);
  193. { Application defined data }
  194. WriteWord($0a);
  195. { write the name as asciiz }
  196. WriteBuffer(ResName[1],length(ResName));
  197. WriteByte(0);
  198. { Movable, Pure and Discardable }
  199. WriteWord($1030);
  200. { Placeholder for the resource size }
  201. WriteDWord(0);
  202. { Return current stream position so that the resource size can be
  203. inserted later }
  204. FixupInfo := Position;
  205. end;
  206. procedure TStream.FixupResourceHeader(FixupInfo: Integer);
  207. var
  208. ResSize : Integer;
  209. begin
  210. ResSize := Position - FixupInfo;
  211. { Insert the correct resource size into the placeholder written by
  212. WriteResourceHeader }
  213. Position := FixupInfo - 4;
  214. WriteDWord(ResSize);
  215. { Seek back to the end of the resource }
  216. Position := FixupInfo + ResSize;
  217. end;
  218. procedure TStream.ReadResHeader;
  219. begin
  220. try
  221. { application specific resource ? }
  222. if ReadByte<>$ff then
  223. raise EInvalidImage.Create(SInvalidImage);
  224. if ReadWord<>$000a then
  225. raise EInvalidImage.Create(SInvalidImage);
  226. { read name }
  227. while ReadByte<>0 do
  228. ;
  229. { check the access specifier }
  230. if ReadWord<>$1030 then
  231. raise EInvalidImage.Create(SInvalidImage);
  232. { ignore the size }
  233. ReadDWord;
  234. except
  235. on EInvalidImage do
  236. raise;
  237. else
  238. raise EInvalidImage.create(SInvalidImage);
  239. end;
  240. end;
  241. function TStream.ReadByte : Byte;
  242. var
  243. b : Byte;
  244. begin
  245. ReadBuffer(b,1);
  246. ReadByte:=b;
  247. end;
  248. function TStream.ReadWord : Word;
  249. var
  250. w : Word;
  251. begin
  252. ReadBuffer(w,2);
  253. ReadWord:=w;
  254. end;
  255. function TStream.ReadDWord : Cardinal;
  256. var
  257. d : Cardinal;
  258. begin
  259. ReadBuffer(d,4);
  260. ReadDWord:=d;
  261. end;
  262. Function TStream.ReadAnsiString : String;
  263. Type
  264. PByte = ^Byte;
  265. Var
  266. TheSize : Longint;
  267. P : PByte ;
  268. begin
  269. ReadBuffer (TheSize,SizeOf(TheSize));
  270. SetLength(Result,TheSize);
  271. // Illegal typecast if no AnsiStrings defined.
  272. if TheSize>0 then
  273. begin
  274. ReadBuffer (Pointer(Result)^,TheSize);
  275. P:=Pointer(Result)+TheSize;
  276. p^:=0;
  277. end;
  278. end;
  279. Procedure TStream.WriteAnsiString (S : String);
  280. Var L : Longint;
  281. begin
  282. L:=Length(S);
  283. WriteBuffer (L,SizeOf(L));
  284. WriteBuffer (Pointer(S)^,L);
  285. end;
  286. procedure TStream.WriteByte(b : Byte);
  287. begin
  288. WriteBuffer(b,1);
  289. end;
  290. procedure TStream.WriteWord(w : Word);
  291. begin
  292. WriteBuffer(w,2);
  293. end;
  294. procedure TStream.WriteDWord(d : Cardinal);
  295. begin
  296. WriteBuffer(d,4);
  297. end;
  298. {****************************************************************************}
  299. {* THandleStream *}
  300. {****************************************************************************}
  301. Constructor THandleStream.Create(AHandle: Integer);
  302. begin
  303. FHandle:=AHandle;
  304. end;
  305. function THandleStream.Read(var Buffer; Count: Longint): Longint;
  306. begin
  307. Result:=FileRead(FHandle,Buffer,Count);
  308. If Result=-1 then Result:=0;
  309. end;
  310. function THandleStream.Write(const Buffer; Count: Longint): Longint;
  311. begin
  312. Result:=FileWrite (FHandle,Buffer,Count);
  313. If Result=-1 then Result:=0;
  314. end;
  315. {$ifdef seek64bit}
  316. Procedure THandleStream.SetSize(NewSize: Longint);
  317. begin
  318. SetSize(Int64(NewSize));
  319. end;
  320. Procedure THandleStream.SetSize(NewSize: Int64);
  321. begin
  322. FileTruncate(FHandle,NewSize);
  323. end;
  324. function THandleStream.Seek(Offset: Int64; Origin: TSeekOrigin): Int64;
  325. begin
  326. Result:=FileSeek(FHandle,Offset,ord(Origin));
  327. end;
  328. {$else seek64bit}
  329. Procedure THandleStream.SetSize(NewSize: Longint);
  330. begin
  331. FileTruncate(FHandle,NewSize);
  332. end;
  333. function THandleStream.Seek(Offset: Longint; Origin: Word): Longint;
  334. begin
  335. Result:=FileSeek(FHandle,Offset,Origin);
  336. end;
  337. {$endif seek64bit}
  338. {****************************************************************************}
  339. {* TFileStream *}
  340. {****************************************************************************}
  341. constructor TFileStream.Create(const AFileName: string; Mode: Word);
  342. begin
  343. FFileName:=AFileName;
  344. If Mode=fmcreate then
  345. FHandle:=FileCreate(AFileName)
  346. else
  347. FHAndle:=FileOpen(AFileName,Mode);
  348. If FHandle<0 then
  349. If Mode=fmcreate then
  350. raise EFCreateError.createfmt(SFCreateError,[AFileName])
  351. else
  352. raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
  353. end;
  354. constructor TFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);
  355. begin
  356. FFileName:=AFileName;
  357. If Mode=fmcreate then
  358. FHandle:=FileCreate(AFileName)
  359. else
  360. FHAndle:=FileOpen(AFileName,Mode);
  361. If FHandle<0 then
  362. If Mode=fmcreate then
  363. raise EFCreateError.createfmt(SFCreateError,[AFileName])
  364. else
  365. raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
  366. end;
  367. destructor TFileStream.Destroy;
  368. begin
  369. FileClose(FHandle);
  370. end;
  371. {****************************************************************************}
  372. {* TCustomMemoryStream *}
  373. {****************************************************************************}
  374. procedure TCustomMemoryStream.SetPointer(Ptr: Pointer; ASize: Longint);
  375. begin
  376. FMemory:=Ptr;
  377. FSize:=ASize;
  378. end;
  379. function TCustomMemoryStream.Read(var Buffer; Count: Longint): Longint;
  380. begin
  381. Result:=0;
  382. If (FSize>0) and (FPosition<Fsize) then
  383. begin
  384. Result:=FSize-FPosition;
  385. If Result>Count then Result:=Count;
  386. Move ((FMemory+FPosition)^,Buffer,Result);
  387. FPosition:=Fposition+Result;
  388. end;
  389. end;
  390. function TCustomMemoryStream.Seek(Offset: Longint; Origin: Word): Longint;
  391. begin
  392. Case Origin of
  393. soFromBeginning : FPosition:=Offset;
  394. soFromEnd : FPosition:=FSize+Offset;
  395. soFromCurrent : FpoSition:=FPosition+Offset;
  396. end;
  397. Result:=FPosition;
  398. end;
  399. procedure TCustomMemoryStream.SaveToStream(Stream: TStream);
  400. begin
  401. if FSize>0 then Stream.WriteBuffer (FMemory^,FSize);
  402. end;
  403. procedure TCustomMemoryStream.SaveToFile(const FileName: string);
  404. Var S : TFileStream;
  405. begin
  406. Try
  407. S:=TFileStream.Create (FileName,fmCreate);
  408. SaveToStream(S);
  409. finally
  410. S.free;
  411. end;
  412. end;
  413. {****************************************************************************}
  414. {* TMemoryStream *}
  415. {****************************************************************************}
  416. Const TMSGrow = 4096; { Use 4k blocks. }
  417. procedure TMemoryStream.SetCapacity(NewCapacity: Longint);
  418. begin
  419. SetPointer (Realloc(NewCapacity),Fsize);
  420. FCapacity:=NewCapacity;
  421. end;
  422. function TMemoryStream.Realloc(var NewCapacity: Longint): Pointer;
  423. Var MoveSize : Longint;
  424. begin
  425. If NewCapacity>0 Then // round off to block size.
  426. NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
  427. // Only now check !
  428. If NewCapacity=FCapacity then
  429. Result:=FMemory
  430. else
  431. If NewCapacity=0 then
  432. FreeMem (FMemory,Fcapacity)
  433. else
  434. begin
  435. GetMem (Result,NewCapacity);
  436. If Result=Nil then
  437. Raise EStreamError.Create(SMemoryStreamError);
  438. If FCapacity>0 then
  439. begin
  440. MoveSize:=FSize;
  441. If MoveSize>NewCapacity then MoveSize:=NewCapacity;
  442. Move (Fmemory^,Result^,MoveSize);
  443. FreeMem (FMemory,FCapacity);
  444. end;
  445. end;
  446. end;
  447. destructor TMemoryStream.Destroy;
  448. begin
  449. Clear;
  450. Inherited Destroy;
  451. end;
  452. procedure TMemoryStream.Clear;
  453. begin
  454. FSize:=0;
  455. FPosition:=0;
  456. SetCapacity (0);
  457. end;
  458. procedure TMemoryStream.LoadFromStream(Stream: TStream);
  459. begin
  460. Stream.Position:=0;
  461. SetSize(Stream.Size);
  462. If FSize>0 then Stream.ReadBuffer(FMemory^,FSize);
  463. end;
  464. procedure TMemoryStream.LoadFromFile(const FileName: string);
  465. Var S : TFileStream;
  466. begin
  467. Try
  468. S:=TFileStream.Create (FileName,fmOpenRead);
  469. LoadFromStream(S);
  470. finally
  471. S.free;
  472. end;
  473. end;
  474. procedure TMemoryStream.SetSize(NewSize: Longint);
  475. begin
  476. SetCapacity (NewSize);
  477. FSize:=NewSize;
  478. IF FPosition>FSize then
  479. FPosition:=FSize;
  480. end;
  481. function TMemoryStream.Write(const Buffer; Count: Longint): Longint;
  482. Var NewPos : Longint;
  483. begin
  484. If Count=0 then
  485. exit(0);
  486. NewPos:=FPosition+Count;
  487. If NewPos>Fsize then
  488. begin
  489. IF NewPos>FCapacity then
  490. SetCapacity (NewPos);
  491. FSize:=Newpos;
  492. end;
  493. System.Move (Buffer,(FMemory+FPosition)^,Count);
  494. FPosition:=NewPos;
  495. Result:=Count;
  496. end;
  497. {****************************************************************************}
  498. {* TStringStream *}
  499. {****************************************************************************}
  500. procedure TStringStream.SetSize(NewSize: Longint);
  501. begin
  502. Setlength(FDataString,NewSize);
  503. If FPosition>NewSize then FPosition:=NewSize;
  504. end;
  505. constructor TStringStream.Create(const AString: string);
  506. begin
  507. Inherited create;
  508. FDataString:=AString;
  509. end;
  510. function TStringStream.Read(var Buffer; Count: Longint): Longint;
  511. begin
  512. Result:=Length(FDataString)-FPosition;
  513. If Result>Count then Result:=Count;
  514. // This supposes FDataString to be of type AnsiString !
  515. Move (Pchar(FDataString)[FPosition],Buffer,Count);
  516. FPosition:=FPosition+Count;
  517. end;
  518. function TStringStream.ReadString(Count: Longint): string;
  519. Var NewLen : Longint;
  520. begin
  521. NewLen:=Length(FDataString)-FPosition;
  522. If NewLen>Count then NewLen:=Count;
  523. SetLength(Result,NewLen);
  524. Read (Pointer(Result)^,NewLen);
  525. ReadString:='';
  526. end;
  527. function TStringStream.Seek(Offset: Longint; Origin: Word): Longint;
  528. begin
  529. Case Origin of
  530. soFromBeginning : FPosition:=Offset;
  531. soFromEnd : FPosition:=Length(FDataString)+Offset;
  532. soFromCurrent : FpoSition:=FPosition+Offset;
  533. end;
  534. If FPosition>Length(FDataString) then FPosition:=Length(FDataString);
  535. If FPosition<0 then FPosition:=0;
  536. Result:=FPosition;
  537. end;
  538. function TStringStream.Write(const Buffer; Count: Longint): Longint;
  539. begin
  540. Result:=Count;
  541. SetSize(FPosition+Count);
  542. // This supposes that FDataString is of type AnsiString)
  543. Move (Buffer,PCHar(FDataString)[Fposition],Count);
  544. FPosition:=FPosition+Count;
  545. end;
  546. procedure TStringStream.WriteString(const AString: string);
  547. begin
  548. Write (PChar(Astring)[0],Length(AString));
  549. end;
  550. {****************************************************************************}
  551. {* TResourceStream *}
  552. {****************************************************************************}
  553. procedure TResourceStream.Initialize(Instance: THandle; Name, ResType: PChar);
  554. begin
  555. end;
  556. constructor TResourceStream.Create(Instance: THandle; const ResName: string; ResType: PChar);
  557. begin
  558. end;
  559. constructor TResourceStream.CreateFromID(Instance: THandle; ResID: Integer; ResType: PChar);
  560. begin
  561. end;
  562. destructor TResourceStream.Destroy;
  563. begin
  564. end;
  565. function TResourceStream.Write(const Buffer; Count: Longint): Longint;
  566. begin
  567. Write:=0;
  568. end;
  569. {
  570. $Log$
  571. Revision 1.7 2002-09-07 15:15:25 peter
  572. * old logs removed and tabs fixed
  573. }