#include "dmlib.h"
#include <stdarg.h>

/* Implementation of strdup() with a NULL check
 */
char *dm_strdup(const char *s)
{
    char *res;
    if (s == NULL)
        return NULL;

    if ((res = dmMalloc(strlen(s) + 1)) == NULL)
        return NULL;

    strcpy(res, s);
    return res;
}


/* Implementation of strndup() with NULL check
 */
char *dm_strndup(const char *s, const size_t n)
{
    char *res;
    if (s == NULL)
        return NULL;

    size_t len = strlen(s);
    if (len > n)
        len = n;

    if ((res = dmMalloc(len + 1)) == NULL)
        return NULL;

    memcpy(res, s, len);
    res[len] = 0;

    return res;
}


/* Simulate a sprintf() that allocates memory
 */
char *dm_strdup_vprintf(const char *fmt, va_list args)
{
    int size = 64;
    char *buf;

    if ((buf = dmMalloc(size)) == NULL)
        return NULL;

    while (1)
    {
        int n;
        va_list ap;
        va_copy(ap, args);
        n = vsnprintf(buf, size, fmt, ap);
        va_end(ap);

        if (n > -1 && n < size)
            return buf;
        if (n > -1)
            size = n + 1;
        else
            size *= 2;

        if ((buf = dmRealloc(buf, size)) == NULL)
            return NULL;
    }
}


char *dm_strdup_printf(const char *fmt, ...)
{
    char *res;
    va_list ap;

    va_start(ap, fmt);
    res = dm_strdup_vprintf(fmt, ap);
    va_end(ap);

    return res;
}
