/*
 * QString Module
 *
 * Copyright (C) 2009 Red Hat Inc.
 *
 * Authors:
 *  Luiz Capitulino <lcapitulino@redhat.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 * See the COPYING.LIB file in the top-level directory.
 */

#include "qemu/osdep.h"
#include "qapi/qmp/qstring.h"

/**
 * qstring_new(): Create a new empty QString
 *
 * Return strong reference.
 */
QString *qstring_new(void)
{
    return qstring_from_str("");
}

/**
 * qstring_get_length(): Get the length of a QString
 */
size_t qstring_get_length(const QString *qstring)
{
    return qstring->length;
}

/**
 * qstring_from_substr(): Create a new QString from a C string substring
 *
 * Return string reference
 */
QString *qstring_from_substr(const char *str, size_t start, size_t end)
{
    QString *qstring;

    assert(start <= end);

    qstring = g_malloc(sizeof(*qstring));
    qobject_init(QOBJECT(qstring), QTYPE_QSTRING);

    qstring->length = end - start;
    qstring->capacity = qstring->length;

    assert(qstring->capacity < SIZE_MAX);
    qstring->string = g_malloc(qstring->capacity + 1);
    memcpy(qstring->string, str + start, qstring->length);
    qstring->string[qstring->length] = 0;

    return qstring;
}

/**
 * qstring_from_str(): Create a new QString from a regular C string
 *
 * Return strong reference.
 */
QString *qstring_from_str(const char *str)
{
    return qstring_from_substr(str, 0, strlen(str));
}

static void capacity_increase(QString *qstring, size_t len)
{
    if (qstring->capacity < (qstring->length + len)) {
        assert(len <= SIZE_MAX - qstring->capacity);
        qstring->capacity += len;
        assert(qstring->capacity <= SIZE_MAX / 2);
        qstring->capacity *= 2; /* use exponential growth */

        qstring->string = g_realloc(qstring->string, qstring->capacity + 1);
    }
}

/* qstring_append(): Append a C string to a QString
 */
void qstring_append(QString *qstring, const char *str)
{
    size_t len = strlen(str);

    capacity_increase(qstring, len);
    memcpy(qstring->string + qstring->length, str, len);
    qstring->length += len;
    qstring->string[qstring->length] = 0;
}

void qstring_append_int(QString *qstring, int64_t value)
{
    char num[32];

    snprintf(num, sizeof(num), "%" PRId64, value);
    qstring_append(qstring, num);
}

/**
 * qstring_append_chr(): Append a C char to a QString
 */
void qstring_append_chr(QString *qstring, int c)
{
    capacity_increase(qstring, 1);
    qstring->string[qstring->length++] = c;
    qstring->string[qstring->length] = 0;
}

/**
 * qstring_get_str(): Return a pointer to the stored string
 *
 * NOTE: Should be used with caution, if the object is deallocated
 * this pointer becomes invalid.
 */
const char *qstring_get_str(const QString *qstring)
{
    return qstring->string;
}

/**
 * qstring_get_try_str(): Return a pointer to the stored string
 *
 * NOTE: will return NULL if qstring is not provided.
 */
const char *qstring_get_try_str(const QString *qstring)
{
    return qstring ? qstring_get_str(qstring) : NULL;
}

/**
 * qobject_get_try_str(): Return a pointer to the corresponding string
 *
 * NOTE: the string will only be returned if the object is valid, and
 * its type is QString, otherwise NULL is returned.
 */
const char *qobject_get_try_str(const QObject *qstring)
{
    return qstring_get_try_str(qobject_to(QString, qstring));
}

/**
 * qstring_is_equal(): Test whether the two QStrings are equal
 */
bool qstring_is_equal(const QObject *x, const QObject *y)
{
    return !strcmp(qobject_to(QString, x)->string,
                   qobject_to(QString, y)->string);
}

/**
 * qstring_destroy_obj(): Free all memory allocated by a QString
 * object
 */
void qstring_destroy_obj(QObject *obj)
{
    QString *qs;

    assert(obj != NULL);
    qs = qobject_to(QString, obj);
    g_free(qs->string);
    g_free(qs);
}
