home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 January / ChipCD_1.03.iso / zkuste / delphi / unity / d56 / FNDUTL.ZIP / Streams / cStreams.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2002-10-29  |  25.2 KB  |  757 lines

  1. {$INCLUDE ..\cDefines.inc}
  2. unit cStreams;
  3.  
  4. {                                                                              }
  5. {                               Streams v3.07                                  }
  6. {                                                                              }
  7. {      This unit is copyright ⌐ 1999-2002 by David Butler (david@e.co.za)      }
  8. {                                                                              }
  9. {                  This unit is part of Delphi Fundamentals.                   }
  10. {                   Its original file name is cStreams.pas                     }
  11. {       The latest version is available from the Fundamentals home page        }
  12. {                     http://fundementals.sourceforge.net/                     }
  13. {                                                                              }
  14. {                I invite you to use this unit, free of charge.                }
  15. {        I invite you to distibute this unit, but it must be for free.         }
  16. {             I also invite you to contribute to its development,              }
  17. {             but do not distribute a modified copy of this file.              }
  18. {                                                                              }
  19. {          A forum is available on SourceForge for general discussion          }
  20. {             http://sourceforge.net/forum/forum.php?forum_id=2117             }
  21. {                                                                              }
  22. {                                                                              }
  23. { Revision history:                                                            }
  24. {   01/03/1999  0.01  Initial version.                                         }
  25. {   08/02/2000  1.02  AStreamEx.                                               }
  26. {   08/05/2000  1.03  ATRecordStream.                                          }
  27. {   01/06/2000  1.04  TFixedLenRecordStreamer.                                 }
  28. {   29/05/2002  3.05  Created cReaders and cWriters units from cStreams.       }
  29. {   03/08/2002  3.06  Moved TVarSizeAllocator to unit cVarAllocator.           }
  30. {   18/08/2002  3.07  Added TReaderWriter as AStream.                          }
  31. {                                                                              }
  32.  
  33. interface
  34.  
  35. uses
  36.   // Delphi
  37.   SysUtils,
  38.  
  39.   // Fundamentals
  40.   cReaders,
  41.   cWriters;
  42.  
  43.  
  44.  
  45. {                                                                              }
  46. { AStream                                                                      }
  47. {   Abstract base class for streams.                                           }
  48. {                                                                              }
  49. type
  50.   AStream = class;
  51.   AStreamCopyProgressEvent = Procedure (const Source, Destination : AStream;
  52.       const BytesCopied : Int64; var Abort : Boolean) of object;
  53.   AStream = class
  54.     protected
  55.     FOnCopyProgress : AStreamCopyProgressEvent;
  56.  
  57.     Function  GetPosition : Int64; virtual; abstract;
  58.     Procedure SetPosition (const Position : Int64); virtual; abstract;
  59.     Function  GetSize : Int64; virtual; abstract;
  60.     Procedure SetSize (const Size : Int64); virtual; abstract;
  61.     Function  GetReader : AReaderEx; virtual; abstract;
  62.     Function  GetWriter : AWriterEx; virtual; abstract;
  63.  
  64.     Procedure TriggerCopyProgressEvent (const Source, Destination : AStream;
  65.               const BytesCopied : Int64; var Abort : Boolean); virtual;
  66.  
  67.     public
  68.     Function  Read (var Buffer; const Size : Integer) : Integer; virtual; abstract;
  69.     Function  Write (const Buffer; const Size : Integer) : Integer; virtual; abstract;
  70.  
  71.     Property  Position : Int64 read GetPosition write SetPosition;
  72.     Property  Size : Int64 read GetSize write SetSize;
  73.     Function  EOF : Boolean; virtual;
  74.  
  75.     Property  Reader : AReaderEx read GetReader;
  76.     Property  Writer : AWriterEx read GetWriter;
  77.  
  78.     Procedure ReadBuffer (var Buffer; const Size : Integer);
  79.     Function  ReadByte : Byte;
  80.     Procedure WriteBuffer (const Buffer; const Size : Integer);
  81.     Procedure WriteStr (const S : String);
  82.  
  83.     Procedure Assign (const Source : TObject); virtual;
  84.     Function  WriteTo (const Destination : AStream; const BlockSize : Integer = 0;
  85.               const Count : Int64 = -1) : Int64;
  86.  
  87.     Property  OnCopyProgress : AStreamCopyProgressEvent read FOnCopyProgress write FOnCopyProgress;
  88.   end;
  89.   EStream = class (Exception);
  90.   EStreamOperationAborted = class (EStream)
  91.     Constructor Create;
  92.   end;
  93.  
  94.  
  95.  
  96. {                                                                              }
  97. { Stream proxies                                                               }
  98. {                                                                              }
  99. type
  100.   { TStreamReaderProxy                                                         }
  101.   TStreamReaderProxy = class (AReaderEx)
  102.     protected
  103.     FStream : AStream;
  104.  
  105.     Function  GetPosition : Int64; override;
  106.     Procedure SetPosition (const Position : Int64); override;
  107.     Function  GetSize : Int64; override;
  108.  
  109.     public
  110.     Constructor Create (const Stream : AStream);
  111.     Property  Stream : AStream read FStream;
  112.  
  113.     Function  Read (var Buffer; const Size : Integer) : Integer; override;
  114.     Function  EOF : Boolean; override;
  115.   end;
  116.  
  117.   { TStreamWriterProxy                                                         }
  118.   TStreamWriterProxy = class (AWriterEx)
  119.     protected
  120.     FStream : AStream;
  121.  
  122.     Function  GetPosition : Int64; override;
  123.     Procedure SetPosition (const Position : Int64); override;
  124.     Function  GetSize : Int64; override;
  125.     Procedure SetSize (const Size : Int64); override;
  126.  
  127.     public
  128.     Constructor Create (const Stream : AStream);
  129.     Property  Stream : AStream read FStream;
  130.  
  131.     Function  Write (const Buffer; const Size : Integer) : Integer; override;
  132.   end;
  133.  
  134.   
  135.  
  136. {                                                                              }
  137. { Stream functions                                                             }
  138. {                                                                              }
  139. type
  140.   TCopyProgressProcedure = Procedure (const Source, Destination : AStream;
  141.       const BytesCopied : Int64; var Abort : Boolean);
  142.  
  143. Function  CopyStream (const Source, Destination : AStream;
  144.           const SourceOffset : Int64 = 0; const DestinationOffset : Int64 = 0;
  145.           const BlockSize : Integer = 0; const Count : Int64 = -1;
  146.           const ProgressCallback : TCopyProgressProcedure = nil;
  147.           const CopyFromBack : Boolean = False) : Int64; overload;
  148.  
  149. Function  CopyStream (const Source : AReaderEx; const Destination : AWriterEx;
  150.           const BlockSize : Integer = 0) : Int64; overload;
  151.  
  152. Procedure DeleteStreamRange (const Stream : AStream; const Position, Count : Int64;
  153.           const ProgressCallback : TCopyProgressProcedure = nil);
  154. Procedure InsertStreamRange (const Stream : AStream; const Position, Count : Int64;
  155.           const ProgressCallback : TCopyProgressProcedure = nil);
  156.  
  157. Procedure StreamDotLineTerminated (const Source : AStream;
  158.           const Destination : AStream; const ProgressCallback : TCopyProgressProcedure = nil); overload;
  159. Procedure StreamDotLineTerminated (const Source : String;
  160.           const Destination : AStream; const ProgressCallback : TCopyProgressProcedure = nil); overload;
  161.  
  162.  
  163.  
  164. {                                                                              }
  165. { TReaderWriter                                                                }
  166. {   Composition of a Reader and a Writer as a Stream.                          }
  167. {                                                                              }
  168. type
  169.   TReaderWriter = class (AStream)
  170.     protected
  171.     FReader         : AReaderEx;
  172.     FWriter         : AWriterEx;
  173.     FReaderOwner    : Boolean;
  174.     FWriterOwner    : Boolean;
  175.  
  176.     Procedure RaiseNoReaderError;
  177.     Procedure RaiseNoWriterError;
  178.  
  179.     Function  GetPosition : Int64; override;
  180.     Procedure SetPosition (const Position : Int64); override;
  181.     Function  GetSize : Int64; override;
  182.     Procedure SetSize (const Size : Int64); override;
  183.     Function  GetReader : AReaderEx; override;
  184.     Function  GetWriter : AWriterEx; override;
  185.  
  186.     public
  187.     Constructor Create (const Reader : AReaderEx; const Writer : AWriterEx;
  188.                 const ReaderOwner : Boolean = True; const WriterOwner : Boolean = True);
  189.     Destructor Destroy; override;
  190.  
  191.     Property  Reader : AReaderEx read FReader;
  192.     Property  Writer : AWriterEx read FWriter;
  193.     Property  ReaderOwner : Boolean read FReaderOwner write FReaderOwner;
  194.     Property  WriterOwner : Boolean read FWriterOwner write FWriterOwner;
  195.  
  196.     Function  Read (var Buffer; const Size : Integer) : Integer; override;
  197.     Function  Write (const Buffer; const Size : Integer) : Integer; override;
  198.   end;
  199.   EReaderWriter = class (Exception);
  200.  
  201.  
  202.  
  203. {                                                                              }
  204. { TFileStream                                                                  }
  205. {   Stream implementation for a file.                                          }
  206. {                                                                              }
  207. type
  208.   TFileStreamOpenMode = (fsomRead,
  209.                          fsomReadWrite,
  210.                          fsomCreate,
  211.                          fsomCreateIfNotExist);
  212.   TFileStream = class (TReaderWriter)
  213.     protected
  214.     FFileName : String;
  215.  
  216.     Procedure SetPosition (const Position : Int64); override;
  217.     Function  GetFileHandle : Integer;
  218.     Function  GetFileCreated : Boolean;
  219.  
  220.     public
  221.     Constructor Create (const FileName : String;
  222.                 const OpenMode : TFileStreamOpenMode); overload;
  223.     Constructor Create (const FileHandle : Integer; const HandleOwner : Boolean); overload;
  224.  
  225.     Property  FileName : String read FFileName;
  226.     Property  FileHandle : Integer read GetFileHandle;
  227.     Property  FileCreated : Boolean read GetFileCreated;
  228.     Procedure DeleteFile;
  229.   end;
  230.   EFileStream = class (EStream);
  231.  
  232.  
  233.  
  234. {                                                                              }
  235. { Self-testing code                                                            }
  236. {                                                                              }
  237. Procedure SelfTest;
  238.  
  239.  
  240.  
  241. implementation
  242.  
  243. uses
  244.   // Fundamentals
  245.   cUtils,
  246.   cStrings;
  247.  
  248.  
  249.  
  250. {                                                                              }
  251. { EStreamOperationAborted                                                      }
  252. {                                                                              }
  253. Constructor EStreamOperationAborted.Create;
  254.   Begin
  255.     inherited Create ('Stream operation aborted');
  256.   End;
  257.  
  258.  
  259.  
  260. {                                                                              }
  261. { TStreamReaderProxy                                                           }
  262. {                                                                              }
  263. Constructor TStreamReaderProxy.Create (const Stream : AStream);
  264.   Begin
  265.     inherited Create;
  266.     Assert (Assigned (Stream), 'Assigned (Stream)');
  267.     FStream := Stream;
  268.   End;
  269.  
  270. Function TStreamReaderProxy.GetPosition : Int64;
  271.   Begin
  272.     Result := FStream.Position;
  273.   End;
  274.  
  275. Procedure TStreamReaderProxy.SetPosition (const Position : Int64);
  276.   Begin
  277.     FStream.Position := Position;
  278.   End;
  279.  
  280. Function TStreamReaderProxy.GetSize : Int64;
  281.   Begin
  282.     Result := FStream.Size;
  283.   End;
  284.  
  285. Function TStreamReaderProxy.Read (var Buffer; const Size : Integer) : Integer;
  286.   Begin
  287.     Result := FStream.Read (Buffer, Size)
  288.   End;
  289.  
  290. Function TStreamReaderProxy.EOF : Boolean;
  291.   Begin
  292.     Result := FStream.EOF;
  293.   End;
  294.  
  295.  
  296.  
  297. {                                                                              }
  298. { TStreamWriterProxy                                                           }
  299. {                                                                              }
  300. Constructor TStreamWriterProxy.Create (const Stream : AStream);
  301.   Begin
  302.     inherited Create;
  303.     Assert (Assigned (Stream), 'Assigned (Stream)');
  304.     FStream := Stream;
  305.   End;
  306.  
  307. Function TStreamWriterProxy.GetPosition : Int64;
  308.   Begin
  309.     Result := FStream.Position;
  310.   End;
  311.  
  312. Procedure TStreamWriterProxy.SetPosition (const Position : Int64);
  313.   Begin
  314.     FStream.Position := Position;
  315.   End;
  316.  
  317. Function TStreamWriterProxy.GetSize : Int64;
  318.   Begin
  319.     Result := FStream.Size;
  320.   End;
  321.  
  322. Procedure TStreamWriterProxy.SetSize (const Size : Int64);
  323.   Begin
  324.     FStream.Size := Size;
  325.   End;
  326.  
  327. Function TStreamWriterProxy.Write (const Buffer; const Size : Integer) : Integer;
  328.   Begin
  329.     Result := FStream.Write (Buffer, Size)
  330.   End;
  331.  
  332.  
  333.  
  334. {                                                                              }
  335. { CopyStream                                                                   }
  336. {                                                                              }
  337. const
  338.   DefaultBlockSize = 2048;
  339.  
  340. Function CopyStream (const Source, Destination : AStream; const SourceOffset : Int64; const DestinationOffset : Int64; const BlockSize : Integer; const Count : Int64; const ProgressCallback : TCopyProgressProcedure; const CopyFromBack : Boolean) : Int64;
  341. var Buf     : Pointer;
  342.     L, I, C : Integer;
  343.     R, S, D : Int64;
  344.     A       : Boolean;
  345.   Begin
  346.     if not Assigned (Source) then
  347.       raise EStream.Create ('Invalid source');
  348.     if not Assigned (Destination) then
  349.       raise EStream.Create ('Invalid destination');
  350.     S := SourceOffset;
  351.     D := DestinationOffset;
  352.     if (S < 0) or (D < 0) then
  353.       raise EStream.Create ('Invalid offset');
  354.     if (Source = Destination) and (Count < 0) and (S < D) then
  355.       raise EStream.Create ('Invalid parameters');
  356.     A := False;
  357.     if Assigned (ProgressCallback) then
  358.       begin
  359.         ProgressCallback (Source, Destination, 0, A);
  360.         if A then
  361.           raise EStreamOperationAborted.Create;
  362.       end;
  363.     Result := 0;
  364.     R := Count;
  365.     if R = 0 then
  366.       exit;
  367.     L := BlockSize;
  368.     if L <= 0 then
  369.       L := DefaultBlockSize;
  370.     if (R > 0) and (R < L) then
  371.       L := R;
  372.     if CopyFromBack then
  373.       begin
  374.         if R < 0 then
  375.           raise EStream.Create ('Invalid count');
  376.         Inc (S, R - L);
  377.         Inc (D, R - L);
  378.       end;
  379.     GetMem (Buf, L);
  380.     try
  381.       While not Source.EOF and (R <> 0) do
  382.         begin
  383.           C := L;
  384.           if (R > 0) and (R < C) then
  385.             C := R;
  386.           Source.Position := S;
  387.           I := Source.Read (Buf^, C);
  388.           if (I <= 0) and not Source.EOF then
  389.             raise EStream.Create ('Stream read error');
  390.           Destination.Position := D;
  391.           Destination.WriteBuffer (Buf^, I);
  392.           Inc (Result, I);
  393.           if R > 0 then
  394.             Dec (R, I);
  395.           if CopyFromBack then
  396.             begin
  397.               Dec (S, I);
  398.               Dec (D, I);
  399.             end else
  400.             begin
  401.               Inc (S, I);
  402.               Inc (D, I);
  403.             end;
  404.           if Assigned (ProgressCallback) then
  405.             begin
  406.               ProgressCallback (Source, Destination, Result, A);
  407.               if A then
  408.                 raise EStreamOperationAborted.Create;
  409.             end;
  410.         end;
  411.     finally
  412.       FreeMem (Buf);
  413.     end;
  414.   End;
  415.  
  416. Function CopyStream (const Source : AReaderEx; const Destination : AWriterEx; const BlockSize : Integer) : Int64;
  417. var Buf  : Pointer;
  418.     L, I : Integer;
  419.   Begin
  420.     if not Assigned (Source) then
  421.       raise EStream.Create ('Invalid source');
  422.     if not Assigned (Destination) then
  423.       raise EStream.Create ('Invalid destination');
  424.     L := BlockSize;
  425.     if L <= 0 then
  426.       L := DefaultBlockSize;
  427.     Result := 0;
  428.     GetMem (Buf, L);
  429.     try
  430.       While not Source.EOF do
  431.         begin
  432.           I := Source.Read (Buf^, L);
  433.           if (I = 0) and not Source.EOF then
  434.             Source.RaiseReadError;
  435.           Destination.WriteBuffer (Buf^, I);
  436.           Inc (Result, I);
  437.         end;
  438.     finally
  439.       FreeMem (Buf);
  440.     end;
  441.   End;
  442.  
  443. Procedure DeleteStreamRange (const Stream : AStream; const Position, Count : Int64; const ProgressCallback : TCopyProgressProcedure);
  444.   Begin
  445.     if Count <= 0 then
  446.       exit;
  447.     if CopyStream (Stream, Stream, Stream.Position + Count, Stream.Position, 0, Count,
  448.         ProgressCallback, False) <> Count then
  449.       raise EStream.Create ('Copy error');
  450.   End;
  451.  
  452. Procedure InsertStreamRange (const Stream : AStream; const Position, Count : Int64; const ProgressCallback : TCopyProgressProcedure);
  453.   Begin
  454.     if Count <= 0 then
  455.       exit;
  456.     if CopyStream (Stream, Stream, Stream.Position, Stream.Position + Count, 0, Count,
  457.         ProgressCallback, True) <> Count then
  458.       raise EStream.Create ('Copy error');
  459.   End;
  460.  
  461. Procedure StreamDotLineTerminated (const Source : AStream; const Destination : AStream; const ProgressCallback : TCopyProgressProcedure);
  462. var R : AReaderEx;
  463.     W : AWriterEx;
  464.     P : Int64;
  465.     A : Boolean;
  466.     S : String;
  467.   Begin
  468.     R := Source.Reader;
  469.     W := Destination.Writer;
  470.     P := R.Position;
  471.     A := False;
  472.     While not R.EOF do
  473.       begin
  474.         S := R.ExtractLine (-1, True);
  475.         if (S <> '') and (S [1] = '.') then
  476.           S := '.' + S;
  477.         W.WriteLine (S, nlCRLF);
  478.         if Assigned (ProgressCallback) then
  479.           begin
  480.             ProgressCallback (Source, Destination, R.Position - P, A);
  481.             if A then
  482.               raise EStreamOperationAborted.Create;
  483.           end;
  484.       end;
  485.     W.WriteLine ('.', nlCRLF);
  486.   End;
  487.  
  488. Procedure StreamDotLineTerminated (const Source : String; const Destination : AStream; const ProgressCallback : TCopyProgressProcedure);
  489. var R : StringArray;
  490.     W : AWriterEx;
  491.     A : Boolean;
  492.     S : String;
  493.     I : Integer;
  494.     P : Int64;
  495.   Begin
  496.     R := Split (Source, CRLF, [], 1, -1, -1, saSingleAllocation);
  497.     W := Destination.Writer;
  498.     A := False;
  499.     P := 0;
  500.     For I := 0 to Length (R) - 1 do
  501.       begin
  502.         S := R [I];
  503.         Inc (P, Length (S) + 2);
  504.         if (S <> '') and (S [1] = '.') then
  505.           S := '.' + S;
  506.         W.WriteLine (S, nlCRLF);
  507.         if Assigned (ProgressCallback) then
  508.           begin
  509.             ProgressCallback (nil, Destination, P, A);
  510.             if A then
  511.               raise EStreamOperationAborted.Create;
  512.           end;
  513.       end;
  514.     W.WriteLine ('.', nlCRLF);
  515.   End;
  516.  
  517.  
  518.  
  519. {                                                                              }
  520. { AStream                                                                      }
  521. {                                                                              }
  522. Function AStream.EOF : Boolean;
  523.   Begin
  524.     Result := Position >= Size;
  525.   End;
  526.  
  527. Procedure AStream.ReadBuffer (var Buffer; const Size : Integer);
  528.   Begin
  529.     if Size <= 0 then
  530.       exit;
  531.     if Read (Buffer, Size) <> Size then
  532.       raise EStream.Create ('Read error');
  533.   End;
  534.  
  535. Function AStream.ReadByte : Byte;
  536.   Begin
  537.     ReadBuffer (Result, 1);
  538.   End;
  539.  
  540. Procedure AStream.WriteBuffer (const Buffer; const Size : Integer);
  541.   Begin
  542.     if Size <= 0 then
  543.       exit;
  544.     if Write (Buffer, Size) <> Size then
  545.       raise EStream.Create ('Write error');
  546.   End;
  547.  
  548. Procedure AStream.WriteStr (const S : String);
  549.   Begin
  550.     WriteBuffer (Pointer (S)^, Length (S));
  551.   End;
  552.  
  553. Procedure AStreamCopyCallback (const Source, Destination : AStream; const BytesCopied : Int64; var Abort : Boolean);
  554.   Begin
  555.     Assert (Assigned (Source) and Assigned (Destination) and not Abort, 'Assigned (Source) and Assigned (Destination) and not Abort');
  556.     Source.TriggerCopyProgressEvent (Source, Destination, BytesCopied, Abort);
  557.     if Abort then
  558.       exit;
  559.     Destination.TriggerCopyProgressEvent (Source, Destination, BytesCopied, Abort);
  560.   End;
  561.  
  562. Procedure AStream.TriggerCopyProgressEvent (const Source, Destination : AStream; const BytesCopied : Int64; var Abort : Boolean);
  563.   Begin
  564.     if Assigned (FOnCopyProgress) then
  565.       FOnCopyProgress (Source, Destination, BytesCopied, Abort);
  566.   End;
  567.  
  568. Procedure AStream.Assign (const Source : TObject);
  569.   Begin
  570.     if not Assigned (Source) then
  571.       raise EStream.Create ('Invalid source');
  572.     if Source is AStream then
  573.       Size := CopyStream (AStream (Source), self, 0, 0, 0, -1, AStreamCopyCallback, False) else
  574.       raise EStream.Create ('Assign not defined for source type');
  575.   End;
  576.  
  577. Function AStream.WriteTo (const Destination : AStream; const BlockSize : Integer; const Count : Int64) : Int64;
  578.   Begin
  579.     Result := CopyStream (self, Destination, Position, Destination.Position,
  580.         BlockSize, Count, AStreamCopyCallback, False);
  581.   End;
  582.  
  583.  
  584.  
  585. {                                                                              }
  586. { TReaderWriter                                                                }
  587. {                                                                              }
  588. Constructor TReaderWriter.Create (const Reader : AReaderEx; const Writer : AWriterEx; const ReaderOwner : Boolean; const WriterOwner : Boolean);
  589.   Begin
  590.     inherited Create;
  591.     FReader := Reader;
  592.     FReaderOwner := ReaderOwner;
  593.     FWriter := Writer;
  594.     FWriterOwner := WriterOwner;
  595.   End;
  596.  
  597. Destructor TReaderWriter.Destroy;
  598.   Begin
  599.     if FReaderOwner then
  600.       FReader.Free;
  601.     FReader := nil;
  602.     if FWriterOwner then
  603.       FWriter.Free;
  604.     FWriter := nil;
  605.     inherited Destroy;
  606.   End;
  607.  
  608. Procedure TReaderWriter.RaiseNoReaderError;
  609.   Begin
  610.     raise EReaderWriter.Create ('No reader');
  611.   End;
  612.  
  613. Procedure TReaderWriter.RaiseNoWriterError;
  614.   Begin
  615.     raise EReaderWriter.Create ('No writer');
  616.   End;
  617.  
  618. Function TReaderWriter.GetPosition : Int64;
  619.   Begin
  620.     if Assigned (FReader) then
  621.       Result := FReader.Position else
  622.     if Assigned (FWriter) then
  623.       Result := FWriter.Position else
  624.       Result := 0;
  625.   End;
  626.  
  627. Procedure TReaderWriter.SetPosition (const Position : Int64);
  628.   Begin
  629.     if Assigned (FReader) then
  630.       FReader.Position := Position;
  631.     if Assigned (FWriter) then
  632.       FWriter.Position := Position;
  633.   End;
  634.  
  635. Function TReaderWriter.GetReader : AReaderEx;
  636.   Begin
  637.     Result := FReader;
  638.   End;
  639.  
  640. Function TReaderWriter.GetWriter : AWriterEx;
  641.   Begin
  642.     Result := FWriter;
  643.   End;
  644.  
  645. Function TReaderWriter.GetSize : Int64;
  646.   Begin
  647.     if Assigned (FWriter) then
  648.       Result := FWriter.Size else
  649.     if Assigned (FReader) then
  650.       Result := FReader.Size else
  651.       Result := 0;
  652.   End;
  653.  
  654. Procedure TReaderWriter.SetSize (const Size : Int64);
  655.   Begin
  656.     if not Assigned (FWriter) then
  657.       RaiseNoWriterError;
  658.     FWriter.Size := Size;
  659.   End;
  660.  
  661. Function TReaderWriter.Read (var Buffer; const Size : Integer) : Integer;
  662.   Begin
  663.     if not Assigned (FReader) then
  664.       RaiseNoReaderError;
  665.     Result := FReader.Read (Buffer, Size);
  666.   End;
  667.  
  668. Function TReaderWriter.Write (const Buffer; const Size : Integer) : Integer;
  669.   Begin
  670.     if not Assigned (FWriter) then
  671.       RaiseNoWriterError;
  672.     Result := FWriter.Write (Buffer, Size);
  673.   End;
  674.  
  675.  
  676.  
  677. {                                                                              }
  678. { TFileStream                                                                  }
  679. {                                                                              }
  680. Constructor TFileStream.Create (const FileName : String; const OpenMode : TFileStreamOpenMode);
  681. const WriterModes : Array [TFileStreamOpenMode] of TFileWriterOpenMode =
  682.       (fwomOpen, fwomOpen, fwomCreate, fwomCreateIfNotExist);
  683. var W : TFileWriter;
  684.     R : AReaderEx;
  685.   Begin
  686.     FFileName := FileName;
  687.     if OpenMode = fsomRead then
  688.       begin
  689.         W := nil;
  690.         R := TFileReader.Create (FileName);
  691.       end else
  692.       begin
  693.         W := TFileWriter.Create (FileName, WriterModes [OpenMode]);
  694.         try
  695.           R := TFileReader.Create (W.Handle, False);
  696.         except
  697.           W.Free;
  698.           raise;
  699.         end;
  700.       end;
  701.     inherited Create (R, W, True, True);
  702.   End;
  703.  
  704. Constructor TFileStream.Create (const FileHandle : Integer; const HandleOwner : Boolean);
  705. var W : TFileWriter;
  706.     R : TFileReader;
  707.   Begin
  708.     W := TFileWriter.Create (FileHandle, HandleOwner);
  709.     try
  710.       R := TFileReader.Create (FileHandle, False);
  711.     except
  712.       W.Free;
  713.       raise;
  714.     end;
  715.     inherited Create (R, W, True, True);
  716.   End;
  717.  
  718. Function TFileStream.GetFileHandle : Integer;
  719.   Begin
  720.     Assert (Assigned (FReader), 'Assigned (FReader)');
  721.     Result := TFileReader (FReader).Handle;
  722.   End;
  723.  
  724. Function TFileStream.GetFileCreated : Boolean;
  725.   Begin
  726.     Result := Assigned (FWriter) and TFileWriter (FWriter).FileCreated;
  727.   End;
  728.  
  729. Procedure TFileStream.SetPosition (const Position : Int64);
  730.   Begin
  731.     if Assigned (FWriter) then
  732.       FWriter.Position := Position else
  733.     if Assigned (FReader) then
  734.       FReader.Position := Position;
  735.   End;
  736.  
  737. Procedure TFileStream.DeleteFile;
  738.   Begin
  739.     if FFileName = '' then
  740.       raise EFileStream.Create ('No filename');
  741.     SysUtils.DeleteFile (FFileName);
  742.   End;
  743.  
  744.  
  745.  
  746. {                                                                              }
  747. { Self-testing code                                                            }
  748. {                                                                              }
  749. Procedure SelfTest;
  750.   Begin
  751.   End;
  752.  
  753.  
  754.  
  755. end.
  756.  
  757.