IdReadLineStream.pas 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 11265: IdReadLineStream.pas
  11. {
  12. Rev 1.1 4/4/2003 7:54:50 PM BGooijen
  13. compiles again
  14. }
  15. {
  16. { Rev 1.0 11/12/2002 09:19:04 PM JPMugaas
  17. { Initial check in. Import from FTP VC.
  18. }
  19. unit IdReadLineStream;
  20. interface
  21. uses Classes;
  22. const
  23. LBUFMAXSIZE = 2048;
  24. type
  25. TIdWriteLineStream = class (TStream)
  26. // IMPORTANT!!!!!!!!
  27. // NO data members may exist in this class
  28. // This class is used to "hackcast" a TStream to add functionality
  29. public
  30. procedure Write(const AData: string); reintroduce;
  31. procedure WriteLn(const AData: string = ''); {Do not Localize}
  32. end;
  33. TIdReadLineStream = class (TStream)
  34. protected
  35. {
  36. This stream type really should be created only for data that has already been completely
  37. loaded into the Source stream. The reason is that Writes will throw this off due to
  38. the persistant internal buffering used. It might not be worth fixing. The buffering is
  39. important as it prevents us from making repeated reads for the same data which does
  40. happen with the TIdStream typecast hack.
  41. To explain, take this data:
  42. Line One<EOL>
  43. Line Two<EOL>
  44. Line Two EOL has to be read twice because the regular stream does not know where the EOL was
  45. so it had to load that text twice (once for the first ReadLn and the other for the second ReadLn.
  46. }
  47. FSourceStream : TStream;
  48. FBuffer : Array [0..LBUFMAXSIZE] of char;
  49. FBufSize : Integer;
  50. FBufferOffset : Integer;
  51. FStreamSize : Integer;
  52. public
  53. constructor Create(ASourceStream : TStream);
  54. function Read(var Buffer; Count: Longint): Longint; override;
  55. function Write(const Buffer; Count: Longint): Longint; override;
  56. function Seek(Offset: Longint; Origin: Word): Longint; override;
  57. function FindEOL(var ACrEncountered: Boolean): String;
  58. function ReadLn : String;
  59. // procedure WriteStr(const AData: string); overload;
  60. // procedure WriteLn(const AData: string = '');
  61. property SourceStream : TStream read FSourceStream;
  62. end;
  63. implementation
  64. uses IdCoreGlobal, IdGlobal, SysUtils, IdTCPStream;
  65. { TIdReadLineStream }
  66. constructor TIdReadLineStream.Create(ASourceStream: TStream);
  67. begin
  68. inherited Create;
  69. FSourceStream := ASourceStream;
  70. FBufSize := 0;
  71. FBufferOffset := 0;
  72. FStreamSize := FSourceStream.Size;
  73. end;
  74. function TIdReadLineStream.Read(var Buffer; Count: Integer): Longint;
  75. begin
  76. if (Count > 0) then
  77. begin
  78. Result := FSourceStream.Read(Buffer,Count);
  79. end
  80. else
  81. begin
  82. Result := 0;
  83. end;
  84. end;
  85. function TIdReadLineStream.ReadLn: String;
  86. var
  87. LCrEncountered : Boolean;
  88. LBytesToRead : Integer; //stream size - Position
  89. LStreamPos : Integer;
  90. begin
  91. Result := '';
  92. if InheritsFrom(TIdTCPStream) then begin
  93. Result := TIdTCPStream(Self).Connection.iohandler.ReadLn;
  94. end
  95. else
  96. begin
  97. LCrEncountered := False;
  98. while (LCrEncountered = False) do
  99. begin
  100. Result := Result + FindEOL(LCrEncountered);
  101. LStreamPos := FSourceStream.Position;
  102. LBytesToRead := FStreamSize - LStreamPos;
  103. if LBytesToRead > 0 then
  104. begin
  105. if (FBufferOffset = FBufSize) then
  106. begin
  107. FBufSize := Min(LBytesToRead,LBUFMAXSIZE);
  108. FBufferOffset := 0;
  109. FSourceStream.ReadBuffer(FBuffer[0], FBufSize);
  110. end;
  111. end
  112. else
  113. begin
  114. Exit;
  115. end;
  116. end;
  117. end;
  118. end;
  119. {procedure TIdReadLineStream.WriteStr(const AData: string);
  120. begin
  121. if Length(AData) > 0 then begin
  122. FSourceStream.WriteBuffer(AData[1], Length(AData));
  123. end;
  124. end; }
  125. function TIdReadLineStream.Write(const Buffer; Count: Integer): Longint;
  126. begin
  127. { if (Count > 0) then
  128. begin
  129. Result := FSourceStream.Write(Buffer,Count);
  130. FStreamSize := FStreamSize + Result;
  131. end
  132. else
  133. begin
  134. Result := 0;
  135. end; }
  136. Result := 0;
  137. end;
  138. {procedure TIdReadLineStream.WriteLn(const AData: string);
  139. begin
  140. WriteStr(AData + EOL);
  141. end; }
  142. function TIdReadLineStream.FindEOL(
  143. var ACrEncountered: Boolean): String;
  144. var i : Integer;
  145. LStringSize : Integer;
  146. LOldOffset : Integer;
  147. begin
  148. Result := '';
  149. i := FBufferOffset;
  150. LOldOffset := i;
  151. LStringSize := (FBufSize - FBufferOffset);
  152. while i <= FBufSize do
  153. begin
  154. case FBuffer[i] of
  155. CR : begin
  156. LStringSize := i - FBufferOffset;
  157. FBufferOffset := i;
  158. Inc(FBufferOffset);
  159. if (i < FBufSize) and (FBuffer[i+1]=LF) then
  160. begin
  161. Inc(FBufferOffset);
  162. end;
  163. ACrEncountered := True;
  164. Break;
  165. end;
  166. LF : begin
  167. LStringSize := i - FBufferOffset;
  168. FBufferOffset := i;
  169. Inc(FBufferOffset);
  170. ACrEncountered := True;
  171. Break;
  172. end;
  173. end;
  174. Inc(i);
  175. end;
  176. if ACrEncountered then
  177. begin
  178. // Dec(LStringSize);
  179. SetLength(Result,LStringSize);
  180. Move(FBuffer[LOldOffset],Result[1],LStringSize);
  181. end
  182. else
  183. begin
  184. FBufferOffset := FBufSize;
  185. SetLength(Result,LStringSize);
  186. Move(FBuffer[LOldOffset],Result[1],LStringSize);
  187. end;
  188. end;
  189. function TIdReadLineStream.Seek(Offset: Integer; Origin: Word): Longint;
  190. begin
  191. // Result := FSourceStream.Seek(Offset, Origin );
  192. Result := -1;
  193. end;
  194. { TIdWriteLineStream }
  195. procedure TIdWriteLineStream.Write(const AData: string);
  196. begin
  197. if Length(AData) > 0 then begin
  198. WriteBuffer(AData[1], Length(AData));
  199. end;
  200. end;
  201. procedure TIdWriteLineStream.WriteLn(const AData: string);
  202. begin
  203. Write(AData + EOL);
  204. end;
  205. end.