/*
 * QEMU generic buffers
 *
 * Copyright (c) 2015 Red Hat, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "qemu/osdep.h"
#include "qemu/host-utils.h"
#include "qemu/buffer.h"
#include "trace.h"

#define BUFFER_MIN_INIT_SIZE     4096
#define BUFFER_MIN_SHRINK_SIZE  65536

/* define the factor alpha for the exponential smoothing
 * that is used in the average size calculation. a shift
 * of 7 results in an alpha of 1/2^7. */
#define BUFFER_AVG_SIZE_SHIFT       7

static size_t buffer_req_size(Buffer *buffer, size_t len)
{
    return MAX(BUFFER_MIN_INIT_SIZE,
               pow2ceil(buffer->offset + len));
}

static void buffer_adj_size(Buffer *buffer, size_t len)
{
    size_t old = buffer->capacity;
    buffer->capacity = buffer_req_size(buffer, len);
    buffer->buffer = g_realloc(buffer->buffer, buffer->capacity);
    trace_buffer_resize(buffer->name ?: "unnamed",
                        old, buffer->capacity);

    /* make it even harder for the buffer to shrink, reset average size
     * to current capacity if it is larger than the average. */
    buffer->avg_size = MAX(buffer->avg_size,
                           buffer->capacity << BUFFER_AVG_SIZE_SHIFT);
}

void buffer_init(Buffer *buffer, const char *name, ...)
{
    va_list ap;

    va_start(ap, name);
    buffer->name = g_strdup_vprintf(name, ap);
    va_end(ap);
}

static uint64_t buffer_get_avg_size(Buffer *buffer)
{
    return buffer->avg_size >> BUFFER_AVG_SIZE_SHIFT;
}

void buffer_shrink(Buffer *buffer)
{
    size_t new;

    /* Calculate the average size of the buffer as
     * avg_size = avg_size * ( 1 - a ) + required_size * a
     * where a is 1 / 2 ^ BUFFER_AVG_SIZE_SHIFT. */
    buffer->avg_size *= (1 << BUFFER_AVG_SIZE_SHIFT) - 1;
    buffer->avg_size >>= BUFFER_AVG_SIZE_SHIFT;
    buffer->avg_size += buffer_req_size(buffer, 0);

    /* And then only shrink if the average size of the buffer is much
     * too big, to avoid bumping up & down the buffers all the time.
     * realloc() isn't exactly cheap ...  */
    new = buffer_req_size(buffer, buffer_get_avg_size(buffer));
    if (new < buffer->capacity >> 3 &&
        new >= BUFFER_MIN_SHRINK_SIZE) {
        buffer_adj_size(buffer, buffer_get_avg_size(buffer));
    }

    buffer_adj_size(buffer, 0);
}

void buffer_reserve(Buffer *buffer, size_t len)
{
    if ((buffer->capacity - buffer->offset) < len) {
        buffer_adj_size(buffer, len);
    }
}

gboolean buffer_empty(Buffer *buffer)
{
    return buffer->offset == 0;
}

uint8_t *buffer_end(Buffer *buffer)
{
    return buffer->buffer + buffer->offset;
}

void buffer_reset(Buffer *buffer)
{
    buffer->offset = 0;
    buffer_shrink(buffer);
}

void buffer_free(Buffer *buffer)
{
    trace_buffer_free(buffer->name ?: "unnamed", buffer->capacity);
    g_free(buffer->buffer);
    g_free(buffer->name);
    buffer->offset = 0;
    buffer->capacity = 0;
    buffer->buffer = NULL;
    buffer->name = NULL;
}

void buffer_append(Buffer *buffer, const void *data, size_t len)
{
    memcpy(buffer->buffer + buffer->offset, data, len);
    buffer->offset += len;
}

void buffer_advance(Buffer *buffer, size_t len)
{
    memmove(buffer->buffer, buffer->buffer + len,
            (buffer->offset - len));
    buffer->offset -= len;
    buffer_shrink(buffer);
}

void buffer_move_empty(Buffer *to, Buffer *from)
{
    trace_buffer_move_empty(to->name ?: "unnamed",
                            from->offset,
                            from->name ?: "unnamed");
    assert(to->offset == 0);

    g_free(to->buffer);
    to->offset = from->offset;
    to->capacity = from->capacity;
    to->buffer = from->buffer;

    from->offset = 0;
    from->capacity = 0;
    from->buffer = NULL;
}

void buffer_move(Buffer *to, Buffer *from)
{
    if (to->offset == 0) {
        buffer_move_empty(to, from);
        return;
    }

    trace_buffer_move(to->name ?: "unnamed",
                      from->offset,
                      from->name ?: "unnamed");
    buffer_reserve(to, from->offset);
    buffer_append(to, from->buffer, from->offset);

    g_free(from->buffer);
    from->offset = 0;
    from->capacity = 0;
    from->buffer = NULL;
}
