filename = $filename; $this->filesize = filesize($filename); $this->type = $type; $this->cache = collect(); } /** * Enable getting values for keys in the response * * @param string $key * @return mixed|object * @throws \Exception */ public function __get(string $key): mixed { switch ($key) { case 'fh': case 'type': return $this->{$key}; default: throw new \Exception('Unknown key: '.$key); } } /** * Unpack data into our cache * * @param string|null $data * @return Collection * @throws \Exception */ protected function cache(?string $data=NULL): Collection { $data = $data ?: $this->data(); if (! count($this->cache) && $this->size) { $this->cache = collect(unpack($this->unpack(),$data)); if ($this->size > ($x=$this->unpack_size())) $this->unused_data = substr($data,$x); } return $this->cache; } protected function data(int $size=4096): string { // Quick validation if (($size ?: $this->size) > static::record_size) throw new \Exception(sprintf('Refusing to read [%d] which is more than %d of data',$size ?: $this->size,self::record_size)); $data = ''; if ($this->fopen()) { while ((! is_null($read=$this->fread())) && (strlen($data) <= ($size ?: $this->size))) $data .= $read; $this->fclose(); } return $data; } protected function fclose(): bool { fclose($this->fh); unset($this->fh); return TRUE; } /** * Open the file and seek to the atom * * @return bool */ protected function fopen(): bool { $this->fh = fopen($this->filename,'r'); fseek($this->fh,$this->offset); $this->fp = 0; return TRUE; } /** * Read the atom from the file * * @param int $size * @return string|NULL */ protected function fread(int $size=4096): ?string { if ($this->fp === $this->size) return NULL; if ($this->fp+$size > $this->size) $size = $this->size-$this->fp; $read = fread($this->fh,$size); $this->fp += $size; return $read; } protected function fseek(int $offset): int { $this->fp = $offset; return fseek($this->fh,$this->offset+$this->fp); } protected function ftell(): int { return ftell($this->fh); } protected function unpack(array $unpack=[]): string { return collect($unpack ?: static::unpack)->map(fn($v,$k)=>$v[0].$k)->join('/'); } protected function unpack_size(array $unpack=[]): int { return collect($unpack ?: static::unpack)->map(fn($v,$k)=>$v[1])->sum(); } }