. * * To disable strict typing, comment out the directive below. */ declare(strict_types=1); class CircularBuffer { /** * @var int Array capacity. */ private int $cap = 0; /** * @var \SplFixedArray Storage, faster than plain array and fixed size. */ private SplFixedArray $data; /** * @var int Start of data with $this->>data. */ private int $base = 0; /** * @var int Number of data items in $this->>data. */ private int $length = 0; public function __construct(int $length) { $this->cap = $length; $this->data = new SplFixedArray($length); } public function clear(): void { $this->data = new SplFixedArray($this->cap); $this->base = 0; $this->length = 0; } /** * @throws \BufferEmptyError */ public function read() { if ($this->length === 0) { throw new BufferEmptyError(); } $res = $this->data[$this->base]; $this->base = ($this->base + 1) % $this->cap; $this->length--; return $res; } /** * @throws \BufferFullError */ public function write($item): void { if ($this->length == $this->cap) { throw new BufferFullError(); } $this->data[($this->base+$this->length)%$this->cap] = $item; $this->length++; } public function forceWrite($item): void { $this->data[($this->base+$this->length)%$this->cap] = $item; if ($this->length === $this->cap) { $this->base = ($this->base+1)%$this->cap; } $this->length = min($this->cap, $this->length+1); } } class BufferFullError extends Exception { } class BufferEmptyError extends Exception { }