protected function read($callback, $length = 1)
    {

        if (!is_callable($callback))
            throw new \InvalidArgumentException(
                "Argument 1 passed to peekWhile needs to be callback"
            );

        $result = '';
        while (!$this->isAtEnd() && $callback($this->peek($length))) {

            //Keep $_line and $_offset updated
            $newLines = $this->substr_count($this->lastPeekResult, "\n");
            $this->line += $newLines;

            if ($newLines) {

                if (strlen($this->lastPeekResult) === 1)
                    $this->offset = 0;
                else {

                    $parts = explode("\n", $this->lastPeekResult);
                    $this->offset = strlen($parts[count($parts) - 1]) - 1;
                }
            }

            $this->consume();
            $result .= $this->lastPeekResult;
        }

        return $result;
    }