type
  TCircularBuffer = class
  public
    constructor Create; overload;
    constructor Create(ACapacity: NativeInt); overload;
    destructor Destroy; override;

    procedure InitBuffer(NewCapacity: NativeInt);
    procedure FreeBuffer;
    procedure Reset;
    procedure EndWriting;
    procedure Terminate;
    function IsEmpty: Boolean;
    function IsFull: Boolean;
    function DataSize: Int64;
    function Discard(Count: LongInt): LongInt;
    function SpaceSize: Int64;
    function Read(var Buffer; Count: LongInt): LongInt;
    function Write(const Buffer; Count: LongInt): LongInt;

    property Capacity: NativeInt read FCapacity write SetCapacity;
    property AutoGrow: Boolean read FAutoGrow write FAutoGrow;
    property AutoGrowMax: NativeInt read FAutoGrowMax write FAutoGrowMax;
    property WaitForData: Boolean read FWaitForData write FWaitForData;
    property WaitForSpace: Boolean read FWaitForSpace write FWaitForSpace;
    property ReadCount: Int64 read FReadCount;
    property WriteCount: Int64 read FWriteCount;
    property EndOfWriting: Boolean read FEndOfWriting;
    property Terminated: Boolean read FTerminated;
  end;

  TCircularBufferStream = class(TStream)
  public
    constructor Create; overload;
    constructor Create(ACapacity: NativeInt); overload;
    destructor Destroy; override;

    function Read(var Buffer; Count: LongInt): LongInt; override;
    function Write(const Buffer; Count: LongInt): LongInt; override;
    function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;

    property Buffer: TCircularBuffer read FBuffer;
  end;

implementation

const
  MemoryAlign     = $2000;    // 8192, 8 KB, Must be a power of 2
  DefaultCapacity = $100000;  // 1024 * 1024, 1 MB
  AutoMaxCapacity = $1000000; // 1024 * 1024 * 16, 16 MB
