+ throw new \Exception("Unable to open $filename");
+ }
+ $this->filesize = filesize($filename);
+ $this->pos = -1;
+ $this->buffer = null;
+ $this->key = -1;
+ $this->value = null;
+ return $this;
+ }
+
+ /**
+ * Read $size bytes behind last position
+ *
+ * @param int $size
+ * @return string
+ */
+ private function _read(int $size): string
+ {
+ $this->pos -= $size;
+ fseek($this->fh, $this->pos);
+ return fread($this->fh, $size);
+ }
+
+ /**
+ * Read next line from end of file
+ * Return null if no lines are left to read
+ *
+ * @return string|null Depending on data being buffered
+ */
+ private function _readline()
+ {
+ $buffer = & $this->buffer;
+ while (true) {
+ if ($this->pos == 0) {
+ return array_pop($buffer);
+ }
+ if (is_null($buffer)) {
+ return null;
+ }
+ if (count($buffer) > 1) {
+ return array_pop($buffer);
+ }
+ $buffer = explode(self::SEPARATOR, $this->_read(self::BUFFER_SIZE) . $buffer[0]);