streams.inc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332
  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), get_caller_frame(get_frame);
  16. end;
  17. procedure TStream.WriteNotImplemented;
  18. begin
  19. raise EStreamError.CreateFmt(SStreamNoWriting, [ClassName]) at get_caller_addr(get_frame), get_caller_frame(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. procedure TStream.Discard(const Count: Int64);
  93. const
  94. CSmallSize =255;
  95. CLargeMaxBuffer =32*1024; // 32 KiB
  96. var
  97. Buffer: array[1..CSmallSize] of Byte;
  98. begin
  99. if Count=0 then
  100. Exit;
  101. if Count<=SizeOf(Buffer) then
  102. ReadBuffer(Buffer,Count)
  103. else
  104. DiscardLarge(Count,CLargeMaxBuffer);
  105. end;
  106. procedure TStream.DiscardLarge(Count: int64; const MaxBufferSize: Longint);
  107. var
  108. Buffer: array of Byte;
  109. begin
  110. if Count=0 then
  111. Exit;
  112. if Count>MaxBufferSize then
  113. SetLength(Buffer,MaxBufferSize)
  114. else
  115. SetLength(Buffer,Count);
  116. while (Count>=Length(Buffer)) do
  117. begin
  118. ReadBuffer(Buffer[0],Length(Buffer));
  119. Dec(Count,Length(Buffer));
  120. end;
  121. if Count>0 then
  122. ReadBuffer(Buffer[0],Count);
  123. end;
  124. procedure TStream.InvalidSeek;
  125. begin
  126. raise EStreamError.CreateFmt(SStreamInvalidSeek, [ClassName]) at get_caller_addr(get_frame), get_caller_frame(get_frame);
  127. end;
  128. procedure TStream.FakeSeekForward(Offset: Int64; const Origin: TSeekOrigin; const Pos: Int64);
  129. begin
  130. if Origin=soBeginning then
  131. Dec(Offset,Pos);
  132. if (Offset<0) or (Origin=soEnd) then
  133. InvalidSeek;
  134. if Offset>0 then
  135. Discard(Offset);
  136. end;
  137. function TStream.Seek(const Offset: Int64; Origin: TSeekorigin): Int64;
  138. begin
  139. // Backwards compatibility that calls the longint Seek
  140. if (Offset<Low(longint)) or
  141. (Offset>High(longint)) then
  142. raise ERangeError.Create(SRangeError);
  143. Result:=Seek(longint(Offset),ord(Origin));
  144. end;
  145. procedure TStream.ReadBuffer(var Buffer; Count: Longint);
  146. Var
  147. r,t : longint;
  148. begin
  149. t:=0;
  150. repeat
  151. r:=Read(PByte(@Buffer)[t],Count-t);
  152. inc(t,r);
  153. until (t=Count) or (r<=0);
  154. if (t<Count) then
  155. Raise EReadError.Create(SReadError);
  156. end;
  157. procedure TStream.WriteBuffer(const Buffer; Count: Longint);
  158. var
  159. r,t : Longint;
  160. begin
  161. T:=0;
  162. Repeat
  163. r:=Write(PByte(@Buffer)[t],Count-t);
  164. inc(t,r);
  165. Until (t=count) or (r<=0);
  166. if (t<Count) then
  167. Raise EWriteError.Create(SWriteError);
  168. end;
  169. function TStream.CopyFrom(Source: TStream; Count: Int64): Int64;
  170. var
  171. Buffer: Pointer;
  172. BufferSize, i: LongInt;
  173. const
  174. MaxSize = $20000;
  175. begin
  176. Result:=0;
  177. if Count=0 then
  178. Source.Position:=0; // This WILL fail for non-seekable streams...
  179. BufferSize:=MaxSize;
  180. if (Count>0) and (Count<BufferSize) then
  181. BufferSize:=Count; // do not allocate more than needed
  182. GetMem(Buffer,BufferSize);
  183. try
  184. if Count=0 then
  185. repeat
  186. i:=Source.Read(buffer^,BufferSize);
  187. if i>0 then
  188. WriteBuffer(buffer^,i);
  189. Inc(Result,i);
  190. until i<BufferSize
  191. else
  192. while Count>0 do
  193. begin
  194. if Count>BufferSize then
  195. i:=BufferSize
  196. else
  197. i:=Count;
  198. Source.ReadBuffer(buffer^,i);
  199. WriteBuffer(buffer^,i);
  200. Dec(count,i);
  201. Inc(Result,i);
  202. end;
  203. finally
  204. FreeMem(Buffer);
  205. end;
  206. end;
  207. function TStream.ReadComponent(Instance: TComponent): TComponent;
  208. var
  209. Reader: TReader;
  210. begin
  211. Reader := TReader.Create(Self, 4096);
  212. try
  213. Result := Reader.ReadRootComponent(Instance);
  214. finally
  215. Reader.Free;
  216. end;
  217. end;
  218. function TStream.ReadComponentRes(Instance: TComponent): TComponent;
  219. begin
  220. ReadResHeader;
  221. Result := ReadComponent(Instance);
  222. end;
  223. procedure TStream.WriteComponent(Instance: TComponent);
  224. begin
  225. WriteDescendent(Instance, nil);
  226. end;
  227. procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
  228. begin
  229. WriteDescendentRes(ResName, Instance, nil);
  230. end;
  231. procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);
  232. var
  233. Driver : TAbstractObjectWriter;
  234. Writer : TWriter;
  235. begin
  236. Driver := TBinaryObjectWriter.Create(Self, 4096);
  237. Try
  238. Writer := TWriter.Create(Driver);
  239. Try
  240. Writer.WriteDescendent(Instance, Ancestor);
  241. Finally
  242. Writer.Destroy;
  243. end;
  244. Finally
  245. Driver.Free;
  246. end;
  247. end;
  248. procedure TStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
  249. var
  250. FixupInfo: Longint;
  251. begin
  252. { Write a resource header }
  253. WriteResourceHeader(ResName, FixupInfo);
  254. { Write the instance itself }
  255. WriteDescendent(Instance, Ancestor);
  256. { Insert the correct resource size into the resource header }
  257. FixupResourceHeader(FixupInfo);
  258. end;
  259. procedure TStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Longint);
  260. var
  261. ResType, Flags : word;
  262. begin
  263. ResType:=NtoLE(word($000A));
  264. Flags:=NtoLE(word($1030));
  265. { Note: This is a Windows 16 bit resource }
  266. { Numeric resource type }
  267. WriteByte($ff);
  268. { Application defined data }
  269. WriteWord(ResType);
  270. { write the name as asciiz }
  271. WriteBuffer(ResName[1],length(ResName));
  272. WriteByte(0);
  273. { Movable, Pure and Discardable }
  274. WriteWord(Flags);
  275. { Placeholder for the resource size }
  276. WriteDWord(0);
  277. { Return current stream position so that the resource size can be
  278. inserted later }
  279. FixupInfo := Position;
  280. end;
  281. procedure TStream.FixupResourceHeader(FixupInfo: Longint);
  282. var
  283. ResSize,TmpResSize : Longint;
  284. begin
  285. ResSize := Position - FixupInfo;
  286. TmpResSize := NtoLE(longword(ResSize));
  287. { Insert the correct resource size into the placeholder written by
  288. WriteResourceHeader }
  289. Position := FixupInfo - 4;
  290. WriteDWord(TmpResSize);
  291. { Seek back to the end of the resource }
  292. Position := FixupInfo + ResSize;
  293. end;
  294. procedure TStream.ReadResHeader;
  295. var
  296. ResType, Flags : word;
  297. begin
  298. try
  299. { Note: This is a Windows 16 bit resource }
  300. { application specific resource ? }
  301. if ReadByte<>$ff then
  302. raise EInvalidImage.Create(SInvalidImage);
  303. ResType:=LEtoN(ReadWord);
  304. if ResType<>$000a then
  305. raise EInvalidImage.Create(SInvalidImage);
  306. { read name }
  307. while ReadByte<>0 do
  308. ;
  309. { check the access specifier }
  310. Flags:=LEtoN(ReadWord);
  311. if Flags<>$1030 then
  312. raise EInvalidImage.Create(SInvalidImage);
  313. { ignore the size }
  314. ReadDWord;
  315. except
  316. on EInvalidImage do
  317. raise;
  318. else
  319. raise EInvalidImage.create(SInvalidImage);
  320. end;
  321. end;
  322. function TStream.ReadByte : Byte;
  323. var
  324. b : Byte;
  325. begin
  326. ReadBuffer(b,1);
  327. ReadByte:=b;
  328. end;
  329. function TStream.ReadWord : Word;
  330. var
  331. w : Word;
  332. begin
  333. ReadBuffer(w,2);
  334. ReadWord:=w;
  335. end;
  336. function TStream.ReadDWord : Cardinal;
  337. var
  338. d : Cardinal;
  339. begin
  340. ReadBuffer(d,4);
  341. ReadDWord:=d;
  342. end;
  343. function TStream.ReadQWord: QWord;
  344. var
  345. q: QWord;
  346. begin
  347. ReadBuffer(q,8);
  348. ReadQWord:=q;
  349. end;
  350. Function TStream.ReadAnsiString : String;
  351. Var
  352. TheSize : Longint;
  353. P : PByte ;
  354. begin
  355. ReadBuffer (TheSize,SizeOf(TheSize));
  356. SetLength(Result,TheSize);
  357. // Illegal typecast if no AnsiStrings defined.
  358. if TheSize>0 then
  359. begin
  360. ReadBuffer (Pointer(Result)^,TheSize);
  361. P:=Pointer(Result)+TheSize;
  362. p^:=0;
  363. end;
  364. end;
  365. Procedure TStream.WriteAnsiString (const S : String);
  366. Var L : Longint;
  367. begin
  368. L:=Length(S);
  369. WriteBuffer (L,SizeOf(L));
  370. WriteBuffer (Pointer(S)^,L);
  371. end;
  372. procedure TStream.WriteByte(b : Byte);
  373. begin
  374. WriteBuffer(b,1);
  375. end;
  376. procedure TStream.WriteWord(w : Word);
  377. begin
  378. WriteBuffer(w,2);
  379. end;
  380. procedure TStream.WriteDWord(d : Cardinal);
  381. begin
  382. WriteBuffer(d,4);
  383. end;
  384. procedure TStream.WriteQWord(q: QWord);
  385. begin
  386. WriteBuffer(q,8);
  387. end;
  388. {****************************************************************************}
  389. {* THandleStream *}
  390. {****************************************************************************}
  391. Constructor THandleStream.Create(AHandle: THandle);
  392. begin
  393. Inherited Create;
  394. FHandle:=AHandle;
  395. end;
  396. function THandleStream.Read(var Buffer; Count: Longint): Longint;
  397. begin
  398. Result:=FileRead(FHandle,Buffer,Count);
  399. If Result=-1 then Result:=0;
  400. end;
  401. function THandleStream.Write(const Buffer; Count: Longint): Longint;
  402. begin
  403. Result:=FileWrite (FHandle,Buffer,Count);
  404. If Result=-1 then Result:=0;
  405. end;
  406. Procedure THandleStream.SetSize(NewSize: Longint);
  407. begin
  408. SetSize(Int64(NewSize));
  409. end;
  410. Procedure THandleStream.SetSize(const NewSize: Int64);
  411. begin
  412. // We set the position afterwards, because the size can also be larger.
  413. if not FileTruncate(FHandle,NewSize) then
  414. Raise EInOutError.Create(SStreamSetSize);
  415. Position:=NewSize;
  416. end;
  417. function THandleStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
  418. begin
  419. Result:=FileSeek(FHandle,Offset,ord(Origin));
  420. end;
  421. {****************************************************************************}
  422. {* TFileStream *}
  423. {****************************************************************************}
  424. constructor TFileStream.Create(const AFileName: string; Mode: Word);
  425. begin
  426. Create(AFileName,Mode,438);
  427. end;
  428. constructor TFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);
  429. begin
  430. FFileName:=AFileName;
  431. If (Mode and fmCreate) > 0 then
  432. FHandle:=FileCreate(AFileName,Mode,Rights)
  433. else
  434. FHAndle:=FileOpen(AFileName,Mode);
  435. If (THandle(FHandle)=feInvalidHandle) then
  436. If Mode=fmcreate then
  437. begin
  438. {$if declared(GetLastOSError)}
  439. raise EFCreateError.createfmt(SFCreateErrorEx,[AFileName, SysErrorMessage(GetLastOSError)])
  440. {$else}
  441. raise EFCreateError.createfmt(SFCreateError,[AFileName])
  442. {$endif}
  443. end
  444. else
  445. begin
  446. {$if declared(GetLastOSError)}
  447. raise EFOpenError.Createfmt(SFOpenErrorEx,[AFilename, SysErrorMessage(GetLastOSError)]);
  448. {$else}
  449. raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
  450. {$endif}
  451. end;
  452. end;
  453. destructor TFileStream.Destroy;
  454. begin
  455. FileClose(FHandle);
  456. end;
  457. {****************************************************************************}
  458. {* TCustomMemoryStream *}
  459. {****************************************************************************}
  460. procedure TCustomMemoryStream.SetPointer(Ptr: Pointer; ASize: PtrInt);
  461. begin
  462. FMemory:=Ptr;
  463. FSize:=ASize;
  464. end;
  465. function TCustomMemoryStream.GetSize: Int64;
  466. begin
  467. Result:=FSize;
  468. end;
  469. function TCustomMemoryStream.GetPosition: Int64;
  470. begin
  471. Result:=FPosition;
  472. end;
  473. function TCustomMemoryStream.Read(var Buffer; Count: LongInt): LongInt;
  474. begin
  475. Result:=0;
  476. If (FSize>0) and (FPosition<Fsize) and (FPosition>=0) then
  477. begin
  478. Result:=Count;
  479. If (Result>(FSize-FPosition)) then
  480. Result:=(FSize-FPosition);
  481. Move ((FMemory+FPosition)^,Buffer,Result);
  482. FPosition:=Fposition+Result;
  483. end;
  484. end;
  485. function TCustomMemoryStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
  486. begin
  487. Case Word(Origin) of
  488. soFromBeginning : FPosition:=Offset;
  489. soFromEnd : FPosition:=FSize+Offset;
  490. soFromCurrent : FPosition:=FPosition+Offset;
  491. end;
  492. Result:=FPosition;
  493. {$IFDEF DEBUG}
  494. if Result < 0 then
  495. raise Exception.Create('TCustomMemoryStream');
  496. {$ENDIF}
  497. end;
  498. procedure TCustomMemoryStream.SaveToStream(Stream: TStream);
  499. begin
  500. if FSize>0 then Stream.WriteBuffer (FMemory^,FSize);
  501. end;
  502. procedure TCustomMemoryStream.SaveToFile(const FileName: string);
  503. Var S : TFileStream;
  504. begin
  505. S:=TFileStream.Create (FileName,fmCreate);
  506. Try
  507. SaveToStream(S);
  508. finally
  509. S.free;
  510. end;
  511. end;
  512. {****************************************************************************}
  513. {* TMemoryStream *}
  514. {****************************************************************************}
  515. Const TMSGrow = 4096; { Use 4k blocks. }
  516. procedure TMemoryStream.SetCapacity(NewCapacity: PtrInt);
  517. begin
  518. SetPointer (Realloc(NewCapacity),Fsize);
  519. FCapacity:=NewCapacity;
  520. end;
  521. function TMemoryStream.Realloc(var NewCapacity: PtrInt): Pointer;
  522. Var
  523. GC : PtrInt;
  524. begin
  525. If NewCapacity<0 Then
  526. NewCapacity:=0
  527. else
  528. begin
  529. GC:=FCapacity + (FCapacity div 4);
  530. // if growing, grow at least a quarter
  531. if (NewCapacity>FCapacity) and (NewCapacity < GC) then
  532. NewCapacity := GC;
  533. // round off to block size.
  534. NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
  535. end;
  536. // Only now check !
  537. If NewCapacity=FCapacity then
  538. Result:=FMemory
  539. else
  540. begin
  541. Result:=Reallocmem(FMemory,Newcapacity);
  542. If (Result=Nil) and (Newcapacity>0) then
  543. Raise EStreamError.Create(SMemoryStreamError);
  544. end;
  545. end;
  546. destructor TMemoryStream.Destroy;
  547. begin
  548. Clear;
  549. Inherited Destroy;
  550. end;
  551. procedure TMemoryStream.Clear;
  552. begin
  553. FSize:=0;
  554. FPosition:=0;
  555. SetCapacity (0);
  556. end;
  557. procedure TMemoryStream.LoadFromStream(Stream: TStream);
  558. begin
  559. Stream.Position:=0;
  560. SetSize(Stream.Size);
  561. If FSize>0 then Stream.ReadBuffer(FMemory^,FSize);
  562. end;
  563. procedure TMemoryStream.LoadFromFile(const FileName: string);
  564. Var S : TFileStream;
  565. begin
  566. S:=TFileStream.Create (FileName,fmOpenRead or fmShareDenyWrite);
  567. Try
  568. LoadFromStream(S);
  569. finally
  570. S.free;
  571. end;
  572. end;
  573. procedure TMemoryStream.SetSize({$ifdef CPU64}const NewSize: Int64{$else}NewSize: LongInt{$endif});
  574. begin
  575. SetCapacity (NewSize);
  576. FSize:=NewSize;
  577. IF FPosition>FSize then
  578. FPosition:=FSize;
  579. end;
  580. function TMemoryStream.Write(const Buffer; Count: LongInt): LongInt;
  581. Var NewPos : PtrInt;
  582. begin
  583. If (Count=0) or (FPosition<0) then
  584. exit(0);
  585. NewPos:=FPosition+Count;
  586. If NewPos>Fsize then
  587. begin
  588. IF NewPos>FCapacity then
  589. SetCapacity (NewPos);
  590. FSize:=Newpos;
  591. end;
  592. System.Move (Buffer,(FMemory+FPosition)^,Count);
  593. FPosition:=NewPos;
  594. Result:=Count;
  595. end;
  596. {****************************************************************************}
  597. {* TBytesStream *}
  598. {****************************************************************************}
  599. constructor TBytesStream.Create(const ABytes: TBytes);
  600. begin
  601. inherited Create;
  602. FBytes:=ABytes;
  603. SetPointer(Pointer(FBytes),Length(FBytes));
  604. FCapacity:=Length(FBytes);
  605. end;
  606. function TBytesStream.Realloc(var NewCapacity: PtrInt): Pointer;
  607. begin
  608. // adapt TMemoryStream code to use with dynamic array
  609. if NewCapacity<0 Then
  610. NewCapacity:=0
  611. else
  612. begin
  613. if (NewCapacity>Capacity) and (NewCapacity < (5*Capacity) div 4) then
  614. NewCapacity := (5*Capacity) div 4;
  615. NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
  616. end;
  617. if NewCapacity=Capacity then
  618. Result:=Pointer(FBytes)
  619. else
  620. begin
  621. SetLength(FBytes,Newcapacity);
  622. Result:=Pointer(FBytes);
  623. if (Result=nil) and (Newcapacity>0) then
  624. raise EStreamError.Create(SMemoryStreamError);
  625. end;
  626. end;
  627. {****************************************************************************}
  628. {* TStringStream *}
  629. {****************************************************************************}
  630. function TStringStream.GetDataString: string;
  631. begin
  632. Result:=FEncoding.GetAnsiString(Bytes,0,Size);
  633. end;
  634. function TStringStream.GetUnicodeDataString: UnicodeString;
  635. begin
  636. Result:=FEncoding.GetString(Bytes, 0, Size);
  637. end;
  638. constructor TStringStream.Create(const AString: string = '');
  639. begin
  640. Create(AString,TEncoding.Default, False);
  641. end;
  642. constructor TStringStream.Create(const ABytes: TBytes);
  643. begin
  644. inherited Create(ABytes);
  645. FEncoding:=TEncoding.Default;
  646. FOwnsEncoding:=False;
  647. end;
  648. constructor TStringStream.CreateRaw(const AString: RawByteString);
  649. var
  650. CP: TSystemCodePage;
  651. begin
  652. CP:=StringCodePage(AString);
  653. if (CP=CP_ACP) or (CP=TEncoding.Default.CodePage) then
  654. begin
  655. FEncoding:=TEncoding.Default;
  656. FOwnsEncoding:=False;
  657. end
  658. else
  659. begin
  660. FEncoding:=TEncoding.GetEncoding(CP);
  661. FOwnsEncoding:=True;
  662. end;
  663. inherited Create(BytesOf(AString));
  664. end;
  665. constructor TStringStream.Create(const AString: string; AEncoding: TEncoding; AOwnsEncoding: Boolean);
  666. begin
  667. FOwnsEncoding:=AOwnsEncoding and not TEncoding.IsStandardEncoding(AEncoding);
  668. FEncoding:=AEncoding;
  669. Inherited Create(AEncoding.GetAnsiBytes(AString));
  670. end;
  671. constructor TStringStream.Create(const AString: string; ACodePage: Integer);
  672. begin
  673. Create(AString,TEncoding.GetEncoding(ACodePage),true);
  674. end;
  675. constructor TStringStream.Create(const AString: UnicodeString);
  676. begin
  677. Create(AString,TEncoding.Unicode,false);
  678. end;
  679. constructor TStringStream.Create(const AString: UnicodeString; AEncoding: TEncoding; AOwnsEncoding: Boolean);
  680. begin
  681. FOwnsEncoding:=AOwnsEncoding and not TEncoding.IsStandardEncoding(AEncoding);
  682. FEncoding:=AEncoding;
  683. Inherited Create(AEncoding.GetBytes(AString));
  684. end;
  685. constructor TStringStream.Create(const AString: UnicodeString; ACodePage: Integer);
  686. begin
  687. Create(AString,TEncoding.GetEncoding(ACodePage),true);
  688. end;
  689. destructor TStringStream.Destroy;
  690. begin
  691. If FOwnsEncoding then
  692. FreeAndNil(FEncoding);
  693. inherited Destroy;
  694. end;
  695. function TStringStream.ReadString(Count: Longint): string;
  696. begin
  697. Result:=ReadAnsiString(Count);
  698. end;
  699. function TStringStream.ReadUnicodeString(Count: Longint): UnicodeString;
  700. Var
  701. NewLen,SLen : Longint;
  702. begin
  703. NewLen:=Size-FPosition;
  704. If NewLen>Count then NewLen:=Count;
  705. Result:=FEncoding.GetString(FBytes,FPosition,NewLen);
  706. end;
  707. procedure TStringStream.WriteString(const AString: string);
  708. begin
  709. WriteAnsiString(AString);
  710. end;
  711. procedure TStringStream.WriteUnicodeString(const AString: UnicodeString);
  712. Var
  713. B: TBytes;
  714. begin
  715. B:=FEncoding.GetBytes(AString);
  716. if Length(B)>0 then
  717. WriteBuffer(B[0],Length(B));
  718. end;
  719. function TStringStream.ReadAnsiString(Count: Longint): AnsiString;
  720. Var
  721. NewLen : Longint;
  722. begin
  723. NewLen:=Size-FPosition;
  724. If NewLen>Count then NewLen:=Count;
  725. Result:=FEncoding.GetAnsiString(FBytes,FPosition,NewLen);
  726. Inc(FPosition,NewLen);
  727. end;
  728. procedure TStringStream.WriteAnsiString(const AString: AnsiString);
  729. Var
  730. B: TBytes;
  731. begin
  732. B:=FEncoding.GetAnsiBytes(AString);
  733. if Length(B)>0 then
  734. WriteBuffer(B[0],Length(B));
  735. end;
  736. {****************************************************************************}
  737. {* TRawByteStringStream *}
  738. {****************************************************************************}
  739. constructor TRawByteStringStream.Create(const aData: RawByteString);
  740. begin
  741. Inherited Create;
  742. If Length(aData)>0 then
  743. begin
  744. WriteBuffer(aData[1],Length(aData));
  745. Position:=0;
  746. end;
  747. end;
  748. function TRawByteStringStream.DataString: RawByteString;
  749. begin
  750. Result:='';
  751. SetLength(Result,Size);
  752. if Size>0 then
  753. Move(Memory^, Result[1], Size);
  754. end;
  755. function TRawByteStringStream.ReadString(Count: Longint): RawByteString;
  756. Var
  757. NewLen : Longint;
  758. begin
  759. NewLen:=Size-FPosition;
  760. If NewLen>Count then NewLen:=Count;
  761. Result:='';
  762. if NewLen>0 then
  763. begin
  764. SetLength(Result, NewLen);
  765. Move(FBytes[FPosition],Result[1],NewLen);
  766. inc(FPosition,Newlen);
  767. end;
  768. end;
  769. procedure TRawByteStringStream.WriteString(const AString: RawByteString);
  770. begin
  771. if Length(AString)>0 then
  772. WriteBuffer(AString[1],Length(AString));
  773. end;
  774. {****************************************************************************}
  775. {* TResourceStream *}
  776. {****************************************************************************}
  777. {$ifdef FPC_OS_UNICODE}
  778. procedure TResourceStream.Initialize(Instance: TFPResourceHMODULE; Name, ResType: PWideChar; NameIsID: Boolean);
  779. begin
  780. Res:=FindResource(Instance, Name, ResType);
  781. if Res=0 then
  782. if NameIsID then
  783. raise EResNotFound.CreateFmt(SResNotFound,[IntToStr(PtrInt(Name))])
  784. else
  785. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  786. Handle:=LoadResource(Instance,Res);
  787. if Handle=0 then
  788. if NameIsID then
  789. raise EResNotFound.CreateFmt(SResNotFound,[IntToStr(PtrInt(Name))])
  790. else
  791. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  792. SetPointer(LockResource(Handle),SizeOfResource(Instance,Res));
  793. end;
  794. constructor TResourceStream.Create(Instance: TFPResourceHMODULE; const ResName: WideString; ResType: PWideChar);
  795. begin
  796. inherited create;
  797. Initialize(Instance,PWideChar(ResName),ResType,False);
  798. end;
  799. constructor TResourceStream.CreateFromID(Instance: TFPResourceHMODULE; ResID: Integer; ResType: PWideChar);
  800. begin
  801. inherited create;
  802. Initialize(Instance,PWideChar(ResID),ResType,True);
  803. end;
  804. {$else FPC_OS_UNICODE}
  805. procedure TResourceStream.Initialize(Instance: TFPResourceHMODULE; Name, ResType: PChar; NameIsID: Boolean);
  806. begin
  807. Res:=FindResource(Instance, Name, ResType);
  808. if Res=0 then
  809. if NameIsID then
  810. raise EResNotFound.CreateFmt(SResNotFound,[IntToStr(PtrInt(Name))])
  811. else
  812. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  813. Handle:=LoadResource(Instance,Res);
  814. if Handle=0 then
  815. if NameIsID then
  816. raise EResNotFound.CreateFmt(SResNotFound,[IntToStr(PtrInt(Name))])
  817. else
  818. raise EResNotFound.CreateFmt(SResNotFound,[Name]);
  819. SetPointer(LockResource(Handle),SizeOfResource(Instance,Res));
  820. end;
  821. constructor TResourceStream.Create(Instance: TFPResourceHMODULE; const ResName: string; ResType: PChar);
  822. begin
  823. inherited create;
  824. Initialize(Instance,pchar(ResName),ResType,False);
  825. end;
  826. constructor TResourceStream.CreateFromID(Instance: TFPResourceHMODULE; ResID: Integer; ResType: PChar);
  827. begin
  828. inherited create;
  829. Initialize(Instance,pchar(PtrInt(ResID)),ResType,True);
  830. end;
  831. {$endif FPC_OS_UNICODE}
  832. destructor TResourceStream.Destroy;
  833. begin
  834. UnlockResource(Handle);
  835. FreeResource(Handle);
  836. inherited destroy;
  837. end;
  838. {****************************************************************************}
  839. {* TOwnerStream *}
  840. {****************************************************************************}
  841. constructor TOwnerStream.Create(ASource: TStream);
  842. begin
  843. FSource:=ASource;
  844. end;
  845. destructor TOwnerStream.Destroy;
  846. begin
  847. If FOwner then
  848. FreeAndNil(FSource);
  849. inherited Destroy;
  850. end;
  851. {****************************************************************************}
  852. {* TStreamAdapter *}
  853. {****************************************************************************}
  854. constructor TStreamAdapter.Create(Stream: TStream; Ownership: TStreamOwnership = soReference);
  855. begin
  856. inherited Create;
  857. FStream:=Stream;
  858. FOwnership:=Ownership;
  859. m_bReverted:=false; // mantis 15003
  860. // http://www.tech-archive.net/Archive/German/microsoft.public.de.vc/2005-08/msg00791.html
  861. // http://code.google.com/p/ddab-lib/wiki/TPJIStreamWrapper
  862. end;
  863. destructor TStreamAdapter.Destroy;
  864. begin
  865. if StreamOwnership=soOwned then
  866. FreeAndNil(FStream);
  867. inherited Destroy;
  868. end;
  869. {$warnings off}
  870. function TStreamAdapter.Read(pv: Pointer; cb: DWORD; pcbRead: PDWORD): HResult; stdcall;
  871. var
  872. readcount: Longint;
  873. begin
  874. if m_bReverted then
  875. begin
  876. Result := STG_E_REVERTED;
  877. Exit;
  878. end;
  879. if pv = nil then
  880. begin
  881. Result := STG_E_INVALIDPOINTER;
  882. Exit;
  883. end;
  884. readcount := FStream.Read(pv^, cb);
  885. if pcbRead <> nil then pcbRead^ := readcount;
  886. Result := S_OK;
  887. end;
  888. function TStreamAdapter.Write(pv: Pointer; cb: DWORD; pcbWritten: PDWORD): HResult; stdcall;
  889. var
  890. writecount: Longint;
  891. begin
  892. if m_bReverted then
  893. begin
  894. Result := STG_E_REVERTED;
  895. Exit;
  896. end;
  897. if pv = nil then
  898. begin
  899. Result := STG_E_INVALIDPOINTER;
  900. Exit;
  901. end;
  902. writecount := FStream.Write(pv^, cb);
  903. if pcbWritten <> nil then pcbWritten^ := writecount;
  904. Result := S_OK;
  905. end;
  906. function TStreamAdapter.Seek(dlibMove: LargeInt; dwOrigin: DWORD; out libNewPosition: LargeUint): HResult; stdcall;
  907. var
  908. newpos: QWord;
  909. begin
  910. if m_bReverted then
  911. begin
  912. Result := STG_E_REVERTED;
  913. Exit;
  914. end;
  915. case dwOrigin of
  916. STREAM_SEEK_SET: newpos := FStream.Seek(dlibMove, soBeginning);
  917. STREAM_SEEK_CUR: newpos := FStream.Seek(dlibMove, soCurrent);
  918. STREAM_SEEK_END: newpos := FStream.Seek(dlibMove, soEnd);
  919. else
  920. begin
  921. Result := STG_E_INVALIDFUNCTION;
  922. Exit;
  923. end;
  924. end;
  925. if @libNewPosition <> nil then
  926. libNewPosition := newpos;
  927. Result := S_OK;
  928. end;
  929. function TStreamAdapter.SetSize(libNewSize: LargeUint): HResult; stdcall;
  930. begin
  931. if m_bReverted then
  932. begin
  933. Result := STG_E_REVERTED;
  934. Exit;
  935. end;
  936. if libNewSize<0 then
  937. begin
  938. Result := STG_E_INVALIDFUNCTION;
  939. Exit;
  940. end;
  941. try
  942. FStream.Size := libNewSize;
  943. Result := S_OK;
  944. except
  945. // TODO: return different error value according to exception like STG_E_MEDIUMFULL
  946. Result := E_FAIL;
  947. end;
  948. end;
  949. function TStreamAdapter.CopyTo(stm: IStream; cb: LargeUint; out cbRead: LargeUint; out cbWritten: Largeuint): HResult; stdcall;
  950. var
  951. sz: dword;
  952. buffer : array[0..1023] of byte;
  953. begin
  954. if m_bReverted then
  955. begin
  956. Result := STG_E_REVERTED;
  957. Exit;
  958. end;
  959. // the method is similar to TStream.CopyFrom => use CopyFrom implementation
  960. cbWritten := 0;
  961. cbRead := 0;
  962. while cb > 0 do
  963. begin
  964. if (cb > sizeof(buffer)) then
  965. sz := sizeof(Buffer)
  966. else
  967. sz := cb;
  968. sz := FStream.Read(buffer, sz);
  969. inc(cbRead, sz);
  970. stm.Write(@buffer[0], sz, @sz);
  971. inc(cbWritten, sz);
  972. if sz = 0 then
  973. begin
  974. Result := E_FAIL;
  975. Exit;
  976. end;
  977. dec(cb, sz);
  978. end;
  979. Result := S_OK;
  980. end;
  981. function TStreamAdapter.Commit(grfCommitFlags: DWORD): HResult; stdcall;
  982. begin
  983. if m_bReverted then
  984. Result := STG_E_REVERTED
  985. else
  986. Result := S_OK;
  987. end;
  988. function TStreamAdapter.Revert: HResult; stdcall;
  989. begin
  990. m_bReverted := True;
  991. Result := S_OK;
  992. end;
  993. function TStreamAdapter.LockRegion(libOffset: LargeUint; cb: LargeUint; dwLockType: DWORD): HResult; stdcall;
  994. begin
  995. Result := STG_E_INVALIDFUNCTION;
  996. end;
  997. function TStreamAdapter.UnlockRegion(libOffset: LargeUint; cb: LargeUint; dwLockType: DWORD): HResult; stdcall;
  998. begin
  999. Result := STG_E_INVALIDFUNCTION;
  1000. end;
  1001. function TStreamAdapter.Stat(out statstg: TStatStg; grfStatFlag: DWORD): HResult; stdcall;
  1002. begin
  1003. if m_bReverted then
  1004. begin
  1005. Result := STG_E_REVERTED;
  1006. Exit;
  1007. end;
  1008. if grfStatFlag in [STATFLAG_DEFAULT,STATFLAG_NOOPEN,STATFLAG_NONAME] then
  1009. begin
  1010. if @statstg <> nil then
  1011. begin
  1012. fillchar(statstg, sizeof(TStatStg),#0);
  1013. { //TODO handle pwcsName
  1014. if grfStatFlag = STATFLAG_DEFAULT then
  1015. runerror(217) //Result :={$ifdef windows} STG_E_INVALIDFLAG{$else}E_INVALID_FLAG{$endif}
  1016. }
  1017. statstg.dwType := STGTY_STREAM;
  1018. statstg.cbSize := FStream.Size;
  1019. statstg.grfLocksSupported := LOCK_WRITE;
  1020. end;
  1021. Result := S_OK;
  1022. end else
  1023. Result := STG_E_INVALIDFLAG
  1024. end;
  1025. function TStreamAdapter.Clone(out stm: IStream): HResult; stdcall;
  1026. begin
  1027. if m_bReverted then
  1028. begin
  1029. Result := STG_E_REVERTED;
  1030. Exit;
  1031. end;
  1032. // don't raise an exception here return error value that function is not implemented
  1033. // to implement this we need a clone method for TStream class
  1034. Result := STG_E_UNIMPLEMENTEDFUNCTION;
  1035. end;
  1036. constructor TProxyStream.Create(const Stream: IStream);
  1037. begin
  1038. FStream := Stream;
  1039. end;
  1040. function TProxyStream.Read(var Buffer; Count: Longint): Longint;
  1041. begin
  1042. Check(FStream.Read(@Buffer, Count, @Result));
  1043. end;
  1044. function TProxyStream.Seek(const Offset: int64; Origin: TSeekOrigin): int64;
  1045. begin
  1046. Check(FStream.Seek(Offset, ord(Origin), QWord(result)));
  1047. end;
  1048. function TProxyStream.Write(const Buffer; Count: Longint): Longint;
  1049. begin
  1050. Check(FStream.Write(@Buffer, Count, @Result));
  1051. end;
  1052. function TProxyStream.GetIStream: IStream;
  1053. begin
  1054. Result := FStream;
  1055. end;
  1056. procedure TProxyStream.Check(err:integer);
  1057. var e : EInOutError;
  1058. begin
  1059. e:= EInOutError.Create('Proxystream.Check');
  1060. e.Errorcode:=err;
  1061. raise e;
  1062. end;
  1063. {$warnings on}