#ifndef MSTRING_H
#define MSTRING_H

#include "qemu/osdep.h"
#include "glib.h"

typedef struct {
    GString *gstr;
    int refcnt;
} MString;

static inline void mstring_ref(MString *mstr)
{
    mstr->refcnt++;
}

static inline void mstring_unref(MString *mstr)
{
    mstr->refcnt--;
    if (mstr->refcnt == 0) {
        g_string_free(mstr->gstr, true);
        g_free(mstr);
    }
}

G_DEFINE_AUTOPTR_CLEANUP_FUNC(MString, mstring_unref)

static inline MString *mstring_new(void)
{
    MString *mstr = g_malloc(sizeof(MString));
    mstr->refcnt = 1;
    mstr->gstr = g_string_new("");
    return mstr;
}

static inline MString *mstring_from_str(const char *str)
{
    MString *mstr = g_malloc(sizeof(MString));
    mstr->refcnt = 1;
    mstr->gstr = g_string_new(str);
    return mstr;
}

static inline __attribute__((format(printf, 1, 2))) MString *
mstring_from_fmt(const char *fmt, ...)
{
    MString *mstr = g_malloc(sizeof(MString));
    mstr->refcnt = 1;

    va_list args;
    va_start(args, fmt);
    // FIXME: Use g_string_new_take (GLib 2.78+)
    g_autofree gchar *str = g_strdup_vprintf(fmt, args);
    mstr->gstr = g_string_new(str);
    va_end(args);

    return mstr;
}

static inline void mstring_append(MString *mstr, const char *str)
{
    g_string_append(mstr->gstr, str);
}

static inline __attribute__((format(printf, 2, 3))) void
mstring_append_fmt(MString *mstr, const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    g_string_append_vprintf(mstr->gstr, fmt, args);
    va_end(args);
}

static inline const gchar *mstring_get_str(MString *mstr)
{
    return mstr->gstr->str;
}

static inline size_t mstring_get_length(MString *mstr)
{
    return mstr->gstr->len;
}

#endif
