hhvm/hsl-experimental

Unable to change pointer position / tell in hsl handles.

azjezz opened this issue · 2 comments

such feature should be included in hsl, there's already builtin function to achieve this when using builtin resources : \ftell() and \fseek().

simplest implementation :

enum SeekWhence

/**
 * Specifies how the cursor position will be calculated
 * based on the seek offset.
 */
enum SeekWhence: int {
  /**
   * Set position equal to offset bytes.
   */
  SET = \SEEK_SET;
  /**
   * Set position to current location plus offset.
   */
  CURRENT = \SEEK_CUR;
  /**
   * Set position to end-of-file plus offset.
   */
  END = \SEEK_END;
}

SeekableHandle :

<<__Sealed(
  SeekableWriteHandle::class,
  SekkableReadHandle::claas,
)>>
interface SeekableHandle {
  /**
   * Seek to a position in the stream.
   */
  public function seek(
    int $offset,
    SeekWhence $whence = SeekWhence::SET,
  ): void;

  /**
   * Seek to the beginning of the stream.
   *
   * If the stream is not seekable, this method will raise an exception;
   * otherwise, it will perform a seek(0).
   */
  public function rewind(): void;

  /**
   * Returns the current position of the file read/write pointer
   *
   * @return int Position of the file pointer
   */
  public function tell(): int;
}

interface SeekableReadHandle
  extends ReadHandle, SeekableHandle {}

interface SeekableWriteHandle
  extends WriteHandle, SeekableHandle {}

interface DisposableSeekableWriteHandle
  extends SeekableWriteHandle, DisposableWriteHandle {}

interface DisposableSeekableReadHandle
  extends SeekableReadHandle, DisposableReadHandle {}

Hanlde::seek(int $offset, SeekWhence $whence = SeekWhence::SET): void :

  public function seek(
    int $offset,
    SeekWhence $whence = SeekWhence::SET,
  ): void {
    $meta = @\stream_get_meta_data($this->impl);

    if (!$meta['seekable']) {
      throw new Exception('Stream is not seekable');
    }

    $retval = @\fseek($this->impl, $offset, $whence as int);

    if ($retval === -1) {
      throw
        new Exception('Error seeking within stream');
    }
  }

Handle::rewind(): void

  public function rewind(): void {
    $this->seek(0);
  }

Handle::tell(): int :

  public function tell(): int {
    $result = @\ftell($this->impl);

    if (false === $result) {
      throw new Exception('Error occurred during tell operation');
    }

    return $result;
  }

We also currently have a separation between seeking for read and seeking for write. We're going to have to investigate portability of unifying them (we were hoping to implement them using fdup, but the result is non-portable). That includes testing the C behavior on platforms we don't currently support.

fixed in #68 #71