static apr_status_t hpack_read_bytes()

in buckets/hpack_buckets.c [1523:1593]


static apr_status_t hpack_read_bytes(serf_bucket_t *bucket,
                                     apr_size_t required,
                                     const void **data)
{
    serf_hpack_decode_ctx_t *ctx = bucket->data;
    apr_status_t status = APR_SUCCESS;
    apr_size_t len;
    const char *some_data;

    /* assert(required < ctx->buffer_used); */

    if (required == 0)
    {
        *data = ctx->buffer;
        return APR_SUCCESS;
    }

    if (!ctx->buffer_used)
    {
        status = serf_bucket_read(ctx->stream, required, &some_data, &len);

        if (SERF_BUCKET_READ_ERROR(status) || (len == required))
        {
            if (APR_STATUS_IS_EOF(status) && len == required)
                status = APR_SUCCESS;
            *data = some_data;
            return status;
        }

        hpack_decode_buffer_ensure(bucket, required);

        memcpy(ctx->buffer, some_data, len);
        ctx->buffer_used = len;

        if (status)
            return status;

          /* Fall through: Try to continue reading*/
    }
    else
    {
      /* Ensure that the buffer is large enough to hold everything */
        hpack_decode_buffer_ensure(bucket, required);
    }

    while (ctx->buffer_used < required)
    {
        status = serf_bucket_read(ctx->stream, required - ctx->buffer_used,
                                  &some_data, &len);

        if (SERF_BUCKET_READ_ERROR(status))
            return status;

        memcpy(ctx->buffer + ctx->buffer_used, some_data, len);
        ctx->buffer_used += len;

        if (status)
            break;
        else if (!status && !len)
            return SERF_ERROR_EMPTY_READ;
    }

    if (ctx->buffer_used == required)
    {
        *data = ctx->buffer;
        ctx->buffer_used = 0; /* Done with buffer */
        status = APR_SUCCESS;
    }

    return status;
}