You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

957 lines
37 KiB

  1. unit uutlStreamHelper;
  2. { Package: Utils
  3. Prefix: utl - UTiLs
  4. Beschreibung: diese Unit enthält Klassen zum lesen und schreiben von Werten in einen Stream
  5. TutlStreamReader - Wrapper für beliebige Streams, handelt Datentypen
  6. TutlStreamWriter - Wrapper für beliebige Streams, handelt Datentypen }
  7. {$mode objfpc}{$H+}
  8. interface
  9. uses
  10. SysUtils, Classes, syncobjs,
  11. uutlGenerics;
  12. type
  13. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  14. TutlFourCC = string[4];
  15. TutlStreamUtility = class
  16. private type
  17. TPositionStack = specialize TutlStack<Int64>;
  18. private
  19. fStream: TStream;
  20. fOwnsStream: Boolean;
  21. fPositions: TPositionStack;
  22. public
  23. property Stream: TStream read FStream;
  24. procedure Push;
  25. procedure Pop;
  26. procedure Drop;
  27. constructor Create(const aBaseStream: TStream; const aOwnsStream: Boolean);
  28. destructor Destroy; override;
  29. end;
  30. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  31. TutlStreamReader = class(TutlStreamUtility)
  32. protected
  33. function ReadBuffer(var Buffer; Size: int64): int64;
  34. public
  35. function ReadFourCC: TutlFourCC; inline;
  36. function CheckFourCC (constref Correct: TutlFourCC): boolean; inline;
  37. function ReadByte: Byte; inline;
  38. function ReadWord: Word; inline;
  39. function ReadCardinal: Cardinal; inline;
  40. function ReadInteger: Integer; inline;
  41. function ReadInt64: Int64; inline;
  42. function ReadSingle: Single; inline;
  43. function ReadDouble: Double; inline;
  44. function ReadAnsiString: AnsiString; inline;
  45. function ReadLine: AnsiString;
  46. function IsEOF: boolean; inline;
  47. end;
  48. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  49. TutlStreamWriter = class(TutlStreamUtility)
  50. protected
  51. procedure WriteBuffer(var Data; Size: int64);
  52. public
  53. procedure WriteFourCC (FCC: TutlFourCC); inline;
  54. procedure WriteByte (A: Byte); inline;
  55. procedure WriteWord (A: Word); inline;
  56. procedure WriteCardinal (A: Cardinal); inline;
  57. procedure WriteInteger (A: Integer); inline;
  58. procedure WriteInt64 (A: Int64); inline;
  59. procedure WriteSingle (A: Single); inline;
  60. procedure WriteDouble (A: Double); inline;
  61. procedure WriteAnsiString (A: AnsiString); inline;
  62. procedure WriteAnsiBytes (A: AnsiString); inline;
  63. procedure WriteLine (A: AnsiString); inline;
  64. end;
  65. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  66. TutlStreamHelper = class
  67. private
  68. class function ReadBuffer (constref aStream: TStream; var Buffer; Size: int64): int64;
  69. class procedure WriteBuffer (constref aStream: TStream; var Data; Size: int64);
  70. public
  71. class function ReadFourCC (constref aStream: TStream): TutlFourCC; inline;
  72. class function CheckFourCC (constref aStream: TStream; Correct: TutlFourCC): boolean; inline;
  73. class function ReadByte (constref aStream: TStream): Byte; inline;
  74. class function ReadWord (constref aStream: TStream): Word; inline;
  75. class function ReadCardinal (constref aStream: TStream): Cardinal; inline;
  76. class function ReadInteger (constref aStream: TStream): Integer; inline;
  77. class function ReadInt64 (constref aStream: TStream): Int64; inline;
  78. class function ReadSingle (constref aStream: TStream): Single; inline;
  79. class function ReadDouble (constref aStream: TStream): Double; inline;
  80. class function ReadAnsiString (constref aStream: TStream): AnsiString; inline;
  81. class function ReadLine (constref aStream: TStream): AnsiString;
  82. class function IsEOF (constref aStream: TStream): boolean; inline;
  83. public
  84. class procedure WriteFourCC (constref aStream: TStream; FCC: TutlFourCC); inline;
  85. class procedure WriteByte (constref aStream: TStream; A: Byte); inline;
  86. class procedure WriteWord (constref aStream: TStream; A: Word); inline;
  87. class procedure WriteCardinal (constref aStream: TStream; A: Cardinal); inline;
  88. class procedure WriteInteger (constref aStream: TStream; A: Integer); inline;
  89. class procedure WriteInt64 (constref aStream: TStream; A: Int64); inline;
  90. class procedure WriteSingle (constref aStream: TStream; A: Single); inline;
  91. class procedure WriteDouble (constref aStream: TStream; A: Double); inline;
  92. class procedure WriteAnsiString (constref aStream: TStream; A: AnsiString); inline;
  93. class procedure WriteAnsiBytes (constref aStream: TStream; A: AnsiString); inline;
  94. class procedure WriteLine (constref aStream: TStream; A: AnsiString); inline;
  95. end;
  96. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  97. TutlPagedBufferStream = class(TOwnerStream)
  98. public const
  99. DEFAULT_BUFLEN = 4096*16;
  100. private
  101. FVirtualSize, FVirtualPosition: Int64;
  102. FBuffer: TBytes;
  103. FBufferStart: Int64;
  104. FBufferModified: boolean;
  105. protected
  106. function GetSize: Int64; override;
  107. procedure SetSize(const NewSize: Int64); override;
  108. procedure ReMapBuffer;
  109. procedure FlushBuffer;
  110. public
  111. function Read(var Buffer; Count: Integer): Integer; override;
  112. function Write(const Buffer; Count: Integer): Integer; override;
  113. function Seek(Offset: Integer; Origin: Word): Integer; override;
  114. constructor Create(const BaseStream: TStream; const BufferSize: Cardinal = DEFAULT_BUFLEN; const aOwnsStream: Boolean = false);
  115. destructor Destroy; override;
  116. end;
  117. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  118. TutlFIFOStream = class(TStream)
  119. private const
  120. MAX_PAGE_SIZE = 4096;
  121. private type
  122. PPage = ^TPage;
  123. TPage = record
  124. Next: PPage;
  125. Data: packed array[0..MAX_PAGE_SIZE-1] of byte;
  126. end;
  127. private
  128. fLockFree: boolean;
  129. fPageFirst, fPageLast: PPage;
  130. fReadPtr, fWritePtr: Cardinal;
  131. fTotalSize: Int64;
  132. fDataLock: TCriticalSection;
  133. protected
  134. function GetSize: Int64; override;
  135. public
  136. property LockFree: boolean read fLockFree;
  137. function Read (var Buffer; Count: Longint): Longint; override;
  138. function Reserve (var Buffer; Count: Longint): Longint;
  139. function Discard (Count: Longint): Longint;
  140. function Write (const Buffer; Count: Longint): Longint; override;
  141. function Seek (const {%H-}Offset: Int64; {%H-}Origin: TSeekOrigin): Int64; override; overload;
  142. procedure BeginOperation;
  143. procedure EndOperation;
  144. procedure Clear;
  145. constructor Create(const aLockFree: boolean = false);
  146. destructor Destroy; override;
  147. end;
  148. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  149. TutlBase64Decoder = class(TStringStream)
  150. public const
  151. CODE64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  152. PADDING_CHARACTER = '=';
  153. public
  154. function Read(var Buffer; Count: Longint): Longint; override;
  155. function Decode(const aOutput: TStream): Boolean;
  156. constructor Create;
  157. end;
  158. implementation
  159. uses
  160. RtlConsts, Math;
  161. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  162. //TutlStreamUtility/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  163. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  164. procedure TutlStreamUtility.Pop;
  165. begin
  166. FStream.Position := fPositions.Pop;
  167. end;
  168. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  169. procedure TutlStreamUtility.Drop;
  170. begin
  171. fPositions.Pop;
  172. end;
  173. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  174. procedure TutlStreamUtility.Push;
  175. begin
  176. FPositions.Push(FStream.Position);
  177. end;
  178. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  179. constructor TutlStreamUtility.Create(const aBaseStream: TStream; const aOwnsStream: Boolean);
  180. begin
  181. inherited Create;
  182. fStream := aBaseStream;
  183. fOwnsStream := aOwnsStream;
  184. fPositions := TPositionStack.Create(true);
  185. end;
  186. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  187. destructor TutlStreamUtility.Destroy;
  188. begin
  189. if FOwnsStream
  190. then FreeAndNil(fStream)
  191. else fStream:= nil;
  192. FreeAndNil(FPositions);
  193. inherited;
  194. end;
  195. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  196. //TutlStreamReader//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  198. function TutlStreamReader.ReadBuffer(var Buffer; Size: int64): int64;
  199. begin
  200. if (FStream.Position + Size > FStream.Size) then
  201. raise EInvalidOperation.Create('stream is to small');
  202. Result:= FStream.Read(Buffer, Size);
  203. end;
  204. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  205. function TutlStreamReader.ReadFourCC: TutlFourCC;
  206. begin
  207. SetLength(Result, 4);
  208. ReadBuffer(Result[1], 4);
  209. end;
  210. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  211. function TutlStreamReader.CheckFourCC(constref Correct: TutlFourCC): boolean;
  212. begin
  213. Result := ReadFourCC=Correct;
  214. end;
  215. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  216. function TutlStreamReader.ReadByte: Byte;
  217. begin
  218. ReadBuffer(Result{%H-}, Sizeof(Result));
  219. end;
  220. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  221. function TutlStreamReader.ReadWord: Word;
  222. begin
  223. ReadBuffer(Result{%H-}, Sizeof(Result));
  224. end;
  225. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  226. function TutlStreamReader.ReadCardinal: Cardinal;
  227. begin
  228. ReadBuffer(Result{%H-}, Sizeof(Result));
  229. end;
  230. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  231. function TutlStreamReader.ReadInteger: Integer;
  232. begin
  233. ReadBuffer(Result{%H-}, Sizeof(Result));
  234. end;
  235. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  236. function TutlStreamReader.ReadInt64: Int64;
  237. begin
  238. ReadBuffer(Result{%H-}, Sizeof(Result));
  239. end;
  240. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  241. function TutlStreamReader.ReadSingle: Single;
  242. begin
  243. ReadBuffer(Result{%H-}, Sizeof(Result));
  244. end;
  245. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  246. function TutlStreamReader.ReadDouble: Double;
  247. begin
  248. ReadBuffer(Result{%H-}, Sizeof(Result));
  249. end;
  250. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  251. function TutlStreamReader.ReadAnsiString: AnsiString;
  252. begin
  253. SetLength(Result, ReadCardinal);
  254. ReadBuffer(Result[1], Length(Result));
  255. end;
  256. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  257. function TutlStreamReader.ReadLine: AnsiString;
  258. begin
  259. result := TutlStreamHelper.ReadLine(fStream);
  260. end;
  261. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  262. function TutlStreamReader.IsEOF: boolean;
  263. begin
  264. Result := FStream.Position = FStream.Size;
  265. end;
  266. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  267. //TutlStreamWriter//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  268. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  269. procedure TutlStreamWriter.WriteBuffer(var Data; Size: int64);
  270. begin
  271. FStream.Write(Data, Size);
  272. end;
  273. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  274. procedure TutlStreamWriter.WriteFourCC(FCC: TutlFourCC);
  275. begin
  276. WriteBuffer(FCC[1], 4);
  277. end;
  278. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  279. procedure TutlStreamWriter.WriteByte(A: Byte);
  280. begin
  281. WriteBuffer(A, SizeOf(a));
  282. end;
  283. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  284. procedure TutlStreamWriter.WriteWord(A: Word);
  285. begin
  286. WriteBuffer(A, SizeOf(a));
  287. end;
  288. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  289. procedure TutlStreamWriter.WriteCardinal(A: Cardinal);
  290. begin
  291. WriteBuffer(A, SizeOf(a));
  292. end;
  293. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  294. procedure TutlStreamWriter.WriteInteger(A: Integer);
  295. begin
  296. WriteBuffer(A, SizeOf(a));
  297. end;
  298. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  299. procedure TutlStreamWriter.WriteInt64(A: Int64);
  300. begin
  301. WriteBuffer(A, SizeOf(a));
  302. end;
  303. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  304. procedure TutlStreamWriter.WriteSingle(A: Single);
  305. begin
  306. WriteBuffer(A, SizeOf(a));
  307. end;
  308. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  309. procedure TutlStreamWriter.WriteDouble(A: Double);
  310. begin
  311. WriteBuffer(A, SizeOf(a));
  312. end;
  313. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  314. procedure TutlStreamWriter.WriteAnsiString(A: AnsiString);
  315. begin
  316. WriteCardinal(Length(A));
  317. WriteBuffer(A[1], Length(a));
  318. end;
  319. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  320. procedure TutlStreamWriter.WriteAnsiBytes(A: AnsiString);
  321. begin
  322. WriteBuffer(A[1], Length(A));
  323. end;
  324. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  325. procedure TutlStreamWriter.WriteLine(A: AnsiString);
  326. begin
  327. WriteAnsiBytes(A + sLineBreak);
  328. end;
  329. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  330. //TutlStreamHelper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  331. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  332. class function TutlStreamHelper.ReadBuffer(constref aStream: TStream; var Buffer; Size: int64): int64;
  333. begin
  334. if (aStream.Position + Size > aStream.Size) then
  335. raise EInvalidOperation.Create('stream is to small');
  336. Result := aStream.Read(Buffer, Size);
  337. end;
  338. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  339. class procedure TutlStreamHelper.WriteBuffer(constref aStream: TStream; var Data; Size: int64);
  340. begin
  341. aStream.Write(Data, Size);
  342. end;
  343. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  344. class function TutlStreamHelper.ReadFourCC(constref aStream: TStream): TutlFourCC;
  345. begin
  346. SetLength(Result, 4);
  347. ReadBuffer(aStream, Result[1], 4);
  348. end;
  349. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  350. class function TutlStreamHelper.CheckFourCC(constref aStream: TStream; Correct: TutlFourCC): boolean;
  351. begin
  352. result := (ReadFourCC(aStream) = Correct);
  353. end;
  354. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  355. class function TutlStreamHelper.ReadByte(constref aStream: TStream): Byte;
  356. begin
  357. ReadBuffer(aStream, result{%H-}, SizeOf(result));
  358. end;
  359. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  360. class function TutlStreamHelper.ReadWord(constref aStream: TStream): Word;
  361. begin
  362. ReadBuffer(aStream, result{%H-}, SizeOf(result));
  363. end;
  364. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  365. class function TutlStreamHelper.ReadCardinal(constref aStream: TStream): Cardinal;
  366. begin
  367. ReadBuffer(aStream, result{%H-}, SizeOf(result));
  368. end;
  369. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  370. class function TutlStreamHelper.ReadInteger(constref aStream: TStream): Integer;
  371. begin
  372. ReadBuffer(aStream, result{%H-}, SizeOf(result));
  373. end;
  374. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  375. class function TutlStreamHelper.ReadInt64(constref aStream: TStream): Int64;
  376. begin
  377. ReadBuffer(aStream, result{%H-}, SizeOf(result));
  378. end;
  379. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  380. class function TutlStreamHelper.ReadSingle(constref aStream: TStream): Single;
  381. begin
  382. ReadBuffer(aStream, result{%H-}, SizeOf(result));
  383. end;
  384. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  385. class function TutlStreamHelper.ReadDouble(constref aStream: TStream): Double;
  386. begin
  387. ReadBuffer(aStream, result{%H-}, SizeOf(result));
  388. end;
  389. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  390. class function TutlStreamHelper.ReadAnsiString(constref aStream: TStream): AnsiString;
  391. begin
  392. SetLength(Result, ReadCardinal(aStream));
  393. ReadBuffer(aStream, Result[1], Length(Result));
  394. end;
  395. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  396. class function TutlStreamHelper.ReadLine(constref aStream: TStream): AnsiString;
  397. const
  398. READ_LENGTH = 80;
  399. var
  400. rp, rl: integer;
  401. cp: PAnsiChar;
  402. bpos: Int64;
  403. r: integer;
  404. EOF: Boolean;
  405. procedure ReadSome;
  406. begin
  407. SetLength(Result, rl + READ_LENGTH);
  408. r:= aStream.Read(Result[rl + 1], READ_LENGTH);
  409. inc(rl, r);
  410. EOF:= r <> READ_LENGTH;
  411. cp:= @Result[rp];
  412. end;
  413. begin
  414. Result := '';
  415. rl := 0;
  416. bpos := aStream.Position;
  417. repeat
  418. rp := rl + 1;
  419. ReadSome;
  420. while rp <= rl do begin
  421. if cp^ in [#10, #13] then begin
  422. inc(bpos, rp);
  423. // never a second char after #10
  424. if cp^ = #13 then begin
  425. if (rp = rl) and not EOF then begin
  426. ReadSome;
  427. end;
  428. if (rp <= rl) then begin
  429. inc(cp);
  430. if cp^ = #10 then
  431. inc(bpos);
  432. end;
  433. end;
  434. aStream.Position := bpos;
  435. SetLength(Result, rp-1);
  436. Exit;
  437. end;
  438. inc(cp);
  439. inc(rp);
  440. end;
  441. until EOF;
  442. SetLength(Result, rl);
  443. end;
  444. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  445. class function TutlStreamHelper.IsEOF(constref aStream: TStream): boolean;
  446. begin
  447. Result := aStream.Position = aStream.Size;
  448. end;
  449. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  450. class procedure TutlStreamHelper.WriteFourCC(constref aStream: TStream; FCC: TutlFourCC);
  451. begin
  452. WriteBuffer(aStream, FCC[1], 4);
  453. end;
  454. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  455. class procedure TutlStreamHelper.WriteByte(constref aStream: TStream; A: Byte);
  456. begin
  457. WriteBuffer(aStream, a, SizeOf(a));
  458. end;
  459. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  460. class procedure TutlStreamHelper.WriteWord(constref aStream: TStream; A: Word);
  461. begin
  462. WriteBuffer(aStream, a, SizeOf(a));
  463. end;
  464. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  465. class procedure TutlStreamHelper.WriteCardinal(constref aStream: TStream; A: Cardinal);
  466. begin
  467. WriteBuffer(aStream, a, SizeOf(a));
  468. end;
  469. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  470. class procedure TutlStreamHelper.WriteInteger(constref aStream: TStream; A: Integer);
  471. begin
  472. WriteBuffer(aStream, a, SizeOf(a));
  473. end;
  474. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  475. class procedure TutlStreamHelper.WriteInt64(constref aStream: TStream; A: Int64);
  476. begin
  477. WriteBuffer(aStream, a, SizeOf(a));
  478. end;
  479. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  480. class procedure TutlStreamHelper.WriteSingle(constref aStream: TStream; A: Single);
  481. begin
  482. WriteBuffer(aStream, a, SizeOf(a));
  483. end;
  484. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  485. class procedure TutlStreamHelper.WriteDouble(constref aStream: TStream; A: Double);
  486. begin
  487. WriteBuffer(aStream, a, SizeOf(a));
  488. end;
  489. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  490. class procedure TutlStreamHelper.WriteAnsiString(constref aStream: TStream; A: AnsiString);
  491. begin
  492. WriteCardinal(aStream, Length(A));
  493. WriteBuffer(aStream, A[1], Length(a));
  494. end;
  495. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  496. class procedure TutlStreamHelper.WriteAnsiBytes(constref aStream: TStream; A: AnsiString);
  497. begin
  498. WriteBuffer(aStream, A[1], Length(a));
  499. end;
  500. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  501. class procedure TutlStreamHelper.WriteLine(constref aStream: TStream; A: AnsiString);
  502. begin
  503. WriteAnsiBytes(aStream, A + sLineBreak);
  504. end;
  505. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  506. //TutlPagedBufferStream/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  507. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  508. function TutlPagedBufferStream.GetSize: Int64;
  509. begin
  510. Result:= FVirtualSize;
  511. end;
  512. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  513. procedure TutlPagedBufferStream.SetSize(const NewSize: Int64);
  514. begin
  515. FVirtualSize:= NewSize;
  516. Source.Size:= NewSize;
  517. if Position > FVirtualSize then
  518. Position:= FVirtualSize;
  519. end;
  520. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  521. procedure TutlPagedBufferStream.ReMapBuffer;
  522. var
  523. newbs: Int64;
  524. inbuf: Int64;
  525. begin
  526. // Welches Buffer-Segment wird gesucht?
  527. newbs:= (FVirtualPosition div Length(FBuffer)) * Length(FBuffer);
  528. // ist das das aktuelle?
  529. if FBufferStart <> newbs then begin
  530. FlushBuffer;
  531. // Segment holen
  532. Source.Position:= newbs;
  533. inbuf:= Min(Length(FBuffer), FVirtualSize - newbs);
  534. Source.ReadBuffer(FBuffer[0], inbuf);
  535. FBufferStart:= newbs;
  536. FBufferModified:= false;
  537. end;
  538. end;
  539. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  540. procedure TutlPagedBufferStream.FlushBuffer;
  541. var
  542. towrite: Int64;
  543. begin
  544. if not FBufferModified then
  545. // Nothing to do
  546. Exit;
  547. Source.Position:= FBufferStart;
  548. towrite:= Min(Length(FBuffer), FVirtualSize - FBufferStart);
  549. Source.WriteBuffer(FBuffer[0], towrite);
  550. end;
  551. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  552. function TutlPagedBufferStream.Read(var Buffer; Count: Integer): Integer;
  553. var
  554. br, c: Int64;
  555. bp: Pointer;
  556. begin
  557. br:= 0;
  558. bp:= @Buffer;
  559. while (br < Count) and (FVirtualPosition<FVirtualSize) do begin
  560. ReMapBuffer;
  561. // Wie viel Daten daraus brauchen wir bzw. können wir kriegen?
  562. c:= Min(Min(Count - br, Length(FBuffer) - (FVirtualPosition-FBufferStart)), FVirtualSize - FVirtualPosition);
  563. // das rausholen und buffer weiterschieben
  564. Move(FBuffer[FVirtualPosition-FBufferStart], bp^, c);
  565. Inc(Bp, c);
  566. Inc(br, c);
  567. Inc(FVirtualPosition, c);
  568. end;
  569. Result:= br;
  570. end;
  571. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  572. function TutlPagedBufferStream.Write(const Buffer; Count: Integer): Integer;
  573. var
  574. bw, c: Int64;
  575. bp: Pointer;
  576. begin
  577. bw:= 0;
  578. bp:= @Buffer;
  579. while (bw < Count) do begin
  580. ReMapBuffer;
  581. // Wie viel Daten können wir schreiben?
  582. c:= Min(Count - bw, Length(FBuffer) - (FVirtualPosition-FBufferStart));
  583. // das schreiben und buffer weiterschieben
  584. Move(bp^, FBuffer[FVirtualPosition-FBufferStart], c);
  585. Inc(Bp, c);
  586. Inc(bw, c);
  587. Inc(FVirtualPosition, c);
  588. if FVirtualPosition > FVirtualSize then
  589. FVirtualSize:= FVirtualPosition;
  590. end;
  591. if bw > 0 then
  592. FBufferModified:= true;
  593. Result:= bw;
  594. end;
  595. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  596. function TutlPagedBufferStream.Seek(Offset: Integer; Origin: Word): Integer;
  597. begin
  598. case Origin of
  599. soFromBeginning: FVirtualPosition := Offset;
  600. soFromCurrent: Inc(FVirtualPosition, Offset);
  601. soFromEnd: FVirtualPosition := Size + Offset;
  602. end;
  603. ReMapBuffer;
  604. Result := FVirtualPosition;
  605. end;
  606. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  607. constructor TutlPagedBufferStream.Create(
  608. const BaseStream: TStream;
  609. const BufferSize: Cardinal;
  610. const aOwnsStream: Boolean);
  611. begin
  612. inherited Create(BaseStream);
  613. SourceOwner:= aOwnsStream;
  614. SetLength(FBuffer, BufferSize);
  615. FVirtualPosition:= 0;
  616. FVirtualSize:= Source.Size;
  617. FBufferStart:= -1;
  618. ReMapBuffer;
  619. end;
  620. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  621. destructor TutlPagedBufferStream.Destroy;
  622. begin
  623. FlushBuffer;
  624. SetLength(FBuffer, 0);
  625. inherited;
  626. end;
  627. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  628. //TutlFIFOStream////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  629. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  630. function TutlFIFOStream.GetSize: Int64;
  631. begin
  632. Result:= fTotalSize;
  633. end;
  634. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  635. function TutlFIFOStream.Read(var Buffer; Count: Longint): Longint;
  636. begin
  637. BeginOperation;
  638. try
  639. Result:= Reserve(Buffer, Count);
  640. Discard(Result);
  641. finally
  642. EndOperation;
  643. end;
  644. end;
  645. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  646. function TutlFIFOStream.Reserve(var Buffer; Count: Longint): Longint;
  647. var
  648. pbuf: PByteArray;
  649. mx: LongInt;
  650. rp: Int64;
  651. p: PPage;
  652. begin
  653. BeginOperation;
  654. try
  655. pbuf:= @Buffer;
  656. Result:= 0;
  657. rp:= fReadPtr;
  658. p:= fPageFirst;
  659. while Count > 0 do begin
  660. mx:= MAX_PAGE_SIZE - rp;
  661. if mx > Count then mx:= Count;
  662. if (p=fPageLast) and (mx > fWritePtr-rp) then mx:= fWritePtr-rp;
  663. if mx=0 then exit;
  664. Move(p^.Data[rp], pbuf^[Result], mx);
  665. inc(rp, mx);
  666. inc(Result, mx);
  667. Dec(Count, mx);
  668. if rp = MAX_PAGE_SIZE then begin
  669. p:= p^.Next;
  670. rp:= 0;
  671. end;
  672. end;
  673. finally
  674. EndOperation;
  675. end;
  676. end;
  677. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  678. function TutlFIFOStream.Discard(Count: Longint): Longint;
  679. var
  680. mx: LongInt;
  681. n: PPage;
  682. begin
  683. BeginOperation;
  684. try
  685. Result:= 0;
  686. while Count > 0 do begin
  687. mx:= MAX_PAGE_SIZE - fReadPtr;
  688. if mx > Count then mx:= Count;
  689. if (fPageFirst=fPageLast) and (mx > fWritePtr-fReadPtr) then mx:= fWritePtr-fReadPtr;
  690. if mx=0 then exit;
  691. inc(fReadPtr, mx);
  692. inc(Result, mx);
  693. dec(Count, mx);
  694. dec(fTotalSize, mx);
  695. if fReadPtr=MAX_PAGE_SIZE then begin
  696. n:= fPageFirst^.Next;
  697. if Assigned(n) then begin
  698. Dispose(fPageFirst);
  699. fPageFirst:= n;
  700. fReadPtr:= 0;
  701. end;// else kann nicht passieren, das wird mit (mx > fWritePtr-fReadPtr) und (mx=0) schon bedient
  702. end;
  703. end;
  704. finally
  705. EndOperation;
  706. end;
  707. end;
  708. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  709. function TutlFIFOStream.Write(const Buffer; Count: Longint): Longint;
  710. var
  711. mx: LongInt;
  712. pbuf: PByteArray;
  713. begin
  714. BeginOperation;
  715. try
  716. pbuf:= @Buffer;
  717. Result:= 0;
  718. while Count > 0 do begin
  719. mx:= MAX_PAGE_SIZE - fWritePtr;
  720. if mx > Count then mx:= Count;
  721. Move(pbuf^[Result], fPageLast^.Data[fWritePtr], mx);
  722. inc(fWritePtr, mx);
  723. inc(fTotalSize, mx);
  724. dec(Count, mx);
  725. inc(Result, mx);
  726. if fWritePtr = MAX_PAGE_SIZE then begin
  727. New(fPageLast^.Next);
  728. fPageLast:= fPageLast^.Next;
  729. fPageLast^.Next:= nil;
  730. fWritePtr:= 0;
  731. end;
  732. end;
  733. finally
  734. EndOperation;
  735. end;
  736. end;
  737. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  738. function TutlFIFOStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
  739. begin
  740. Result:= 0;
  741. raise EStreamError.CreateFmt(SStreamInvalidSeek,[ClassName]);
  742. end;
  743. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  744. procedure TutlFIFOStream.BeginOperation;
  745. begin
  746. if not fLockFree then
  747. fDataLock.Acquire;
  748. end;
  749. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  750. procedure TutlFIFOStream.EndOperation;
  751. begin
  752. if not fLockFree then
  753. fDataLock.Release;
  754. end;
  755. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  756. procedure TutlFIFOStream.Clear;
  757. var
  758. p: PPage;
  759. begin
  760. BeginOperation;
  761. try
  762. while fPageFirst<>fPageLast do begin
  763. p:= fPageFirst;
  764. fPageFirst:= fPageFirst^.Next;
  765. Dispose(p);
  766. end;
  767. fTotalSize:= 0;
  768. fReadPtr:= 0;
  769. fWritePtr:= 0;
  770. finally
  771. EndOperation;
  772. end;
  773. end;
  774. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  775. constructor TutlFIFOStream.Create(const aLockFree: boolean);
  776. begin
  777. inherited Create;
  778. fDataLock:= TCriticalSection.Create;
  779. fTotalSize:= 0;
  780. New(fPageFirst);
  781. fPageFirst^.Next:= nil;
  782. fPageLast:= fPageFirst;
  783. fReadPtr:= 0;
  784. fWritePtr:= 0;
  785. fLockFree:= aLockFree;
  786. end;
  787. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  788. destructor TutlFIFOStream.Destroy;
  789. begin
  790. Clear;
  791. Dispose(fPageFirst);
  792. FreeAndNil(fDataLock);
  793. inherited Destroy;
  794. end;
  795. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  796. //TutlBase64Decoder/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  797. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  798. function TutlBase64Decoder.{%H-}Read(var Buffer; Count: Longint): Longint;
  799. begin
  800. ReadNotImplemented;
  801. end;
  802. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  803. function TutlBase64Decoder.Decode(const aOutput: TStream): boolean;
  804. var
  805. a: Integer;
  806. x: Integer;
  807. b: Integer;
  808. c: AnsiChar;
  809. begin
  810. Result:= false;
  811. a := 0;
  812. b := 0;
  813. Position:= 0;
  814. while inherited Read(c{%H-}, sizeof(c)) = sizeof(c) do begin
  815. x := Pos(c, CODE64) - 1;
  816. if (x >= 0) then begin
  817. b := b * 64 + x;
  818. a := a + 6;
  819. if a >= 8 then begin
  820. a := a - 8;
  821. x := b shr a;
  822. b := b mod (1 shl a);
  823. aOutput.WriteByte(x);
  824. end;
  825. end else if c = PADDING_CHARACTER then
  826. break
  827. else
  828. Exit;
  829. end;
  830. Result:= true;
  831. end;
  832. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  833. constructor TutlBase64Decoder.Create;
  834. begin
  835. inherited Create('');
  836. end;
  837. end.