public function substring($start = 0, $length = null, $char = false)
    {
        if ($start !== 0) {
            $this->seek($start, true, $char);
        }

        $out = '';
        $to_end = is_null($length);

        /* If length is greater than remaining stream, use more efficient
         * algorithm below. Also, if doing a negative length, deal with that
         * below also. */
        if ($char &&
            $this->_utf8_char &&
            !$to_end &&
            ($length >= 0) &&
            ($length < ($this->length() - $this->pos()))) {
            while ($length-- && (($char = $this->getChar()) !== false)) {
                $out .= $char;
            }
            return $out;
        }

        if (!$to_end && ($length < 0)) {
            $pos = $this->pos();
            $this->end();
            $this->seek($length, true, $char);
            $length = $this->pos() - $pos;
            $this->seek($pos, false);
            if ($length < 0) {
                return '';
            }
        }

        while (!feof($this->stream) && ($to_end || $length)) {
            $read = fread($this->stream, $to_end ? 16384 : $length);
            $out .= $read;
            if (!$to_end) {
                $length -= strlen($read);
            }
        }

        return $out;
    }