static int s_input_stream_seek()

in source/io.c [620:672]


static int s_input_stream_seek(struct aws_input_stream *stream, int64_t offset, enum aws_stream_seek_basis basis) {
    struct aws_napi_input_stream_impl *impl = stream->impl;

    int result = AWS_OP_SUCCESS;
    uint64_t final_offset = 0;

    aws_mutex_lock(&impl->mutex);
    uint64_t total_bytes = impl->bytes_read + impl->buffer.len;

    switch (basis) {
        case AWS_SSB_BEGIN:
            /* Offset must be positive, must be greater than the bytes already read (because those
             * bytes are gone from the buffer), and must not be greater than the sum of the bytes
             * read so far and the size of the buffer
             */
            if (offset < 0 || (uint64_t)offset > total_bytes || (uint64_t)offset < impl->bytes_read) {
                result = aws_raise_error(AWS_IO_STREAM_INVALID_SEEK_POSITION);
                goto failed;
            }
            final_offset = (uint64_t)offset - impl->bytes_read;
            break;
        case AWS_SSB_END:
            /* Offset must be negative, and must not be trying to go further back than the
             * current length of the buffer, because those bytes have been purged
             */
            if (offset > 0 || offset == INT64_MIN || (uint64_t)(-offset) > impl->buffer.len) {
                result = aws_raise_error(AWS_IO_STREAM_INVALID_SEEK_POSITION);
                goto failed;
            }
            final_offset = (uint64_t)impl->buffer.len - (uint64_t)(-offset);
            break;
        default:
            result = aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
            goto failed;
    }

    AWS_ASSERT(final_offset <= SIZE_MAX);
    size_t buf_offset = (size_t)final_offset;
    AWS_ASSERT(buf_offset <= impl->buffer.len);

    if (buf_offset == impl->buffer.len) {
        impl->bytes_read += impl->buffer.len;
        impl->buffer.len = 0;
    } else if (buf_offset > 0) {
        size_t new_len = impl->buffer.len - buf_offset;
        memmove(impl->buffer.buffer, impl->buffer.buffer + buf_offset, new_len);
        impl->buffer.len = new_len;
    }

failed:
    aws_mutex_unlock(&impl->mutex);
    return result;
}