filename,'r'); fseek($fh,$offset); } $result = collect(); $prelude = 8; while ($rp < $size) { $read = $atom ? substr($atom,$rp,$prelude) : fread($fh,$prelude); $header = unpack('Nsize/a4atom',$read); $rp += strlen($read); // For mdat atoms, if size = 1, the true size is in the 64 bit extended header, in the next 8 bytes if (($header['atom'] === 'mdat') && ($header['size'] === 1)) { $eheader = unpack('Jsize',fread($fh,8)); $rp += 8; $prelude = 16; $header['size'] = $eheader['size']; } // Load our class for this supplier $class = $class_prefix.strtolower($header['atom']); $data = $atom ? substr($atom,$rp,$header['size']-$prelude) : ($header['size']-$prelude && ($header['size']-$prelude <= self::record_size) ? fread($fh,$header['size']-$prelude) : NULL); if ($header['size'] >= $prelude) { $o = class_exists($class) ? new $class($offset+$rp,$header['size']-$prelude,$this->filename,$data,$passthru) : new $unknown($offset+$rp,$header['size']-$prelude,$this->filename,$header['atom'],$data); $result->push($o); $rp += $header['size']-$prelude; // Only need to seek if we didnt read all the data if ((! $atom) && ($header['size']-8 > static::record_size)) fseek($fh,$offset+$rp); } else { dd([get_class($this) => $data]); } // Work out if data from the last atom next to be passed onto the next one if ($callback) $passthru = $callback($o); } if (! $atom) { fclose($fh); unset($fh); } return $result; } /** * Recursively look through our object hierarchy of atoms for a specific atom class * * @param string $subatom * @param int|NULL $expect * @param int $depth * @return Collection|Atom|NULL * @throws \Exception */ public function find_atoms(string $subatom,?int $expect=NULL,int $depth=100): Collection|Atom|NULL { if (! isset($this->atoms) || ($depth < 0)) return NULL; $subatomo = $this->atoms->filter(fn($item)=>get_class($item)===$subatom); $subatomo = $subatomo ->merge($this->atoms->map(fn($item)=>$item->find_atoms($subatom,NULL,$depth-1)) ->filter(fn($item)=>$item ? $item->count() : NULL) ->flatten()); if (! $subatomo->count()) return $subatomo; if ($expect && ($subatomo->count() !== $expect)) throw new \Exception(sprintf('! Expected %d subatoms of %s, but have %d',$expect,$subatom,$subatomo->count())); return ($expect === 1) ? $subatomo->pop() : $subatomo; } }