NMs_stream.pas
上传用户:szzdds
上传日期:2013-09-18
资源大小:293k
文件大小:5k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit NMS_Stream;
  2. interface
  3. uses
  4.   WinTypes, Classes, SysUtils;
  5. type
  6.   TS_BufferState = (bsUnknown, bsRead, bsWrite);
  7.   TS_BufferStream = class(TStream)
  8.   private
  9.     fStream: TStream;
  10.     fBuffer: PChar;
  11.     fBufPtr: PChar;
  12.     fBufEnd: PChar;
  13.     fBufSize: Cardinal;
  14.     fState: TS_BufferState;
  15.     fOnFillBuffer: TNotifyEvent;
  16.     fOnFlushBuffer: TNotifyEvent;
  17.     function GetBufPosition: Integer;
  18.   protected
  19.     function FillBuffer: Boolean; virtual;
  20.     procedure PutBack(Ch: Char); virtual;
  21.     procedure AfterFillBuffer; virtual;
  22.     procedure AfterFlushBuffer; virtual;
  23.     property Buffer: PChar read fBuffer;
  24.     property BufPtr: PChar read fBufPtr;
  25.     property BufSize: Cardinal read fBufSize;
  26.     property BufEnd: PChar read fBufEnd;
  27.     property BufPosition: Integer read GetBufPosition;
  28.     property State: TS_BufferState read fState;
  29.     property Stream: TStream read fStream;
  30.   public
  31.     constructor Create(Stream: TStream); virtual;
  32.     destructor Destroy; override;
  33.     function FlushBuffer: Boolean; virtual;
  34.     function Read(var Buffer; Count: LongInt): LongInt; override;
  35.     function Write(const Buffer; Count: LongInt): LongInt; override;
  36.     function Seek(Offset: LongInt; Origin: Word): LongInt; override;
  37.     function IsEof: Boolean;
  38.     property OnFillBuffer: TNotifyEvent read fOnFillBuffer write fOnFillBuffer;
  39.     property OnFlushBuffer: TNotifyEvent read fOnFlushBuffer write fOnFlushBuffer;
  40.   end;
  41. const
  42. //  BufferSize: Integer = 8192;
  43. //  BufferSize: Integer = 16384;
  44.   BufferSize: Integer = 32768;
  45. //  BufferSize: Integer = 65536;
  46. implementation
  47. uses
  48.   WinProcs, NMS_Huge;
  49. constructor TS_BufferStream.Create(Stream: TStream);
  50. begin
  51.   inherited Create;
  52.   fStream := Stream;
  53.   fBufSize := BufferSize;
  54.   GetMem(fBuffer, BufSize);
  55.   fBufEnd := Buffer + BufSize;
  56.   fState := bsUnknown;
  57. end;
  58. destructor TS_BufferStream.Destroy;
  59. begin
  60.   if State = bsWrite then
  61.     FlushBuffer;
  62.   FreeMem(fBuffer, BufSize);
  63.   inherited Destroy;
  64. end;
  65. function TS_BufferStream.FillBuffer: Boolean;
  66. var
  67.   NumBytes: Cardinal;
  68. begin
  69.   NumBytes := Stream.Read(Buffer^, BufSize);
  70.   fBufPtr := Buffer;
  71.   fBufEnd := Buffer + NumBytes;
  72.   Result := NumBytes > 0;
  73.   if Result then
  74.     fState := bsRead
  75.   else
  76.     fState := bsUnknown;
  77.   AfterFillBuffer;
  78. end;
  79. function TS_BufferStream.FlushBuffer: Boolean;
  80. var
  81.   NumBytes: Cardinal;
  82. begin
  83.   NumBytes := BufPtr - Buffer;
  84.   Result := NumBytes = Stream.Write(Buffer^, NumBytes);
  85.   fBufPtr := Buffer;
  86.   fState := bsUnknown;
  87.   AfterFlushBuffer;
  88. end;
  89. function TS_BufferStream.Read(var Buffer; Count: LongInt): LongInt;
  90. var
  91.   Ptr: PChar;
  92.   NumBytes: Cardinal;
  93. begin
  94.   if State = bsWrite then
  95.     FlushBuffer
  96.   else if BufPtr = nil then
  97.     fBufPtr := BufEnd;
  98.   Ptr := @Buffer;
  99.   Result := 0;
  100.   while Count > 0 do
  101.   begin
  102.      if BufPtr = BufEnd then
  103.       if not FillBuffer then
  104.         Break;
  105.     NumBytes := BufEnd - BufPtr;
  106.     if Count < NumBytes then
  107.       NumBytes := Count;
  108.     HMemCpy(Ptr, BufPtr, NumBytes);
  109.     Dec(Count, NumBytes);
  110.     Inc(fBufPtr, NumBytes);
  111.     Inc(Result, NumBytes);
  112.     Ptr := HugeOffset(Ptr, NumBytes);
  113.   end;
  114. end;
  115. function TS_BufferStream.Write(const Buffer; Count: LongInt): LongInt;
  116. var
  117.   Ptr: Pointer;
  118.   NumBytes: Cardinal;
  119. begin
  120.   if State = bsRead then
  121.     fStream.Position := Position
  122.   else if BufPtr = nil then
  123.   begin
  124.     fBufPtr := fBuffer;
  125.     fBufEnd := fBuffer + BufSize;
  126.   end;
  127.   Ptr := @Buffer;
  128.   Result := 0;
  129.   while Count > 0 do
  130.   begin
  131.     NumBytes := BufEnd - BufPtr;
  132.     if Count < NumBytes then
  133.       NumBytes := Count;
  134.     HMemCpy(BufPtr, Ptr, NumBytes);
  135.     Dec(Count, NumBytes);
  136.     Inc(fBufPtr, NumBytes);
  137.     Inc(Result, NumBytes);
  138.     Ptr := HugeOffset(Ptr, NumBytes);
  139.     if BufPtr = BufEnd then
  140.       if not FlushBuffer then
  141.         Break;
  142.   end;
  143.   if BufPtr <> fBuffer then
  144.     fState := bsWrite;
  145. end;
  146. function TS_BufferStream.Seek(Offset: LongInt; Origin: Word): LongInt;
  147. var
  148.   CurrentPosition: LongInt;
  149. begin
  150.   CurrentPosition := Stream.Position + BufPosition;
  151.   case Origin of
  152.     soFromBeginning: Result := Offset;
  153.     soFromCurrent:   Result := Stream.Position + BufPosition + Offset;
  154.     soFromEnd:       Result := Stream.Size - Offset;
  155.   else
  156.     raise Exception.CreateFmt('Invalid seek origin = %d', [Origin]);
  157.   end;
  158.    if Result <> CurrentPosition then
  159.   begin
  160.     if (State = bsWrite) and not FlushBuffer then
  161.       raise EStreamError.Create('Seek error');
  162.     Stream.Position := Result;
  163.     fBufPtr := nil;
  164.     fState := bsUnknown;
  165.   end;
  166. end;
  167. function TS_BufferStream.GetBufPosition: Integer;
  168. begin
  169.   Result := 0;
  170.   case State of
  171.     bsUnknown: Result := 0;
  172.     bsRead:    Result := BufPtr - BufEnd;
  173.     bsWrite:   Result := BufPtr - Buffer;
  174.   end;
  175. end;
  176. procedure TS_BufferStream.PutBack(Ch: Char);
  177. begin
  178.   if fBufPtr <= fBuffer then
  179.     raise EStreamError.Create('PutBack overflow');
  180.   Dec(fBufPtr);
  181.   BufPtr[0] := Ch;
  182. end;
  183. function TS_BufferStream.IsEof: Boolean;
  184. begin
  185.   Result := (BufPtr = BufEnd) and
  186.     (Stream.Position = Stream.Size);
  187. end;
  188. procedure TS_BufferStream.AfterFillBuffer;
  189. begin
  190.   if Assigned(fOnFillBuffer) then
  191.     fOnFillBuffer(Self);
  192. end;
  193. procedure TS_BufferStream.AfterFlushBuffer;
  194. begin
  195.   if Assigned(fOnFlushBuffer) then
  196.     fOnFlushBuffer(Self);
  197. end;
  198. end.