/**
  * return current position
  *
  * @return  int
  * @throws  \LogicException  in case the stream was already closed
  * @throws  \stubbles\streams\StreamException
  */
 public function tell() : int
 {
     if (null === $this->handle) {
         throw new \LogicException('No position available for closed input stream');
     }
     $position = @ftell($this->handle);
     if (false === $position) {
         throw new StreamException('Can not read current position in php://input: ' . lastErrorMessage('unknown error'));
     }
     return $position;
 }
 /**
  * construct class from a file
  *
  * @api
  * @param   string  $propertiesFile  full path to file containing properties
  * @return  \stubbles\values\Properties
  * @throws  \InvalidArgumentException  if file can not be found or is not readable
  * @throws  \UnexpectedValueException  if file contains errors and can not be parsed
  */
 public static function fromFile(string $propertiesFile) : self
 {
     if (!file_exists($propertiesFile) || !is_readable($propertiesFile)) {
         throw new \InvalidArgumentException('Property file ' . $propertiesFile . ' not found');
     }
     $propertyData = @parse_ini_file($propertiesFile, true);
     if (false === $propertyData) {
         throw new \UnexpectedValueException('Property file at ' . $propertiesFile . ' contains errors and can not be parsed: ' . lastErrorMessage()->value());
     }
     return new static($propertyData);
 }
 /**
  * writes given bytes
  *
  * @param   string  $bytes
  * @return  int     amount of written bytes
  * @throws  \LogicException
  * @throws  \stubbles\streams\StreamException
  */
 public function write(string $bytes) : int
 {
     if (null === $this->handle) {
         throw new \LogicException('Can not write to closed output stream.');
     }
     $length = @fwrite($this->handle, $bytes);
     if (false === $length) {
         throw new StreamException('Can not write to output stream:' . lastErrorMessage('unknown error'));
     }
     return $length;
 }
 /**
  * do actual read
  *
  * @param   string  $read    function to use for reading from handle
  * @param   int     $length  max amount of bytes to read
  * @return  string
  * @throws  \LogicException
  * @throws  \stubbles\streams\StreamException
  */
 private function doRead(string $read, int $length) : string
 {
     if (null === $this->handle) {
         throw new \LogicException('Can not read from closed input stream.');
     }
     $data = @$read($this->handle, $length);
     if (false === $data) {
         $error = lastErrorMessage('unknown error');
         if (!@feof($this->handle)) {
             throw new StreamException('Can not read from input stream: ' . $error);
         }
         return '';
     }
     return $data;
 }