/*
 * sbuf - Simple C string buffer implementation.
 * 
 * Forked from jgmenu/blob/master/src/sbuf.c
 * (original from https://github.com/johanmalm/jgmenu/blob/master/src/sbuf.c)
 * 
 * All modifications to the original source file are:
 * Copyright (C) 2021 Aitor Cuadrado Zubizarreta <aitor_czr@gnuinos.org>
 *
 * Original copyright and license text produced below.
 */

/*
 * sbuf.c
 * Simple C string buffer implementation.
 *
 * Copyright Johan Malm 2016
 *
 * The buffer is a byte array which is at least (len + 1) bytes in size.
 * The sbuf functions are designed too maintain/add '\0' at the end,
 * allowing the buffer to be used be used as a C string
 * (i.e. buf[len] == 0).
 *
 * sbuf_init allocates one byte so that the buffer can always be safely:
 *	- assumed to be a valid C string (i.e. buf != NULL)
 *	- freed (i.e. buf must not to point to memory on the stack)
 *
 * Example life cycle:
 *	sbuf_t s;
 *	sbuf_init(&s);
 *	sbuf_addch(&s, 'F');
 *	sbuf_addstr(&s, "oo");
 *	printf("%s\n", s.buf);
 *	free(s.buf);
 */

#include "sbuf.h"
#include <ctype.h>
#include <stdarg.h>

void sbuf_init(sbuf_t *s)
{
	s->buf = (char*)malloc(1);
	s->buf[0] = '\0';
	s->bufsiz = 1;
	s->len = 0;
}

void sbuf_addch(sbuf_t *s, char ch)
{
	if (s->bufsiz <= s->len + 1) {
		s->bufsiz = s->bufsiz * 2 + 16;
		s->buf = (char*)realloc(s->buf, s->bufsiz);
	}
	s->buf[s->len++] = ch;
	s->buf[s->len] = 0;
}

void sbuf_addstr(sbuf_t *s, const char *data)
{
	int len;

	if (!data)
		return;
	len = strlen(data);
	if (s->bufsiz <= s->len + len + 1) {
		s->bufsiz = s->bufsiz + len;
		s->buf = realloc(s->buf, s->bufsiz);
	}
	memcpy(s->buf + s->len, data, len);
	s->len += len;
	s->buf[s->len] = 0;
}

/**
 * \brief Variadic function
 */
void sbuf_concat(sbuf_t *s, int count, ...)
{
    va_list items;
	
    va_start(items, count);  /* Requires the last fixed parameter (to get the address) */
    
    while (count--)
    sbuf_addstr(s, va_arg(items, const char*));
	
    va_end(items);
}

void sbuf_free(sbuf_t *s)
{
	if (!s->buf) return;
	free(s->buf);
	s->buf = NULL;
}
