streams.inc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {****************************************************************************}
  11. {* TStream *}
  12. {****************************************************************************}
  13. procedure TStream.ReadNotImplemented;
  14. begin
  15. raise EStreamError.CreateFmt(SStreamNoReading, [ClassName]) at get_caller_addr(get_frame);
  16. end;
  17. procedure TStream.WriteNotImplemented;
  18. begin
  19. raise EStreamError.CreateFmt(SStreamNoWriting, [ClassName]) at get_caller_addr(get_frame);
  20. end;
  21. function TStream.Read(var Buffer; Count: Longint): Longint;
  22. begin
  23. ReadNotImplemented;
  24. Result := 0;
  25. end;
  26. function TStream.Write(const Buffer; Count: Longint): Longint;
  27. begin
  28. WriteNotImplemented;
  29. Result := 0;
  30. end;
  31. function TStream.GetPosition: Int64;
  32. begin
  33. Result:=Seek(0,soCurrent);
  34. end;
  35. procedure TStream.SetPosition(const Pos: Int64);
  36. begin
  37. Seek(pos,soBeginning);
  38. end;
  39. procedure TStream.SetSize64(const NewSize: Int64);
  40. begin
  41. // Required because can't use overloaded functions in properties
  42. SetSize(NewSize);
  43. end;
  44. function TStream.GetSize: Int64;
  45. var
  46. p : int64;
  47. begin
  48. p:=Seek(0,soCurrent);
  49. GetSize:=Seek(0,soEnd);
  50. Seek(p,soBeginning);
  51. end;
  52. procedure TStream.SetSize(NewSize: Longint);
  53. begin
  54. // We do nothing. Pipe streams don't support this
  55. // As wel as possible read-ony streams !!
  56. end;
  57. procedure TStream.SetSize(const NewSize: Int64);
  58. begin
  59. // Backwards compatibility that calls the longint SetSize
  60. if (NewSize<Low(longint)) or
  61. (NewSize>High(longint)) then
  62. raise ERangeError.Create(SRangeError);
  63. SetSize(longint(NewSize));
  64. end;
  65. function TStream.Seek(Offset: Longint; Origin: Word): Longint;
  66. type
  67. TSeek64 = function(const offset:Int64;Origin:TSeekorigin):Int64 of object;
  68. var
  69. CurrSeek,
  70. TStreamSeek : TSeek64;
  71. CurrClass : TClass;
  72. begin
  73. // Redirect calls to 64bit Seek, but we can't call the 64bit Seek
  74. // from TStream, because then we end up in an infinite loop
  75. CurrSeek:=nil;
  76. CurrClass:=Classtype;
  77. while (CurrClass<>nil) and
  78. (CurrClass<>TStream) do
  79. CurrClass:=CurrClass.Classparent;
  80. if CurrClass<>nil then
  81. begin
  82. CurrSeek:[email protected];
  83. TStreamSeek:=@TStream(@CurrClass).Seek;
  84. if TMethod(TStreamSeek).Code=TMethod(CurrSeek).Code then
  85. CurrSeek:=nil;
  86. end;
  87. if CurrSeek<>nil then
  88. Result:=Seek(Int64(offset),TSeekOrigin(origin))
  89. else
  90. raise EStreamError.CreateFmt(SSeekNotImplemented,[ClassName]);
  91. end;
  92. function TStream.Seek(const Offset: Int64; Origin: TSeekorigin): Int64;
  93. begin
  94. // Backwards compatibility that calls the longint Seek
  95. if (Offset<Low(longint)) or
  96. (Offset>High(longint)) then
  97. raise ERangeError.Create(SRangeError);
  98. Result:=Seek(longint(Offset),ord(Origin));
  99. end;
  100. procedure TStream.ReadBuffer(var Buffer; Count: Longint);
  101. begin
  102. if Read(Buffer,Count)<Count then
  103. Raise EReadError.Create(SReadError);
  104. end;
  105. procedure TStream.WriteBuffer(const Buffer; Count: Longint);
  106. begin
  107. if Write(Buffer,Count)<Count then
  108. Raise EWriteError.Create(SWriteError);
  109. end;
  110. function TStream.CopyFrom(Source: TStream; Count: Int64): Int64;
  111. var
  112. Buffer: Pointer;
  113. BufferSize, i: LongInt;
  114. const
  115. MaxSize = $20000;
  116. begin
  117. Result:=0;
  118. if Count=0 then
  119. Source.Position:=0; // This WILL fail for non-seekable streams...
  120. BufferSize:=MaxSize;
  121. if (Count>0) and (Count<BufferSize) then
  122. BufferSize:=Count; // do not allocate more than needed
  123. GetMem(Buffer,BufferSize);
  124. try
  125. if Count=0 then
  126. repeat
  127. i:=Source.Read(buffer^,BufferSize);
  128. if i>0 then
  129. WriteBuffer(buffer^,i);
  130. Inc(Result,i);
  131. until i<BufferSize
  132. else
  133. while Count>0 do
  134. begin
  135. if Count>BufferSize then
  136. i:=BufferSize
  137. else
  138. i:=Count;
  139. Source.ReadBuffer(buffer^,i);
  140. WriteBuffer(buffer^,i);
  141. Dec(count,i);
  142. Inc(Result,i);
  143. end;
  144. finally
  145. FreeMem(Buffer);
  146. end;
  147. end;
  148. function TStream.ReadComponent(Instance: TComponent): TComponent;
  149. var
  150. Reader: TReader;
  151. begin
  152. Reader := TReader.Create(Self, 4096);
  153. try
  154. Result := Reader.ReadRootComponent(Instance);
  155. finally
  156. Reader.Free;
  157. end;
  158. end;
  159. function TStream.ReadComponentRes(Instance: TComponent): TComponent;
  160. begin
  161. ReadResHeader;
  162. Result := ReadComponent(Instance);
  163. end;
  164. procedure TStream.WriteComponent(Instance: TComponent);
  165. begin
  166. WriteDescendent(Instance, nil);
  167. end;
  168. procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
  169. begin
  170. WriteDescendentRes(ResName, Instance, nil);
  171. end;
  172. procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);
  173. var
  174. Driver : TAbstractObjectWriter;
  175. Writer : TWriter;
  176. begin
  177. Driver := TBinaryObjectWriter.Create(Self, 4096);
  178. Try
  179. Writer := TWriter.Create(Driver);
  180. Try
  181. Writer.WriteDescendent(Instance, Ancestor);
  182. Finally
  183. Writer.Destroy;
  184. end;
  185. Finally
  186. Driver.Free;
  187. end;
  188. end;
  189. procedure TStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
  190. var
  191. FixupInfo: Integer;
  192. begin
  193. { Write a resource header }
  194. WriteResourceHeader(ResName, FixupInfo);
  195. { Write the instance itself }
  196. WriteDescendent(Instance, Ancestor);
  197. { Insert the correct resource size into the resource header }
  198. FixupResourceHeader(FixupInfo);
  199. end;
  200. procedure TStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Integer);
  201. var
  202. ResType, Flags : word;
  203. begin
  204. ResType:=NtoLE(word($000A));
  205. Flags:=NtoLE(word($1030));
  206. { Note: This is a Windows 16 bit resource }
  207. { Numeric resource type }
  208. WriteByte($ff);
  209. { Application defined data }
  210. WriteWord(ResType);
  211. { write the name as asciiz }
  212. WriteBuffer(ResName[1],length(ResName));
  213. WriteByte(0);
  214. { Movable, Pure and Discardable }
  215. WriteWord(Flags);
  216. { Placeholder for the resource size }
  217. WriteDWord(0);
  218. { Return current stream position so that the resource size can be
  219. inserted later }
  220. FixupInfo := Position;
  221. end;
  222. procedure TStream.FixupResourceHeader(FixupInfo: Integer);
  223. var
  224. ResSize,TmpResSize : Integer;
  225. begin
  226. ResSize := Position - FixupInfo;
  227. TmpResSize := NtoLE(longword(ResSize));
  228. { Insert the correct resource size into the placeholder written by
  229. WriteResourceHeader }
  230. Position := FixupInfo - 4;
  231. WriteDWord(TmpResSize);
  232. { Seek back to the end of the resource }
  233. Position := FixupInfo + ResSize;
  234. end;
  235. procedure TStream.ReadResHeader;
  236. var
  237. ResType, Flags : word;
  238. begin
  239. try
  240. { Note: This is a Windows 16 bit resource }
  241. { application specific resource ? }
  242. if ReadByte<>$ff then
  243. raise EInvalidImage.Create(SInvalidImage);
  244. ResType:=LEtoN(ReadWord);
  245. if ResType<>$000a then
  246. raise EInvalidImage.Create(SInvalidImage);
  247. { read name }
  248. while ReadByte<>0 do
  249. ;
  250. { check the access specifier }
  251. Flags:=LEtoN(ReadWord);
  252. if Flags<>$1030 then
  253. raise EInvalidImage.Create(SInvalidImage);
  254. { ignore the size }
  255. ReadDWord;
  256. except
  257. on EInvalidImage do
  258. raise;
  259. else
  260. raise EInvalidImage.create(SInvalidImage);
  261. end;
  262. end;
  263. function TStream.ReadByte : Byte;
  264. var
  265. b : Byte;
  266. begin
  267. ReadBuffer(b,1);
  268. ReadByte:=b;
  269. end;
  270. function TStream.ReadWord : Word;
  271. var
  272. w : Word;
  273. begin
  274. ReadBuffer(w,2);
  275. ReadWord:=w;
  276. end;
  277. function TStream.ReadDWord : Cardinal;
  278. var
  279. d : Cardinal;
  280. begin
  281. ReadBuffer(d,4);
  282. ReadDWord:=d;
  283. end;
  284. function TStream.ReadQWord: QWord;
  285. var
  286. q: QWord;
  287. begin
  288. ReadBuffer(q,8);
  289. ReadQWord:=q;
  290. end;
  291. Function TStream.ReadAnsiString : String;
  292. Var
  293. TheSize : Longint;
  294. P : PByte ;
  295. begin
  296. ReadBuffer (TheSize,SizeOf(TheSize));
  297. SetLength(Result,TheSize);
  298. // Illegal typecast if no AnsiStrings defined.
  299. if TheSize>0 then
  300. begin
  301. ReadBuffer (Pointer(Result)^,TheSize);
  302. P:=Pointer(Result)+TheSize;
  303. p^:=0;
  304. end;
  305. end;
  306. Procedure TStream.WriteAnsiString (const S : String);
  307. Var L : Longint;
  308. begin
  309. L:=Length(S);
  310. WriteBuffer (L,SizeOf(L));
  311. WriteBuffer (Pointer(S)^,L);
  312. end;
  313. procedure TStream.WriteByte(b : Byte);
  314. begin
  315. WriteBuffer(b,1);
  316. end;
  317. procedure TStream.WriteWord(w : Word);
  318. begin
  319. WriteBuffer(w,2);
  320. end;
  321. procedure TStream.WriteDWord(d : Cardinal);
  322. begin
  323. WriteBuffer(d,4);
  324. end;
  325. procedure TStream.WriteQWord(q: QWord);
  326. begin
  327. WriteBuffer(q,8);
  328. end;
  329. {****************************************************************************}
  330. {* THandleStream *}
  331. {****************************************************************************}
  332. Constructor THandleStream.Create(AHandle: THandle);
  333. begin
  334. FHandle:=AHandle;
  335. end;
  336. function THandleStream.Read(var Buffer; Count: Longint): Longint;
  337. begin
  338. Result:=FileRead(FHandle,Buffer,Count);
  339. If Result=-1 then Result:=0;
  340. end;
  341. function THandleStream.Write(const Buffer; Count: Longint): Longint;
  342. begin
  343. Result:=FileWrite (FHandle,Buffer,Count);
  344. If Result=-1 then Result:=0;
  345. end;
  346. Procedure THandleStream.SetSize(NewSize: Longint);
  347. begin
  348. SetSize(Int64(NewSize));
  349. end;
  350. Procedure THandleStream.SetSize(const NewSize: Int64);
  351. begin
  352. FileTruncate(FHandle,NewSize);
  353. end;
  354. function THandleStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
  355. begin
  356. Result:=FileSeek(FHandle,Offset,ord(Origin));
  357. end;
  358. {****************************************************************************}
  359. {* TFileStream *}
  360. {****************************************************************************}
  361. constructor TFileStream.Create(const AFileName: string; Mode: Word);
  362. begin
  363. FFileName:=AFileName;
  364. If Mode=fmcreate then
  365. FHandle:=FileCreate(AFileName)
  366. else
  367. FHAndle:=FileOpen(AFileName,Mode);
  368. If (THandle(FHandle)=feInvalidHandle) then
  369. If Mode=fmcreate then
  370. raise EFCreateError.createfmt(SFCreateError,[AFileName])
  371. else
  372. raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
  373. end;
  374. constructor TFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);
  375. begin
  376. FFileName:=AFileName;
  377. If Mode=fmcreate then
  378. FHandle:=FileCreate(AFileName,Rights)
  379. else
  380. FHAndle:=FileOpen(AFileName,Mode);
  381. If (THandle(FHandle)=feInvalidHandle) then
  382. If Mode=fmcreate then
  383. raise EFCreateError.createfmt(SFCreateError,[AFileName])
  384. else
  385. raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
  386. end;
  387. destructor TFileStream.Destroy;
  388. begin
  389. FileClose(FHandle);
  390. end;
  391. {****************************************************************************}
  392. {* TCustomMemoryStream *}
  393. {****************************************************************************}
  394. procedure TCustomMemoryStream.SetPointer(Ptr: Pointer; ASize: PtrInt);
  395. begin
  396. FMemory:=Ptr;
  397. FSize:=ASize;
  398. end;
  399. function TCustomMemoryStream.GetSize: Int64;
  400. begin
  401. Result:=FSize;
  402. end;
  403. function TCustomMemoryStream.Read(var Buffer; Count: LongInt): LongInt;
  404. begin
  405. Result:=0;
  406. If (FSize>0) and (FPosition<Fsize) and (FPosition>=0) then
  407. begin
  408. Result:=FSize-FPosition;
  409. If Result>Count then Result:=Count;
  410. Move ((FMemory+FPosition)^,Buffer,Result);
  411. FPosition:=Fposition+Result;
  412. end;
  413. end;
  414. function TCustomMemoryStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
  415. begin
  416. Case Word(Origin) of
  417. soFromBeginning : FPosition:=Offset;
  418. soFromEnd : FPosition:=FSize+Offset;
  419. soFromCurrent : FPosition:=FPosition+Offset;
  420. end;
  421. Result:=FPosition;
  422. {$IFDEF DEBUG}
  423. if Result < 0 then
  424. raise Exception.Create('TCustomMemoryStream');
  425. {$ENDIF}
  426. end;
  427. procedure TCustomMemoryStream.SaveToStream(Stream: TStream);
  428. begin
  429. if FSize>0 then Stream.WriteBuffer (FMemory^,FSize);
  430. end;
  431. procedure TCustomMemoryStream.SaveToFile(const FileName: string);
  432. Var S : TFileStream;
  433. begin
  434. S:=TFileStream.Create (FileName,fmCreate);
  435. Try
  436. SaveToStream(S);
  437. finally
  438. S.free;
  439. end;
  440. end;
  441. {****************************************************************************}
  442. {* TMemoryStream *}
  443. {****************************************************************************}
  444. Const TMSGrow = 4096; { Use 4k blocks. }
  445. procedure TMemoryStream.SetCapacity(NewCapacity: PtrInt);
  446. begin
  447. SetPointer (Realloc(NewCapacity),Fsize);
  448. FCapacity:=NewCapacity;
  449. end;
  450. function TMemoryStream.Realloc(var NewCapacity: PtrInt): Pointer;
  451. begin
  452. If NewCapacity<0 Then
  453. NewCapacity:=0
  454. else
  455. begin
  456. // if growing, grow at least a quarter
  457. if (NewCapacity>FCapacity) and (NewCapacity < (5*FCapacity) div 4) then
  458. NewCapacity := (5*FCapacity) div 4;
  459. // round off to block size.
  460. NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
  461. end;
  462. // Only now check !
  463. If NewCapacity=FCapacity then
  464. Result:=FMemory
  465. else
  466. begin
  467. Result:=Reallocmem(FMemory,Newcapacity);
  468. If (Result=Nil) and (Newcapacity>0) then
  469. Raise EStreamError.Create(SMemoryStreamError);
  470. end;
  471. end;
  472. destructor TMemoryStream.Destroy;
  473. begin
  474. Clear;
  475. Inherited Destroy;
  476. end;
  477. procedure TMemoryStream.Clear;
  478. begin
  479. FSize:=0;
  480. FPosition:=0;
  481. SetCapacity (0);
  482. end;
  483. procedure TMemoryStream.LoadFromStream(Stream: TStream);
  484. begin
  485. Stream.Position:=0;
  486. SetSize(Stream.Size);
  487. If FSize>0 then Stream.ReadBuffer(FMemory^,FSize);
  488. end;
  489. procedure TMemoryStream.LoadFromFile(const FileName: string);
  490. Var S : TFileStream;
  491. begin
  492. S:=TFileStream.Create (FileName,fmOpenRead or fmShareDenyWrite);
  493. Try
  494. LoadFromStream(S);
  495. finally
  496. S.free;
  497. end;
  498. end;
  499. procedure TMemoryStream.SetSize({$ifdef CPU64}const{$endif CPU64} NewSize: PtrInt);
  500. begin
  501. SetCapacity (NewSize);
  502. FSize:=NewSize;
  503. IF FPosition>FSize then
  504. FPosition:=FSize;
  505. end;
  506. function TMemoryStream.Write(const Buffer; Count: LongInt): LongInt;
  507. Var NewPos : PtrInt;
  508. begin
  509. If (Count=0) or (FPosition<0) then
  510. exit(0);
  511. NewPos:=FPosition+Count;
  512. If NewPos>Fsize then
  513. begin
  514. IF NewPos>FCapacity then
  515. SetCapacity (NewPos);
  516. FSize:=Newpos;
  517. end;
  518. System.Move (Buffer,(FMemory+FPosition)^,Count);
  519. FPosition:=NewPos;
  520. Result:=Count;
  521. end;
  522. {****************************************************************************}
  523. {* TStringStream *}
  524. {****************************************************************************}
  525. procedure TStringStream.SetSize(NewSize: Longint);
  526. begin
  527. Setlength(FDataString,NewSize);
  528. If FPosition>NewSize then FPosition:=NewSize;
  529. end;
  530. constructor TStringStream.Create(const AString: string);
  531. begin
  532. Inherited create;
  533. FDataString:=AString;
  534. end;
  535. function TStringStream.Read(var Buffer; Count: Longint): Longint;
  536. begin
  537. Result:=Length(FDataString)-FPosition;
  538. If Result>Count then Result:=Count;
  539. // This supposes FDataString to be of type AnsiString !
  540. Move (Pchar(FDataString)[FPosition],Buffer,Result);
  541. FPosition:=FPosition+Result;
  542. end;
  543. function TStringStream.ReadString(Count: Longint): string;
  544. Var NewLen : Longint;
  545. begin
  546. NewLen:=Length(FDataString)-FPosition;
  547. If NewLen>Count then NewLen:=Count;
  548. SetLength(Result,NewLen);
  549. Read (Pointer(Result)^,NewLen);
  550. end;
  551. function TStringStream.Seek(Offset: Longint; Origin: Word): Longint;
  552. begin
  553. Case Origin of
  554. soFromBeginning : FPosition:=Offset;
  555. soFromEnd : FPosition:=Length(FDataString)+Offset;
  556. soFromCurrent : FpoSition:=FPosition+Offset;
  557. end;
  558. If FPosition>Length(FDataString) then FPosition:=Length(FDataString);
  559. If FPosition<0 then FPosition:=0;
  560. Result:=FPosition;
  561. end;
  562. function TStringStream.Write(const Buffer; Count: Longint): Longint;
  563. begin
  564. Result:=Count;
  565. SetSize(FPosition+Count);
  566. // This supposes that FDataString is of type AnsiString)
  567. Move (Buffer,PChar(FDataString)[Fposition],Count);
  568. FPosition:=FPosition+Count;
  569. end;
  570. procedure TStringStream.WriteString(const AString: string);
  571. begin
  572. Write (PChar(Astring)[0],Length(AString));
  573. end;
  574. {****************************************************************************}
  575. {* TResourceStream *}
  576. {****************************************************************************}
  577. {$ifdef UNICODE}
  578. procedure TResourceStream.Initialize(Instance: THandle; Name, ResType: PWideChar);
  579. begin
  580. Res:=FindResource(Instance, Name, ResType);
  581. if Res=0 then
  582. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  583. Handle:=LoadResource(Instance,Res);
  584. if Handle=0 then
  585. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  586. SetPointer(LockResource(Handle),SizeOfResource(Instance,Res));
  587. end;
  588. constructor TResourceStream.Create(Instance: THandle; const ResName: WideString; ResType: PWideChar);
  589. begin
  590. inherited create;
  591. Initialize(Instance,PWideChar(ResName),ResType);
  592. end;
  593. constructor TResourceStream.CreateFromID(Instance: THandle; ResID: Integer; ResType: PWideChar);
  594. begin
  595. inherited create;
  596. Initialize(Instance,PWideChar(ResID),ResType);
  597. end;
  598. {$else UNICODE}
  599. procedure TResourceStream.Initialize(Instance: THandle; Name, ResType: PChar);
  600. begin
  601. Res:=FindResource(Instance, Name, ResType);
  602. if Res=0 then
  603. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  604. Handle:=LoadResource(Instance,Res);
  605. if Handle=0 then
  606. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  607. SetPointer(LockResource(Handle),SizeOfResource(Instance,Res));
  608. end;
  609. constructor TResourceStream.Create(Instance: THandle; const ResName: string; ResType: PChar);
  610. begin
  611. inherited create;
  612. Initialize(Instance,pchar(ResName),ResType);
  613. end;
  614. constructor TResourceStream.CreateFromID(Instance: THandle; ResID: Integer; ResType: PChar);
  615. begin
  616. inherited create;
  617. Initialize(Instance,pchar(PtrInt(ResID)),ResType);
  618. end;
  619. {$endif UNICODE}
  620. destructor TResourceStream.Destroy;
  621. begin
  622. UnlockResource(Handle);
  623. FreeResource(Handle);
  624. inherited destroy;
  625. end;
  626. {****************************************************************************}
  627. {* TOwnerStream *}
  628. {****************************************************************************}
  629. constructor TOwnerStream.Create(ASource: TStream);
  630. begin
  631. FSource:=ASource;
  632. end;
  633. destructor TOwnerStream.Destroy;
  634. begin
  635. If FOwner then
  636. FreeAndNil(FSource);
  637. inherited Destroy;
  638. end;
  639. {****************************************************************************}
  640. {* TStreamAdapter *}
  641. {****************************************************************************}
  642. constructor TStreamAdapter.Create(Stream: TStream; Ownership: TStreamOwnership = soReference);
  643. begin
  644. inherited Create;
  645. FStream:=Stream;
  646. FOwnership:=Ownership;
  647. m_bReverted:=false; // mantis 15003
  648. // http://www.tech-archive.net/Archive/German/microsoft.public.de.vc/2005-08/msg00791.html
  649. // http://code.google.com/p/ddab-lib/wiki/TPJIStreamWrapper
  650. end;
  651. destructor TStreamAdapter.Destroy;
  652. begin
  653. if StreamOwnership=soOwned then
  654. FreeAndNil(FStream);
  655. inherited Destroy;
  656. end;
  657. {$warnings off}
  658. function TStreamAdapter.Read(pv: Pointer; cb: DWORD; pcbRead: PDWORD): HResult; stdcall;
  659. var
  660. readcount: Longint;
  661. begin
  662. if m_bReverted then
  663. begin
  664. Result := STG_E_REVERTED;
  665. Exit;
  666. end;
  667. if pv = nil then
  668. begin
  669. Result := STG_E_INVALIDPOINTER;
  670. Exit;
  671. end;
  672. readcount := FStream.Read(pv^, cb);
  673. if pcbRead <> nil then pcbRead^ := readcount;
  674. Result := S_OK;
  675. end;
  676. function TStreamAdapter.Write(pv: Pointer; cb: DWORD; pcbWritten: PDWORD): HResult; stdcall;
  677. var
  678. writecount: Longint;
  679. begin
  680. if m_bReverted then
  681. begin
  682. Result := STG_E_REVERTED;
  683. Exit;
  684. end;
  685. if pv = nil then
  686. begin
  687. Result := STG_E_INVALIDPOINTER;
  688. Exit;
  689. end;
  690. writecount := FStream.Write(pv^, cb);
  691. if pcbWritten <> nil then pcbWritten^ := writecount;
  692. Result := S_OK;
  693. end;
  694. function TStreamAdapter.Seek(dlibMove: Largeint; dwOrigin: Longint; out libNewPosition: Largeint): HResult; stdcall;
  695. var
  696. newpos: Int64;
  697. begin
  698. if m_bReverted then
  699. begin
  700. Result := STG_E_REVERTED;
  701. Exit;
  702. end;
  703. case dwOrigin of
  704. STREAM_SEEK_SET: newpos := FStream.Seek(dlibMove, soBeginning);
  705. STREAM_SEEK_CUR: newpos := FStream.Seek(dlibMove, soCurrent);
  706. STREAM_SEEK_END: newpos := FStream.Seek(dlibMove, soEnd);
  707. else
  708. begin
  709. Result := STG_E_INVALIDFUNCTION;
  710. Exit;
  711. end;
  712. end;
  713. if @libNewPosition <> nil then
  714. libNewPosition := newpos;
  715. Result := S_OK;
  716. end;
  717. function TStreamAdapter.SetSize(libNewSize: Largeint): HResult; stdcall;
  718. begin
  719. if m_bReverted then
  720. begin
  721. Result := STG_E_REVERTED;
  722. Exit;
  723. end;
  724. if libNewSize<0 then
  725. begin
  726. Result := STG_E_INVALIDFUNCTION;
  727. Exit;
  728. end;
  729. try
  730. FStream.Size := libNewSize;
  731. Result := S_OK;
  732. except
  733. // TODO: return different error value according to exception like STG_E_MEDIUMFULL
  734. Result := E_FAIL;
  735. end;
  736. end;
  737. function TStreamAdapter.CopyTo(stm: IStream; cb: Largeint; out cbRead: Largeint; out cbWritten: Largeint): HResult; stdcall;
  738. var
  739. sz: dword;
  740. buffer : array[0..1023] of byte;
  741. begin
  742. if m_bReverted then
  743. begin
  744. Result := STG_E_REVERTED;
  745. Exit;
  746. end;
  747. // the method is similar to TStream.CopyFrom => use CopyFrom implementation
  748. cbWritten := 0;
  749. cbRead := 0;
  750. while cb > 0 do
  751. begin
  752. if (cb > sizeof(buffer)) then
  753. sz := sizeof(Buffer)
  754. else
  755. sz := cb;
  756. sz := FStream.Read(buffer, sz);
  757. inc(cbRead, sz);
  758. stm.Write(@buffer[0], sz, @sz);
  759. inc(cbWritten, sz);
  760. if sz = 0 then
  761. begin
  762. Result := E_FAIL;
  763. Exit;
  764. end;
  765. dec(cb, sz);
  766. end;
  767. Result := S_OK;
  768. end;
  769. function TStreamAdapter.Commit(grfCommitFlags: Longint): HResult; stdcall;
  770. begin
  771. if m_bReverted then
  772. Result := STG_E_REVERTED
  773. else
  774. Result := S_OK;
  775. end;
  776. function TStreamAdapter.Revert: HResult; stdcall;
  777. begin
  778. m_bReverted := True;
  779. Result := S_OK;
  780. end;
  781. function TStreamAdapter.LockRegion(libOffset: Largeint; cb: Largeint; dwLockType: Longint): HResult; stdcall;
  782. begin
  783. Result := STG_E_INVALIDFUNCTION;
  784. end;
  785. function TStreamAdapter.UnlockRegion(libOffset: Largeint; cb: Largeint; dwLockType: Longint): HResult; stdcall;
  786. begin
  787. Result := STG_E_INVALIDFUNCTION;
  788. end;
  789. function TStreamAdapter.Stat(out statstg: TStatStg; grfStatFlag: Longint): HResult; stdcall;
  790. begin
  791. if m_bReverted then
  792. begin
  793. Result := STG_E_REVERTED;
  794. Exit;
  795. end;
  796. if grfStatFlag in [STATFLAG_DEFAULT,STATFLAG_NOOPEN,STATFLAG_NONAME] then
  797. begin
  798. if @statstg <> nil then
  799. begin
  800. fillchar(statstg, sizeof(TStatStg),#0);
  801. { //TODO handle pwcsName
  802. if grfStatFlag = STATFLAG_DEFAULT then
  803. runerror(217) //Result :={$ifdef windows} STG_E_INVALIDFLAG{$else}E_INVALID_FLAG{$endif}
  804. }
  805. statstg.dwType := STGTY_STREAM;
  806. statstg.cbSize := FStream.Size;
  807. statstg.grfLocksSupported := LOCK_WRITE;
  808. end;
  809. Result := S_OK;
  810. end else
  811. Result := STG_E_INVALIDFLAG
  812. end;
  813. function TStreamAdapter.Clone(out stm: IStream): HResult; stdcall;
  814. begin
  815. if m_bReverted then
  816. begin
  817. Result := STG_E_REVERTED;
  818. Exit;
  819. end;
  820. // don't raise an exception here return error value that function is not implemented
  821. // to implement this we need a clone method for TStream class
  822. Result := STG_E_UNIMPLEMENTEDFUNCTION;
  823. end;
  824. constructor TProxyStream.Create(const Stream: IStream);
  825. begin
  826. FStream := Stream;
  827. end;
  828. function TProxyStream.Read(var Buffer; Count: Longint): Longint;
  829. begin
  830. Check(FStream.Read(@Buffer, Count, @Result));
  831. end;
  832. function TProxyStream.Seek(Offset: Longint; Origin: Word): Longint;
  833. var
  834. Pos: Int64;
  835. begin
  836. Check(FStream.Seek(Offset, Origin, Pos));
  837. Result := Pos;
  838. end;
  839. function TProxyStream.Write(const Buffer; Count: Longint): Longint;
  840. begin
  841. Check(FStream.Write(@Buffer, Count, @Result));
  842. end;
  843. function TProxyStream.GetIStream: IStream;
  844. begin
  845. Result := FStream;
  846. end;
  847. procedure TProxyStream.Check(err:integer);
  848. var e : EInOutError;
  849. begin
  850. e:= EInOutError.Create('Proxystream.Check');
  851. e.Errorcode:=err;
  852. raise e;
  853. end;
  854. {$warnings on}